# -*- coding: utf-8 -*-
"""blog-elevenlabs-ses-klonlama — ses klonu için kaydı yüklemeden önce ölçen kontrol betiği (ffmpeg gerekir).

Kullanım:
  python -X utf8 blog-elevenlabs-ses-klonlama.py kayit.wav     → kaydı ölçer
  python -X utf8 blog-elevenlabs-ses-klonlama.py               → sentetik öz-test (3 sn ton + 2 sn sessizlik)
Ölçülenler: süre, tümleşik ses yüksekliği (LUFS) ve gerçek tepe (ebur128), RMS ve gürültü tabanı (astats),
1 saniyeden uzun sessizlikler (silencedetect, -50 dB). Sonuç, ElevenLabs belgesindeki önerilerle karşılaştırılır:
Instant Voice Cloning en az 1 dk, 1–2 dk önerilir, 3 dk üstüne çıkmayın; RMS -23 ile -18 dB, gerçek tepe -3 dB;
Professional Voice Cloning 30–180 dk.
Kaynaklar (18 Ekim 2026): https://elevenlabs.io/docs/eleven-creative/voices/voice-cloning
                          https://elevenlabs.io/docs/eleven-creative/voices/voice-cloning/instant-voice-cloning
"""
import re
import subprocess
import sys
import tempfile
from pathlib import Path


def ffmpeg(*a):
    return subprocess.run(["ffmpeg", "-hide_banner", *a], capture_output=True, text=True).stderr


def olc(yol):
    sure = float(subprocess.run(["ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "default=nw=1:nk=1", str(yol)],
                                capture_output=True, text=True).stdout.strip())
    e = ffmpeg("-i", str(yol), "-af", "ebur128=peak=true", "-f", "null", "-")
    lufs = re.findall(r"I:\s+(-?[\d.]+) LUFS", e)
    gtepe = re.findall(r"Peak:\s+(-?[\d.]+|-inf) dBFS", e)
    a = ffmpeg("-i", str(yol), "-af", "astats=measure_overall=Peak_level+RMS_level+Noise_floor:measure_perchannel=none,"
               "silencedetect=noise=-50dB:d=1", "-f", "null", "-")
    deger = lambda ad: (re.findall(ad + r" dB: (-?[\d.]+|-inf)", a) or ["?"])[-1]
    sessiz = [float(x) for x in re.findall(r"silence_duration: ([\d.]+)", a)]
    return dict(sure_sn=round(sure, 1), lufs=lufs[-1] if lufs else "?", gercek_tepe_dbfs=gtepe[-1] if gtepe else "?",
                tepe_db=deger("Peak level"), rms_db=deger("RMS level"),
                gurultu_tabani_db=deger("Noise floor"), uzun_sessizlik_sayisi=len(sessiz), en_uzun_sessizlik_sn=max(sessiz) if sessiz else 0)


def yorum(o):
    dk = o["sure_sn"] / 60
    n = []
    n.append("Instant için süre uygun (en az 1 dk; 1–2 dk önerilir)." if 1 <= dk <= 3 else ("Instant için kısa: belge en az 1 dk istiyor." if dk < 1 else "Instant için uzun: belge 3 dk üstüne çıkmamayı öneriyor."))
    n.append("Professional için süre yeterli (30–180 dk)." if 30 <= dk <= 180 else "Professional için belge 30–180 dk öneriyor.")
    if o["rms_db"] not in ("?", "-inf"):
        r = float(o["rms_db"])
        n.append("RMS hedef aralıkta (-23…-18 dB)." if -23 <= r <= -18 else f"RMS {r:.1f} dB: belge -23 ile -18 dB arasını öneriyor.")
    if o["gercek_tepe_dbfs"] not in ("?", "-inf"):
        t = float(o["gercek_tepe_dbfs"])
        n.append("Gerçek tepe -3 dB'nin altında." if t <= -3 else f"Gerçek tepe {t:.1f} dBFS: belge -3 dB öneriyor.")
    if o["uzun_sessizlik_sayisi"]:
        n.append(f"{o['uzun_sessizlik_sayisi']} uzun sessizlik var: belge uzun sessizlikten kaçınmayı öneriyor.")
    return n


if len(sys.argv) > 1:
    hedef = Path(sys.argv[1])
    o = olc(hedef)
else:
    with tempfile.TemporaryDirectory() as t:
        hedef = Path(t) / "oz_test.wav"
        ffmpeg("-y", "-f", "lavfi", "-i", "sine=frequency=220:duration=3", "-f", "lavfi", "-i", "anullsrc=r=48000:cl=mono",
               "-filter_complex", "[0:a]aresample=48000[a];[1:a]atrim=0:2[s];[a][s]concat=n=2:v=0:a=1", "-ac", "1", str(hedef))
        o = olc(hedef)
print(o)
for x in yorum(o):
    print("-", x)
