Apunta los scripts de sync prod al Hetzner nuevo y suma trabajo pendiente
- sync_translations_to_prod.py / sync_audio_to_prod.py / sync_carta_from_prod.py: migran de FEA_PROD_HOST/PASS (CDMON, password) a FEA_PROD_SSH_HOST/PASS + FEA_PROD_DOCKER_CONTAINER (Hetzner/Coolify, auth por clave), con wrapping docker exec y el fix del bug de redirecciones (wc -c/cat) resuelto en el host en vez de dentro del contenedor. - fea_translate_helper.php: subcomando clone_new para clonar en ID local nuevo cuando el ID de prod ya está ocupado localmente. - translate_post.py: --dry-run. - tts_produce.py: --allow-default-voice (voz Nico solo si se permite explícitamente para autores sin voz clonada) + fix voice_for_author. - minimax_tts.py: parámetro speed en t2a/_synth_chunk. - mirror-antiguo/deploy/nginx-mirror.conf: redirects de URLs históricas de catálogo y vista imprimible EFFA. - Importaciones humanas de Pagola (carta 738) + scripts/manifest de la fase A Enrique, y release_issue181_prod.sh / cdmon-retire-fewp1.sh. - .gitignore: excluye docs/backups/ (dumps SQL, mismo motivo que backups/*). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -361,12 +361,12 @@ def _split_for_tts(text, limit=CHAR_LIMIT):
|
||||
return chunks
|
||||
|
||||
|
||||
def _synth_chunk(text, voice_id, model):
|
||||
def _synth_chunk(text, voice_id, model, speed=1.0):
|
||||
"""Una petición t2a. Devuelve (audio_bytes|None, rc, usage_chars)."""
|
||||
body = {
|
||||
"model": model,
|
||||
"text": text,
|
||||
"voice_setting": {"voice_id": voice_id, "speed": 1.0, "vol": 1.0, "pitch": 0},
|
||||
"voice_setting": {"voice_id": voice_id, "speed": speed, "vol": 1.0, "pitch": 0},
|
||||
"audio_setting": {"sample_rate": 32000, "bitrate": 128000, "format": "mp3", "channel": 1},
|
||||
"language_boost": "Spanish",
|
||||
}
|
||||
@@ -381,13 +381,15 @@ def _synth_chunk(text, voice_id, model):
|
||||
return bytes.fromhex(audio_hex), 0, usage
|
||||
|
||||
|
||||
def t2a(text, voice_id, model, name):
|
||||
def t2a(text, voice_id, model, name, speed=1.0):
|
||||
if not 0.5 <= float(speed) <= 2.0:
|
||||
raise ValueError(f"speed fuera de rango: {speed} (permitido 0.5–2.0)")
|
||||
chunks = _split_for_tts(text)
|
||||
print(f"Sintetizando {len(text)} car con {model} / {voice_id} "
|
||||
print(f"Sintetizando {len(text)} car con {model} / {voice_id} a {float(speed):.2f}× "
|
||||
f"({len(chunks)} petición/es)…", flush=True)
|
||||
raw = OUT / f"{name}.raw.mp3"
|
||||
if len(chunks) == 1:
|
||||
audio, rc, _ = _synth_chunk(chunks[0], voice_id, model)
|
||||
audio, rc, _ = _synth_chunk(chunks[0], voice_id, model, speed)
|
||||
if audio is None:
|
||||
return rc
|
||||
raw.write_bytes(audio)
|
||||
@@ -398,7 +400,7 @@ def t2a(text, voice_id, model, name):
|
||||
import os as _os, time as _t
|
||||
_t.sleep(int(_os.environ.get("FEA_CHUNK_PAUSE", "35"))) # respetar TPM de MiniMax
|
||||
print(f" trozo {k + 1}/{len(chunks)} ({len(ch)} car)…", flush=True)
|
||||
audio, rc, _ = _synth_chunk(ch, voice_id, model)
|
||||
audio, rc, _ = _synth_chunk(ch, voice_id, model, speed)
|
||||
if audio is None:
|
||||
for p in parts:
|
||||
p.unlink(missing_ok=True)
|
||||
|
||||
Reference in New Issue
Block a user