← back to AgentAbrams

podcast/tts_engine.py

75 lines

#!/usr/bin/env python3
"""
podcast/tts_engine.py — TTS wrapper for podcast audio generation.

Reuses the same ElevenLabs API as video TTS but with podcast-optimized settings.

Usage:
    python3 podcast/tts_engine.py <script.txt> <output.mp3>

Environment variables:
    ELEVEN_API_KEY
    ELEVEN_VOICE_ID (optional)
"""

import os
import sys
from pathlib import Path

import requests

DEFAULT_VOICE_ID = "pNInz6obpgDQGcFmaJgB"  # Adam


def generate_podcast_audio(text: str, output_file: str):
    api_key = os.environ.get("ELEVEN_API_KEY")
    if not api_key:
        print("ERROR: ELEVEN_API_KEY not set", file=sys.stderr)
        sys.exit(1)

    voice_id = os.environ.get("ELEVEN_VOICE_ID", DEFAULT_VOICE_ID)
    url = f"https://api.elevenlabs.io/v1/text-to-speech/{voice_id}"

    headers = {
        "xi-api-key": api_key,
        "Content-Type": "application/json",
    }

    payload = {
        "text": text,
        "model_id": "eleven_monolingual_v1",
        "voice_settings": {
            "stability": 0.70,
            "similarity_boost": 0.65,
            "style": 0.2,
        },
    }

    resp = requests.post(url, json=payload, headers=headers, timeout=180)
    resp.raise_for_status()

    with open(output_file, "wb") as f:
        f.write(resp.content)

    print(f"Podcast audio generated: {output_file} ({len(resp.content) / 1024:.0f} KB)")


def main():
    if len(sys.argv) < 3:
        print("Usage: tts_engine.py <script_file_or_text> <output.mp3>", file=sys.stderr)
        sys.exit(2)

    source = sys.argv[1]
    output = sys.argv[2]

    if Path(source).is_file():
        text = Path(source).read_text(encoding="utf-8")
    else:
        text = source

    generate_podcast_audio(text, output)


if __name__ == "__main__":
    main()