#!/usr/bin/env python3
"""Placeholder audio for a post's podcast and spoken-article versions.

Until the real versions are generated (e.g. with ElevenLabs), this renders
robot-voiced stand-ins with ffmpeg's flite speech synthesiser:

- a podcast from a "Speaker: line" transcript (one flite voice per speaker),
- a spoken article from plain text.

Both are written as MP3 and the script prints their durations in seconds.

Usage:
  python3 scripts/placeholder-audio.py podcast TRANSCRIPT.txt OUT.mp3
  python3 scripts/placeholder-audio.py spoken ARTICLE.txt OUT.mp3
Requires ffmpeg built with libflite and libmp3lame.
"""

import pathlib
import subprocess
import sys
import tempfile

VOICES = ["slt", "rms", "awb", "kal"]


def run(*args):
    subprocess.run(args, check=True, capture_output=True)


def say(text, voice, out):
    with tempfile.NamedTemporaryFile("w", suffix=".txt", delete=False) as f:
        f.write(text)
    run("ffmpeg", "-y", "-f", "lavfi", "-i", f"flite=textfile={f.name}:voice={voice}", "-ar", "22050", "-ac", "1", out)
    pathlib.Path(f.name).unlink()


def duration(path):
    out = subprocess.run(["ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "csv=p=0", path],
                         check=True, capture_output=True, text=True).stdout
    return round(float(out.strip()))


def build(segments, out):
    """segments: list of (text, voice). Joined with short pauses, encoded as MP3."""
    with tempfile.TemporaryDirectory() as tmp:
        silence = f"{tmp}/pause.wav"
        run("ffmpeg", "-y", "-f", "lavfi", "-i", "anullsrc=r=22050:cl=mono", "-t", "0.45", silence)
        parts = []
        for i, (text, voice) in enumerate(segments):
            wav = f"{tmp}/part{i:03d}.wav"
            say(text, voice, wav)
            parts += [wav, silence]
        listing = f"{tmp}/list.txt"
        pathlib.Path(listing).write_text("".join(f"file '{p}'\n" for p in parts))
        pathlib.Path(out).parent.mkdir(parents=True, exist_ok=True)
        run("ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", listing, "-codec:a", "libmp3lame", "-b:a", "64k", out)
    return duration(out)


def main():
    mode, source, out = sys.argv[1], sys.argv[2], sys.argv[3]
    text = pathlib.Path(source).read_text().strip()
    if mode == "podcast":
        voices, segments = {}, []
        for line in text.splitlines():
            if ":" not in line:
                continue
            speaker, said = (s.strip() for s in line.split(":", 1))
            voice = voices.setdefault(speaker, VOICES[len(voices) % len(VOICES)])
            segments.append((said, voice))
    else:
        segments = [(p.strip(), "slt") for p in text.split("\n\n") if p.strip()]
    print(build(segments, out))


if __name__ == "__main__":
    main()
