Home
Relevant source files
The following files were used as context for generating this wiki page:The Discord Live Translator is a bot designed to automatically translate voice chat within a Discord channel into a user-selectable language. Its primary purpose is to facilitate real-time communication between individuals who speak different languages. The system is architected as a set of microservices, orchestrated by a central Node.js bot application, to handle audio processing, speech-to-text, translation, and text-to-speech.
This document provides a high-level overview of the project's architecture, core functionalities, and configuration. It details the flow of data from a user speaking in a voice channel to the final translated audio being played back.
Sources: README.md
System Architecture
The application is composed of several containerized services managed via Docker Compose. This microservice architecture separates concerns, allowing each component to handle a specific part of the translation pipeline.
The following diagram illustrates the high-level service architecture.
This diagram shows the interaction between the main services defined in the production Docker Compose file.
Sources: docker-compose.prod.yml
Service Components
| Service | Image | Description |
|---|---|---|
bot | ghcr.io/wotschofsky/discord-live-translator | The main bot application. It connects to Discord, manages voice connections, and orchestrates the translation pipeline by communicating with other services. |
stt | ghcr.io/wotschofsky/discord-live-translator/stt | A Rust-based Speech-to-Text service that uses the Whisper model to transcribe audio files. |
libretranslate | libretranslate/libretranslate:v1.3.11 | A self-hosted translation service. It receives text and returns its translation in a specified language. |
redis | redis:alpine | A Redis instance used for caching and storing user settings, such as their selected target language. |
Sources: docker-compose.prod.yml, src/env.ts:15-17
Core Translation Workflow
The central feature of the bot is its ability to process live voice audio and return a translated version. This process is initiated when a user with translation enabled speaks in a voice channel where the bot is present.
The sequence diagram below outlines the entire process from audio capture to translated playback.
This diagram shows the step-by-step process of capturing, transcribing, translating, and synthesizing voice.
Sources: src/commands/join.ts:90-107, src/processors/recordAudio.ts, src/processors/recognizeRecording.ts, src/processors/readText.ts
Workflow Steps
-
Audio Recording: When a user starts speaking, the
speakingevent is triggered. TherecordAudioprocessor subscribes to the user's voice stream, decodes the Opus packets, and writes the raw audio to a.wavfile. The recording ends after a 100ms silence.
Sources: src/commands/join.ts:92, src/processors/recordAudio.ts:30-33 -
Speech-to-Text (STT): The
recognizeRecordingprocessor sends the.wavfile to theSTT_HOST. The STT service, built in Rust, useswhisper-rsto transcribe the audio into text and returns the result.
Sources: src/processors/recognizeRecording.ts:10-16, stt/src/main.rs:38-48 -
Translation: If the user's target language is not English, the transcribed text is sent to the
TRANSLATION_HOST(LibreTranslate) for translation.
Sources: src/commands/join.ts:102-104 -
Text-to-Speech (TTS): The
readTextprocessor takes the final (translated or original) text and invokes a Python script (read_text.py) to generate a new.wavfile using a pre-trained TTS model.
Sources: src/processors/readText.ts:14-17 -
Audio Playback: The path to the generated TTS audio file is added to the
audioQueue. The queue plays the audio back into the voice channel through the bot's voice connection. The queue ensures that multiple audio clips are played sequentially without overlapping.
Sources: src/processors/readText.ts:19, src/utils/AudioQueue.ts:63-67
Bot Initialization and Command Handling
The bot's entry point is src/app.ts. It initializes the Discord client, logs in, and sets up listeners for events, primarily interactionCreate for handling slash commands.
Sources: src/app.ts
Command Routing
When a user executes a slash command, the interactionCreate event is fired. The application routes the interaction to the appropriate command handler based on the commandName.
This diagram shows how incoming interactions are routed to the correct handler function.
Sources: src/app.ts:19-45
Slash Commands
The bot's functionality is exposed through a set of slash commands. These commands are defined in the src/commands directory and registered with Discord's API.
| Command | Description | Handler File |
|---|---|---|
/join | Move the bot into your voice channel. | src/commands/join.ts |
/leave | Move the bot out of your voice channel. | src/commands/leave.ts |
/start <target> | Start the translation for yourself. | src/commands/start.ts |
/stop | Stop the translation. | src/commands/stop.ts |
/status | Show your current settings. | src/commands/status.ts |
/languages | Show all available languages. | src/commands/languages.ts |
Commands can be deployed globally using pnpm run deploy or for a specific guild on startup if GUILD_ID is set.
Sources: README.md:10-20, src/app.ts:29-45, src/interactions.ts:13-19, src/deploy.ts
Configuration
The application is configured using environment variables, which are validated at runtime using Zod.
Sources: src/env.ts
Environment Variables
| Variable | Description | Type | Required |
|---|---|---|---|
BOT_TOKEN | The Discord bot token. | string | Yes |
CLIENT_ID | The Discord application client ID. | string | No |
GUILD_ID | The Discord server ID for auto-deploying guild commands. | string | No |
LOG_PATH | Optional file path for logging. | string | No |
POSTHOG_API_KEY | API key for PostHog analytics. | string | No |
REDIS_URL | Connection URL for the Redis instance. | string | No |
STT_HOST | URL for the Speech-to-Text service. | string | Yes |
TRANSLATION_HOST | URL for the translation service. | string | Yes |
HEARTBEAT_URL | URL to send a heartbeat to for uptime monitoring. | string (url) | No |
Sources: src/env.ts:10-21