-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
551 additions
and
502 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# An env file can be used to in the working folder to set the environment variables | ||
|
||
MUMBLE_ADDRESS= | ||
MUMBLE_USERNAME= | ||
MUMBLE_PASSWORD= | ||
|
||
DISCORD_TOKEN= | ||
DISCORD_GID= | ||
DISCORD_CID= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.env | ||
main | ||
mumble-discord-bridge |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# syntax=docker/dockerfile:experimental | ||
|
||
# Stage 1 | ||
|
||
FROM golang:latest as builder | ||
WORKDIR /go/src/app | ||
COPY . . | ||
|
||
RUN go build -o mumble-discord-bridge -ldflags="-extldflags=-static" *.go | ||
|
||
# Stage 2 | ||
|
||
FROM alpine:latest as static | ||
WORKDIR /opt/ | ||
RUN apk add opus | ||
COPY --from=builder /go/src/app/mumble-discord-bridge . | ||
|
||
# Entry Point | ||
CMD ["/opt/mumble-discord-bridge"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
GOFILES=main.go mumble.go discord.go | ||
|
||
mumble-discord-bridge: $(GOFILES) | ||
go build -o $@ $(GOFILES) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,99 @@ | ||
# mumble-discord-bridge | ||
# Mumble Discord Bridge | ||
|
||
Mumble Discord Bridge is an open source Go application to bridge the audio between Mumble and Discord. | ||
|
||
It was built with the hope that people can continue to use the voice application of their choice. | ||
|
||
## Usage | ||
|
||
Several configuration variables must be set for the binary to function correctly. | ||
All variables can be set using flags or in the environment. | ||
The binary will also attempt to load .env file located in the working directory. | ||
|
||
```bash | ||
Usage of mumble-discord-bridge: | ||
-discord-cid string | ||
DISCORD_CID, discord cid | ||
-discord-gid string | ||
DISCORD_GID, discord gid | ||
-discord-token string | ||
DISCORD_TOKEN, discord bot token | ||
-mumble-address string | ||
MUMBLE_ADDRESS, mumble server address, example example.com | ||
-mumble-password string | ||
MUMBLE_PASSWORD, mumble password, optional | ||
-mumble-port int | ||
MUMBLE_PORT mumble port (default 64738) | ||
-mumble-username string | ||
MUMBLE_USERNAME, mumble username (default "discord-bridge") | ||
``` | ||
|
||
## Setup | ||
|
||
### Creating a Discord Bot | ||
|
||
A Discord bot is required to authenticate this application with Discord. | ||
The guide below provides information on how to setup a Discord bot. | ||
|
||
[Create a Discord Bot](https://discordpy.readthedocs.io/en/latest/discord.html) | ||
|
||
Individual Discord servers need to invite the bot before it can connect. | ||
|
||
### Binary | ||
|
||
Prebuilt binaries are available. | ||
|
||
```bash | ||
curl ... | ||
``` | ||
|
||
### Docker | ||
|
||
This project is built and distributed in a docker container. | ||
A sample docker command can be copied from below. | ||
This service command will always attempt to restart the service due to the `--restart=always` flag even when the server is restarted. | ||
For testing purposes it may be best to remove the restart flag. | ||
|
||
Replace the environment variables with variable for the desired mumble server, discord bot and discord server/channel. | ||
|
||
```bash | ||
# Sample for testing | ||
docker docker run -e MUMBLE_ADDRESS=example.com -e MUMBLE_PASSWORD=optional -e DISCORD_TOKEN=TOKEN -e DISCORD_GID=GID -e DISCORD_CID=CID stieneee/mumble-discord-bridge | ||
|
||
# Run as a service | ||
docker docker run -e MUMBLE_ADDRESS=example.com -e MUMBLE_PASSWORD=optional -e DISCORD_TOKEN=TOKEN -e DISCORD_GID=GID -e DISCORD_CID=CID --restart=always --name=mumble-discord-bridge -d stieneee/mumble-discord-bridge | ||
|
||
# Stop the service | ||
docker stop mumble-discord-bridge && docker rm mumble-discord-bridge | ||
``` | ||
|
||
## Building From Source | ||
|
||
This project requires Golang to build from source. | ||
A simple go build command is all that is needed. | ||
Ensure the opus library is installed. | ||
|
||
```bash | ||
go build *.go -o mumble-discord-bridge | ||
``` | ||
|
||
## Known Issues | ||
|
||
Currently there is an issue opening the discord voice channel. | ||
It is a known issue with a dependency of this project. | ||
|
||
## License | ||
|
||
Distributed under the MIT License. See LICENSE for more information. | ||
|
||
## Contributing | ||
|
||
Issues and PRs are welcome and encouraged. | ||
Please consider opening an issue to discuss features and ideas. | ||
|
||
## Acknowledgement | ||
|
||
The project would not have been possible without: | ||
|
||
- [gumble](https://github.com/layeh/gumble) | ||
- [discordgo](https://github.com/bwmarrin/discordgo) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"time" | ||
|
||
"github.com/bwmarrin/discordgo" | ||
"layeh.com/gopus" | ||
"layeh.com/gumble/gumble" | ||
_ "layeh.com/gumble/opus" | ||
) | ||
|
||
// OnError gets called by dgvoice when an error is encountered. | ||
// By default logs to STDERR | ||
var OnError = func(str string, err error) { | ||
prefix := "dgVoice: " + str | ||
|
||
if err != nil { | ||
os.Stderr.WriteString(prefix + ": " + err.Error()) | ||
} else { | ||
os.Stderr.WriteString(prefix) | ||
} | ||
} | ||
|
||
// SendPCM will receive on the provied channel encode | ||
// received PCM data into Opus then send that to Discordgo | ||
func discordSendPCM(v *discordgo.VoiceConnection, pcm <-chan []int16) { | ||
const channels int = 1 | ||
const frameRate int = 48000 // audio sampling rate | ||
const frameSize int = 960 // uint16 size of each audio frame | ||
const maxBytes int = (frameSize * 2) * 2 // max size of opus data | ||
|
||
streaming := false | ||
|
||
opusEncoder, err := gopus.NewEncoder(frameRate, channels, gopus.Audio) | ||
if err != nil { | ||
OnError("NewEncoder Error", err) | ||
return | ||
} | ||
|
||
ticker := time.NewTicker(20 * time.Millisecond) | ||
|
||
for { | ||
<-ticker.C | ||
|
||
if len(pcm) > 1 { | ||
if !streaming { | ||
v.Speaking(true) | ||
streaming = true | ||
} | ||
|
||
r1 := <-pcm | ||
r2 := <-pcm | ||
|
||
// try encoding pcm frame with Opus | ||
opus, err := opusEncoder.Encode(append(r1, r2...), frameSize, maxBytes) | ||
if err != nil { | ||
OnError("Encoding Error", err) | ||
return | ||
} | ||
|
||
if v.Ready == false || v.OpusSend == nil { | ||
OnError(fmt.Sprintf("Discordgo not ready for opus packets. %+v : %+v", v.Ready, v.OpusSend), nil) | ||
return | ||
} | ||
|
||
v.OpusSend <- opus | ||
} else { | ||
if streaming { | ||
v.Speaking(false) | ||
streaming = false | ||
} | ||
} | ||
} | ||
} | ||
|
||
// ReceivePCM will receive on the the Discordgo OpusRecv channel and decode | ||
// the opus audio into PCM then send it on the provided channel. | ||
func discordReceivePCM(v *discordgo.VoiceConnection, toMumble chan gumble.AudioBuffer) { | ||
var err error | ||
speakers := make(map[uint32]*gopus.Decoder) | ||
|
||
for { | ||
if v.Ready == false || v.OpusRecv == nil { | ||
OnError(fmt.Sprintf("Discordgo not to receive opus packets. %+v : %+v", v.Ready, v.OpusSend), nil) | ||
return | ||
} | ||
|
||
p, ok := <-v.OpusRecv | ||
if !ok { | ||
fmt.Println("Opus not ok") | ||
return | ||
} | ||
|
||
_, ok = speakers[p.SSRC] | ||
if !ok { | ||
speakers[p.SSRC], err = gopus.NewDecoder(48000, 1) | ||
if err != nil { | ||
OnError("error creating opus decoder", err) | ||
continue | ||
} | ||
} | ||
|
||
p.PCM, err = speakers[p.SSRC].Decode(p.Opus, 960, false) | ||
if err != nil { | ||
OnError("Error decoding opus data", err) | ||
continue | ||
} | ||
|
||
toMumble <- p.PCM[0:480] | ||
toMumble <- p.PCM[480:960] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module github.com/stieneee/mumble-discord-bridge | ||
|
||
go 1.15 | ||
|
||
require ( | ||
github.com/bwmarrin/discordgo v0.22.0 | ||
github.com/joho/godotenv v1.3.0 | ||
layeh.com/gopus v0.0.0-20161224163843-0ebf989153aa | ||
layeh.com/gumble v0.0.0-20200818122324-146f9205029b | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
github.com/bwmarrin/discordgo v0.22.0 h1:uBxY1HmlVCsW1IuaPjpCGT6A2DBwRn0nvOguQIxDdFM= | ||
github.com/bwmarrin/discordgo v0.22.0/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M= | ||
github.com/dchote/go-openal v0.0.0-20171116030048-f4a9a141d372 h1:tz3KnXWtRZR0RWOfcMNOw+HHezWLQa7vfSOWTtKjchI= | ||
github.com/dchote/go-openal v0.0.0-20171116030048-f4a9a141d372/go.mod h1:74z+CYu2/mx4N+mcIS/rsvfAxBPBV9uv8zRAnwyFkdI= | ||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= | ||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= | ||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= | ||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= | ||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= | ||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 h1:y6ce7gCWtnH+m3dCjzQ1PCuwl28DDIc3VNnvY29DlIA= | ||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= | ||
layeh.com/gopus v0.0.0-20161224163843-0ebf989153aa h1:WNU4LYsgD2UHxgKgB36mL6iMAMOvr127alafSlgBbiA= | ||
layeh.com/gopus v0.0.0-20161224163843-0ebf989153aa/go.mod h1:AOef7vHz0+v4sWwJnr0jSyHiX/1NgsMoaxl+rEPz/I0= | ||
layeh.com/gumble v0.0.0-20200818122324-146f9205029b h1:Kne6wkHqbqrygRsqs5XUNhSs84DFG5TYMeCkCbM56sY= | ||
layeh.com/gumble v0.0.0-20200818122324-146f9205029b/go.mod h1:tWPVA9ZAfImNwabjcd9uDE+Mtz0Hfs7a7G3vxrnrwyc= |
Oops, something went wrong.