diff --git a/.env.example b/.env.example index 87ddf19..d838b93 100644 --- a/.env.example +++ b/.env.example @@ -1,9 +1,16 @@ -# Discord Bot Token (from Discord Developer Portal) -DISCORD_TOKEN=your_discord_bot_token_here +# Discord Bot Configuration +# Copy this file to .env and fill in your values -# Channel ID to monitor for TTS messages -# Right-click the channel in Discord and copy ID (enable Developer Mode in settings) +# Your Discord bot token (from Discord Developer Portal) +DISCORD_TOKEN=your_bot_token_here + +# The text channel ID to monitor for messages +# (Right-click channel with Developer Mode enabled -> Copy ID) TEXT_CHANNEL_ID=123456789012345678 -# Path to the voice reference WAV file for voice cloning -VOICE_WAV_PATH=./voice.wav +# Directory containing voice .wav files +VOICES_DIR=./voices + +# Default voice name (optional - uses first found voice if not set) +# This should match the filename without .wav extension (case-insensitive) +# DEFAULT_VOICE=masterchief diff --git a/README.md b/README.md index a139090..527ea22 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,9 @@ A Discord bot that reads messages aloud using [Pocket TTS](https://github.com/ky - 📝 **Auto-read Messages**: Automatically reads all messages from a configured text channel - 🔊 **Voice Channel Streaming**: Streams generated audio to the voice channel where the message author is - 📋 **Message Queue**: Messages are queued and spoken in order +- 🔄 **Per-User Voice Selection**: Each user can choose their own TTS voice via `/voice` commands +- 💾 **Voice Persistence**: User voice preferences are saved and restored on restart +- 🔄 **Hot-reload Voices**: Add new voices without restarting the bot using `/voice refresh` ## Prerequisites @@ -75,12 +78,15 @@ A Discord bot that reads messages aloud using [Pocket TTS](https://github.com/ky ```env DISCORD_TOKEN=your_bot_token_here TEXT_CHANNEL_ID=123456789012345678 - VOICE_WAV_PATH=./voice.wav + VOICES_DIR=./voices + DEFAULT_VOICE=estinien ``` -5. **Add a voice reference file**: - - Place a WAV file named `voice.wav` in the project directory - - The file should contain 3-10 seconds of clear speech +5. **Add voice reference files**: + - Create a `voices/` directory: `mkdir voices` + - Place `.wav` files in the `voices/` directory + - Each file should contain 3-10 seconds of clear speech + - File names become voice names (e.g., `MasterChief.wav` → `/voice set masterchief`) - Higher quality audio = better voice cloning results ## Usage @@ -96,6 +102,12 @@ A Discord bot that reads messages aloud using [Pocket TTS](https://github.com/ky - The bot will join your voice channel and read your message aloud - Messages are queued if the bot is already speaking +3. **Voice Commands** (Slash Commands): + - `/voice list` - Shows all available voices + - `/voice set ` - Change your personal TTS voice + - `/voice current` - Shows your current voice + - `/voice refresh` - Re-scan for new voice files (no restart needed) + ## How It Works ``` @@ -106,8 +118,8 @@ A Discord bot that reads messages aloud using [Pocket TTS](https://github.com/ky ▲ │ ┌─────┴─────┐ - │ voice.wav │ - │ (speaker) │ + │ voices/ │ + │ per-user │ └───────────┘ ``` @@ -133,6 +145,95 @@ A Discord bot that reads messages aloud using [Pocket TTS](https://github.com/ky - Ensure the reference audio is clear with minimal background noise - Try a longer reference clip (5-10 seconds) +## Linux Server Deployment + +To run the bot as a service on a Linux server: + +### Quick Setup (Recommended) + +```bash +# Make the setup script executable +chmod +x setup_linux.sh + +# Run the setup script +./setup_linux.sh +``` + +The script will: +- Check system dependencies (Python 3.10+, FFmpeg, pip) +- Create a virtual environment and install dependencies +- Create `.env` template if needed +- Optionally install and configure the systemd service + +### Manual Setup + +1. **Install system dependencies**: + ```bash + # Ubuntu/Debian + sudo apt update + sudo apt install python3 python3-pip python3-venv ffmpeg + + # Fedora + sudo dnf install python3 python3-pip ffmpeg + + # Arch + sudo pacman -S python python-pip ffmpeg + ``` + +2. **Set up the project**: + ```bash + cd /path/to/PocketTTSBot + python3 -m venv venv + source venv/bin/activate + pip install -r requirements.txt + ``` + +3. **Configure the service**: + + Edit `pockettts.service` and replace: + - `YOUR_USERNAME` with your Linux username + - Update paths if your bot is not in `/home/YOUR_USERNAME/PocketTTSBot` + +4. **Install the service**: + ```bash + sudo cp pockettts.service /etc/systemd/system/ + sudo systemctl daemon-reload + sudo systemctl enable pockettts # Start on boot + sudo systemctl start pockettts # Start now + ``` + +### Service Management + +```bash +# Check status +sudo systemctl status pockettts + +# View logs (live) +journalctl -u pockettts -f + +# View recent logs +journalctl -u pockettts --since "1 hour ago" + +# Restart after changes +sudo systemctl restart pockettts + +# Stop the bot +sudo systemctl stop pockettts + +# Disable auto-start +sudo systemctl disable pockettts +``` + +### Updating the Bot + +```bash +cd /path/to/PocketTTSBot +git pull # If using git +source venv/bin/activate +pip install -r requirements.txt +sudo systemctl restart pockettts +``` + ## License MIT License diff --git a/setup_linux.sh b/setup_linux.sh new file mode 100644 index 0000000..e6b5aef --- /dev/null +++ b/setup_linux.sh @@ -0,0 +1,213 @@ +#!/bin/bash + +# Pocket TTS Discord Bot - Linux Setup Script +# This script helps set up the bot and install it as a systemd service + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo -e "${GREEN}========================================${NC}" +echo -e "${GREEN} Pocket TTS Discord Bot - Linux Setup${NC}" +echo -e "${GREEN}========================================${NC}" +echo + +# Get the directory where this script is located +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +USERNAME="$(whoami)" + +# Check if running as root +if [ "$EUID" -eq 0 ]; then + echo -e "${RED}Please do not run this script as root.${NC}" + echo "Run it as the user who will own the bot." + exit 1 +fi + +# Function to check if a command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +echo -e "${YELLOW}Step 1: Checking system dependencies...${NC}" + +# Check for Python 3.10+ +if command_exists python3; then + PYTHON_VERSION=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') + PYTHON_MAJOR=$(echo $PYTHON_VERSION | cut -d. -f1) + PYTHON_MINOR=$(echo $PYTHON_VERSION | cut -d. -f2) + + if [ "$PYTHON_MAJOR" -ge 3 ] && [ "$PYTHON_MINOR" -ge 10 ]; then + echo -e " ${GREEN}✓${NC} Python $PYTHON_VERSION found" + else + echo -e " ${RED}✗${NC} Python 3.10+ required, found $PYTHON_VERSION" + echo " Please install Python 3.10 or later" + exit 1 + fi +else + echo -e " ${RED}✗${NC} Python 3 not found" + echo " Please install Python 3.10 or later" + exit 1 +fi + +# Check for FFmpeg +if command_exists ffmpeg; then + FFMPEG_VERSION=$(ffmpeg -version 2>&1 | head -n1 | cut -d' ' -f3) + echo -e " ${GREEN}✓${NC} FFmpeg found ($FFMPEG_VERSION)" +else + echo -e " ${RED}✗${NC} FFmpeg not found" + echo "" + echo " Please install FFmpeg:" + echo " Ubuntu/Debian: sudo apt install ffmpeg" + echo " Fedora: sudo dnf install ffmpeg" + echo " Arch: sudo pacman -S ffmpeg" + exit 1 +fi + +# Check for pip +if command_exists pip3; then + echo -e " ${GREEN}✓${NC} pip3 found" +else + echo -e " ${RED}✗${NC} pip3 not found" + echo " Please install python3-pip" + exit 1 +fi + +echo +echo -e "${YELLOW}Step 2: Setting up virtual environment...${NC}" + +cd "$SCRIPT_DIR" + +if [ -d "venv" ]; then + echo " Virtual environment already exists" +else + echo " Creating virtual environment..." + python3 -m venv venv + echo -e " ${GREEN}✓${NC} Virtual environment created" +fi + +echo " Activating virtual environment..." +source venv/bin/activate + +echo " Installing dependencies..." +pip install --upgrade pip -q +pip install -r requirements.txt -q +echo -e " ${GREEN}✓${NC} Dependencies installed" + +echo +echo -e "${YELLOW}Step 3: Checking configuration...${NC}" + +# Check for .env file +if [ -f ".env" ]; then + echo -e " ${GREEN}✓${NC} .env file found" +else + echo -e " ${YELLOW}!${NC} .env file not found" + echo " Creating .env template..." + cat > .env << 'EOF' +# Discord Bot Configuration +DISCORD_TOKEN=your_bot_token_here +TEXT_CHANNEL_ID=your_channel_id_here + +# Voice Configuration +VOICES_DIR=./voices +# DEFAULT_VOICE=estinien +EOF + echo -e " ${YELLOW}!${NC} Please edit .env with your Discord token and channel ID" +fi + +# Check for voices directory +if [ -d "voices" ]; then + VOICE_COUNT=$(find voices -name "*.wav" 2>/dev/null | wc -l) + echo -e " ${GREEN}✓${NC} voices directory found ($VOICE_COUNT voice files)" + if [ "$VOICE_COUNT" -eq 0 ]; then + echo -e " ${YELLOW}!${NC} No voice files found. Add .wav files to the voices directory." + fi +else + echo " Creating voices directory..." + mkdir -p voices + echo -e " ${YELLOW}!${NC} Add voice .wav files to the voices directory" +fi + +echo +echo -e "${YELLOW}Step 4: Setting up systemd service...${NC}" + +read -p "Do you want to install the bot as a systemd service? (y/n) " -n 1 -r +echo +if [[ $REPLY =~ ^[Yy]$ ]]; then + # Create the service file with correct paths + SERVICE_FILE="/tmp/pockettts.service" + + cat > "$SERVICE_FILE" << EOF +[Unit] +Description=Pocket TTS Discord Bot +After=network-online.target +Wants=network-online.target + +[Service] +User=$USERNAME +Group=$USERNAME +WorkingDirectory=$SCRIPT_DIR +ExecStart=$SCRIPT_DIR/venv/bin/python bot.py +Restart=on-failure +RestartSec=10 +TimeoutStopSec=30 +StandardOutput=journal +StandardError=journal +SyslogIdentifier=pockettts + +# Security hardening +NoNewPrivileges=true +ProtectSystem=strict +ProtectHome=read-only +ReadWritePaths=$SCRIPT_DIR/voices +PrivateTmp=true + +[Install] +WantedBy=multi-user.target +EOF + + echo " Installing systemd service (requires sudo)..." + sudo cp "$SERVICE_FILE" /etc/systemd/system/pockettts.service + sudo systemctl daemon-reload + echo -e " ${GREEN}✓${NC} Service installed" + + read -p "Do you want to enable the service to start on boot? (y/n) " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + sudo systemctl enable pockettts + echo -e " ${GREEN}✓${NC} Service enabled for boot" + fi + + read -p "Do you want to start the service now? (y/n) " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + sudo systemctl start pockettts + echo -e " ${GREEN}✓${NC} Service started" + sleep 2 + echo + echo " Service status:" + sudo systemctl status pockettts --no-pager || true + fi +fi + +echo +echo -e "${GREEN}========================================${NC}" +echo -e "${GREEN} Setup Complete!${NC}" +echo -e "${GREEN}========================================${NC}" +echo +echo "Useful commands:" +echo " Start bot: sudo systemctl start pockettts" +echo " Stop bot: sudo systemctl stop pockettts" +echo " Restart bot: sudo systemctl restart pockettts" +echo " View status: sudo systemctl status pockettts" +echo " View logs: journalctl -u pockettts -f" +echo " Disable boot: sudo systemctl disable pockettts" +echo +echo "To run the bot manually (without systemd):" +echo " cd $SCRIPT_DIR" +echo " source venv/bin/activate" +echo " python bot.py" +echo