Skip to content

Repository files navigation

ttsbot

Discord text-to-speech bot using OpenAI TTS and Discord voice playback.

Scope

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.

Requirements

  • 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

Configuration

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=info

DISCORD_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.

Install

npm install

The project uses native ESM and requires Node.js 26 or newer.

Run

npm start

The root entrypoint is ttsbot.mjs; it loads src/main.mjs, validates required environment variables, initializes the Discord client, and registers lifecycle handlers.

Commands

  • /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.

Behavior and state

  • 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_MS controls the PCM prebuffer (optional integer 0-1000, default: 200 ms).
  • HEALTH_PORT controls the local health server port (optional integer, default: 8080).
  • LOG_LEVEL controls logging verbosity (optional, default: info).
  • Word replacements are loaded from replacements.json and applied before TTS requests.
  • /leave, /skip, /stop, and process shutdown clean active playback and queues.

Logging and privacy

  • LOG_LEVEL=debug enables 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.

Development and validation

npm run lint
npm test
npm run test:gaps

Tests are under tests/. Tests use native ESM Jest and cover in-memory settings and resampler stream behavior.

Deployment with systemd

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 -f

After code or dependency changes:

sudo systemctl restart ttsbot.service

The service restarts on failure. Verify logs after restart. Roll back by restoring the previous repository revision, reinstalling dependencies, and restarting the service.

Security and operational notes

  • Keep .env outside version control and restrict its permissions, for example chmod 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) and GET /ready (Discord startup complete) on 0.0.0.0:HEALTH_PORT for Kubernetes probe access.

Project files

  • ttsbot.mjs — root entrypoint
  • src/main.mjs — startup and environment validation
  • src/discordClient.mjs — Discord commands, events, and shutdown
  • src/ttsEngine.mjs — TTS requests, queueing, resampling, and playback
  • src/healthServer.mjs — local health and readiness endpoints
  • src/settings.mjs — settings persistence
  • tests/ — focused automated tests
  • replacements.json — search/replace rules
  • ttsbot.service — systemd unit

License and support

This project is maintained for Eliware infrastructure. See package metadata and repository history for project ownership and changes.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages