docs: Update README and add Linux setup script
Improve documentation and add a setup script for easy deployment on Linux systems. - Update README.md with instructions for the new multi-voice slash commands and the oices/ directory structure. - Add a comprehensive 'Linux Server Deployment' section to the README, detailing both a quick setup via a new script and a manual systemd service setup. - Create setup_linux.sh to automate dependency checking, virtual environment creation, and service installation on Linux. - Revise comments in .env.example for clarity and to reflect the latest configuration options.
This commit is contained in:
19
.env.example
19
.env.example
@@ -1,9 +1,16 @@
|
|||||||
# Discord Bot Token (from Discord Developer Portal)
|
# Discord Bot Configuration
|
||||||
DISCORD_TOKEN=your_discord_bot_token_here
|
# Copy this file to .env and fill in your values
|
||||||
|
|
||||||
# Channel ID to monitor for TTS messages
|
# Your Discord bot token (from Discord Developer Portal)
|
||||||
# Right-click the channel in Discord and copy ID (enable Developer Mode in settings)
|
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
|
TEXT_CHANNEL_ID=123456789012345678
|
||||||
|
|
||||||
# Path to the voice reference WAV file for voice cloning
|
# Directory containing voice .wav files
|
||||||
VOICE_WAV_PATH=./voice.wav
|
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
|
||||||
|
|||||||
113
README.md
113
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
|
- 📝 **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
|
- 🔊 **Voice Channel Streaming**: Streams generated audio to the voice channel where the message author is
|
||||||
- 📋 **Message Queue**: Messages are queued and spoken in order
|
- 📋 **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
|
## Prerequisites
|
||||||
|
|
||||||
@@ -75,12 +78,15 @@ A Discord bot that reads messages aloud using [Pocket TTS](https://github.com/ky
|
|||||||
```env
|
```env
|
||||||
DISCORD_TOKEN=your_bot_token_here
|
DISCORD_TOKEN=your_bot_token_here
|
||||||
TEXT_CHANNEL_ID=123456789012345678
|
TEXT_CHANNEL_ID=123456789012345678
|
||||||
VOICE_WAV_PATH=./voice.wav
|
VOICES_DIR=./voices
|
||||||
|
DEFAULT_VOICE=estinien
|
||||||
```
|
```
|
||||||
|
|
||||||
5. **Add a voice reference file**:
|
5. **Add voice reference files**:
|
||||||
- Place a WAV file named `voice.wav` in the project directory
|
- Create a `voices/` directory: `mkdir voices`
|
||||||
- The file should contain 3-10 seconds of clear speech
|
- 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
|
- Higher quality audio = better voice cloning results
|
||||||
|
|
||||||
## Usage
|
## 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
|
- The bot will join your voice channel and read your message aloud
|
||||||
- Messages are queued if the bot is already speaking
|
- Messages are queued if the bot is already speaking
|
||||||
|
|
||||||
|
3. **Voice Commands** (Slash Commands):
|
||||||
|
- `/voice list` - Shows all available voices
|
||||||
|
- `/voice set <name>` - 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
|
## How It Works
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -106,8 +118,8 @@ A Discord bot that reads messages aloud using [Pocket TTS](https://github.com/ky
|
|||||||
▲
|
▲
|
||||||
│
|
│
|
||||||
┌─────┴─────┐
|
┌─────┴─────┐
|
||||||
│ voice.wav │
|
│ voices/ │
|
||||||
│ (speaker) │
|
│ 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
|
- Ensure the reference audio is clear with minimal background noise
|
||||||
- Try a longer reference clip (5-10 seconds)
|
- 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
|
## License
|
||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|||||||
213
setup_linux.sh
Normal file
213
setup_linux.sh
Normal file
@@ -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
|
||||||
Reference in New Issue
Block a user