Discord text-to-speech bot using OpenAI TTS and Discord voice playback.
The bot joins a Discord voice channel, links the current text channel, and speaks new messages from that channel. Speech is queued FIFO, converted from OpenAI 24 kHz mono PCM to Discord-compatible 48 kHz stereo PCM, and played in the voice channel.
- Node.js 26 or newer
- Discord application/bot token
- OpenAI API key
- Discord server where the bot can:
- View channels and read message history
- Read message content
- Connect to and speak in voice channels
- Use slash commands
Copy .env.example to .env and set:
DISCORD_CLIENT_ID=your_discord_application_client_id_hereDISCORD_TOKEN=your_discord_bot_token_hereOPENAI_API_KEY=your_openai_api_key_hereHEALTH_PORT=8080LOG_LEVEL=infoDISCORD_CLIENT_ID identifies the Discord application and is not secret. DISCORD_TOKEN and OPENAI_API_KEY are required secrets. Never commit .env, tokens, or API keys. Configuration is loaded at startup and is not logged.
npm installThe project uses native ESM and requires Node.js 26 or newer.
npm startThe root entrypoint is ttsbot.mjs; it loads src/main.mjs, validates required environment variables, initializes the Discord client, and registers lifecycle handlers.
/help— show basic usage/join— join your current voice channel and link the current text channel/leave— leave voice and clear guild state/voice <voice>— set your TTS voice/skip— skip the current message/stop— stop playback and clear the queue
Available voices are defined in src/discordClient.mjs and exposed as /voice choices.
- Only messages in the linked text channel are spoken.
- Bot-authored messages are ignored.
- Messages longer than 2,000 characters are ignored.
- Messages are queued FIFO per guild.
- Users without settings receive an automatically assigned voice on first use.
- Settings are kept in memory and reset when the process restarts.
TTS_JITTER_BUFFER_MScontrols the PCM prebuffer (optional integer 0-1000, default: 200 ms).HEALTH_PORTcontrols the local health server port (optional integer, default: 8080).LOG_LEVELcontrols logging verbosity (optional, default: info).- Word replacements are loaded from
replacements.jsonand applied before TTS requests. /leave,/skip,/stop, and process shutdown clean active playback and queues.
LOG_LEVEL=debugenables detailed Discord, queue, OpenAI timing, playback, retry, and buffer logs.- Logs include operational IDs, lengths, statuses, and timings; message text and audio are not logged.
- API keys and tokens are not logged. Avoid enabling debug logs permanently in production because IDs and timing data increase log volume.
npm run lint
npm test
npm run test:gapsTests are under tests/. Tests use native ESM Jest and cover in-memory settings and resampler stream behavior.
The included ttsbot.service runs the bot from /opt/ttsbot using /opt/ttsbot/.env:
sudo systemctl enable --now ttsbot.service
sudo systemctl status ttsbot.service
journalctl -u ttsbot.service -fAfter code or dependency changes:
sudo systemctl restart ttsbot.serviceThe service restarts on failure. Verify logs after restart. Roll back by restoring the previous repository revision, reinstalling dependencies, and restarting the service.
- Keep
.envoutside version control and restrict its permissions, for examplechmod 600 .env. - The bot requires the Discord Message Content privileged intent; enable it in the Discord Developer Portal.
- Use the minimum Discord permissions required for the bot.
- Do not expose logs containing message content, credentials, or full API responses.
- Runtime settings are local mutable state; back them up only if preserving user preferences is required.
- The local HTTP health server exposes
GET /health(process alive) andGET /ready(Discord startup complete) on0.0.0.0:HEALTH_PORTfor Kubernetes probe access.
ttsbot.mjs— root entrypointsrc/main.mjs— startup and environment validationsrc/discordClient.mjs— Discord commands, events, and shutdownsrc/ttsEngine.mjs— TTS requests, queueing, resampling, and playbacksrc/healthServer.mjs— local health and readiness endpointssrc/settings.mjs— settings persistencetests/— focused automated testsreplacements.json— search/replace rulesttsbot.service— systemd unit
This project is maintained for Eliware infrastructure. See package metadata and repository history for project ownership and changes.