Skip to content

A Linux-based audio bridge that connects Discord voice channels to SRT streams (egress) and injects web-based overlay audio (ingress) using Headless Chrome and Pipewire.

License

Notifications You must be signed in to change notification settings

viruslox/VLX_AudioBridge

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

105 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

VLX_AudioBridge

VLX_AudioBridge (formerly Ermete) is a bi-directional audio gateway designed for Linux servers. It bridges the gap between Discord voice channels, web-based overlays, and streaming protocols (SRT). It allows you to inject audio from web sources (overlays) into Discord and simultaneously extract, mix, and stream Discord voice chat to an external media server via SRT.

NOTE:

The idea, the logics, the architecture, reviews, validation are made in VirusLox, but the code is 95% generated by Gemini.

Architecture

The bridge operates in two concurrent directions:

  1. Ingress (Overlay -> Discord):

    • Spawns headless Chromium instances for configured overlay URLs.
    • Routes browser audio to a dedicated Pipewire Virtual Sink.
    • Captures audio via PortAudio, encodes it to Opus, and streams it to the Discord voice channel.
  2. Egress (Discord -> SRT Stream):

    • Captures incoming Opus packets from Discord users.
    • Mixes audio streams in real-time.
    • Filters out specific users (e.g., the bot itself or admin accounts) based on configuration.
    • Pipes the mixed PCM audio to FFmpeg for encoding and SRT transmission.

Structure

VLX_AudioBridge/
├── main.go              # Entry point: config load, bot init, system checks
├── AudioBridge.yaml     # Centralized configuration
├── internal/
│   ├── config/
│   │   └── config.go            # YAML Config Parser
│   ├── bot/
│   │   └── bot.go               # Discord session, commands (join/leave/shutdown)
│   ├── stream/                  # [Discord -> SRT]
│   │   ├── packet_handler.go    # Opus packet receiver and SSRC handling
│   │   ├── mixer.go             # PCM Soft-Clipping Mixer
│   │   └── ffmpeg_srt.go        # FFmpeg process wrapper (stdin pipe)
│   ├── overlay/                 # [Overlay -> Discord]
│   │   ├── browser_manager.go   # Headless Chromium manager
│   │   └── audio_capture.go     # PortAudio capture from Pipewire Monitor
│   └── system/
│       └── pipewire.go          # Virtual Sink automation (pactl/pw-cli)
├── scripts/
│   └── vlx_audiobridge.service  # Systemd User Unit file
├── go.mod                       # Go Dependencies
├── go.sum                       # Dependencies Checksum
└── README.md

System Requirements

  • OS: Linux (Tested on Debian).
  • Audio System: Pipewire (with pipewire-pulse).
  • Dependencies: Go 1.20+, FFmpeg, Chromium Browser, PortAudio & Opus dev libraries.

Install Dependencies

sudo apt update
sudo apt install git golang ffmpeg chromium-browser portaudio19-dev libopus-dev libopusfile-dev pulseaudio-utils

Installation & Build

Clone the repository:

mkdir -p ~/go/src/ && cd ~/go/src/
git clone https://github.com/viruslox/VLX_AudioBridge.git
cd VLX_AudioBridge

Initialize and Tidy Modules:

go mod init
go mod edit -replace github.com/bwmarrin/discordgo=github.com/ozraru/discordgo@master
go mod tidy

Build the Binary:

go build

Deploy to /opt

I hate "sudo", but let's make it easy:

sudo mkdir -p /opt/VLX_AudioBridge

# Ensure your user owns the directory
sudo chown -R $USER:$USER /opt/VLX_AudioBridge
cp ~/go/src/VLX_AudioBridge/VLX_AudioBridge /opt/VLX_AudioBridge/

# Copy config the example, but remember to edit it
cp ~/go/src/VLX_AudioBridge/AudioBridge.yaml /opt/VLX_AudioBridge/

Configuration

The application uses a YAML configuration file. Edit /opt/VLX_AudioBridge/AudioBridge.yaml. Example:

discord:
  token: "YOUR_DISCORD_BOT_TOKEN"
  prefix: "vlx."       # Discord commands prefix
  guild_id: ""         # Optional: Restrict to specific Guild ID

streaming:
  # SRT Destination (e.g., MediaMTX) # mode=caller to enable "us" as media sender
  destination_url: "srt://127.0.0.1:8890?streamid=publish:vlx_audio&mode=caller&pkt_size=1316"
  bitrate: "128k" # Audio output Bitrate for FFmpeg
  # List of Discord User IDs to exclude from the SRT stream (Max 2)
  excluded_users:
    - "123456789012345678"

overlays:
  # List of Web Overlay URLs to load and inject into Discord (Max 3)
  urls:
    - "https://stream-elements.com/overlay/"
    - "https://another-overlay.com/"
    # - "https://tuo-overlay-3.com"

Usage

Manual Run

NOTE: Ensure your Pipewire session is active.

/opt/VLX_AudioBridge/
export XDG_RUNTIME_DIR=/run/user/$(id -u)
./VLX_AudioBridge

Discord Commands

vlx.join : Joins the user's voice channel, starts the SRT stream, and launches overlay browsers.

vlx.leave: Stops streaming, closes browsers, and disconnects from the voice channel.

vlx.shutdown: Gracefully shuts down the entire bridge process.

Running as a Service (Systemd)

mkdir -p ~/.config/systemd/user/
cp ~/go/src/VLX_AudioBridge/scripts/vlx_audiobridge.service ~/.config/systemd/user/

Edit ~/.config/systemd/user/vlx_audiobridge.service - at least configure "your user".

[Unit]
Description=VLX AudioBridge Service
After=network.target sound.target pipewire.service
Requires=pipewire.service

[Service]
Type=simple
ExecStart=/opt/VLX_AudioBridge/VLX_AudioBridge
WorkingDirectory=/opt/VLX_AudioBridge/
Restart=always
RestartSec=5
# Ensure XDG_RUNTIME_DIR is set for Pipewire access
Environment=XDG_RUNTIME_DIR=/run/user/%U

[Install]
WantedBy=default.target

Enable and Start:

systemctl --user daemon-reload
systemctl --user enable vlx_audiobridge.service
systemctl --user start vlx_audiobridge.service

Check Logs:

journalctl --user -u vlx_audiobridge.service -f

Troubleshooting

"Virtual Sink not found": Ensure pipewire-pulse is running. The application attempts to create VLX_VirtualSink automatically using pactl. Chromium Audio Issues: Check if the PULSE_SINK environment variable is correctly respected by your Chromium version. FFmpeg Errors: Ensure FFmpeg is installed and accessible in the system $PATH. Opus/CGO Errors: Ensure libopus-dev and portaudio19-dev are installed.

License

This project is licensed under the GNU General Public License v3.0. See the LICENSE file for details.

About

A Linux-based audio bridge that connects Discord voice channels to SRT streams (egress) and injects web-based overlay audio (ingress) using Headless Chrome and Pipewire.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages