Fix render

This commit is contained in:
Andras Schmelczer 2026-07-14 19:28:09 +01:00
parent 68097386df
commit bf3f09aeb6
4 changed files with 96 additions and 80 deletions

View file

@ -9,7 +9,12 @@ requires-python = ">=3.12"
# model in-process, which dragged in torch + torchaudio + a CUDA-matched
# flash-attn wheel (~700MB of downloads, pinned to the host's driver version
# and to cp312). Generating over HTTP moved all of that onto the server.
#
# Nothing here pins a platform or an interpreter ceiling on purpose: the old
# `[tool.uv] environments` marker existed only to keep torch/torchaudio/
# flash-attn resolving to linux + cp312. Left in place it would outlive its
# reason and break the build, because it caps the LOCK at python < 3.14 while
# requires-python lets uv pick a newer interpreter: `uv sync` then fails with
# "the current Python platform is not compatible with the lockfile's supported
# environments" and render.sh aborts before synthesising a single cue.
dependencies = []
[tool.uv]
environments = ["sys_platform == 'linux' and python_version < '3.14'"]

View file

@ -283,17 +283,34 @@ def ramble_baseline(items: list[dict]) -> float | None:
def rambling_cues(items: list[dict]) -> list[dict]:
"""Cues running far enough past the storyboard's pace to look hallucinated."""
"""Cues running far enough past the storyboard's pace to look hallucinated.
Cues already marked `rambleRepairExhausted` are excluded: we tried every
re-roll and kept the best take we could get, so re-flagging them would
re-run the identical seeds (the server is deterministic per seed) for the
identical result on every render, and would defeat the cache forever.
"""
baseline = ramble_baseline(items)
if baseline is None:
return []
return [
it
for it in items
if secs_per_char(it["text"], it["durationMs"]) > baseline * RAMBLE_TOLERANCE
if not it.get("rambleRepairExhausted")
and secs_per_char(it["text"], it["durationMs"]) > baseline * RAMBLE_TOLERANCE
]
def within_pace(rate: float, baseline: float) -> bool:
"""Is this take's speech rate sane, in EITHER direction?
Two-sided on purpose. A one-sided "not too long" gate would accept a take
whose ending was cut off (rate far BELOW baseline) and stop re-rolling,
quietly shipping clipped narration in place of a ramble.
"""
return baseline / RAMBLE_TOLERANCE <= rate <= baseline * RAMBLE_TOLERANCE
def repair_rambling_cues(
server: str,
audio_dir: Path,
@ -332,12 +349,17 @@ def repair_rambling_cues(
error = abs(candidate_rate - baseline)
if error < best_error:
best, best_error = (data, sample_rate, duration_ms, seed), error
if candidate_rate <= baseline * RAMBLE_TOLERANCE:
if within_pace(candidate_rate, baseline):
break
if best is None:
# Every re-roll was worse than the take we already had. Record that
# we exhausted the sweep so the next render trusts the cache
# instead of re-running these exact seeds for these exact results.
item["rambleRepairExhausted"] = True
print(
f"[synth] cue {item['cueIndex']}: no re-roll beat the original; keeping it",
f"[synth] cue {item['cueIndex']}: no re-roll beat the original; keeping it. "
"Listen before publishing.",
flush=True,
)
continue
@ -347,11 +369,16 @@ def repair_rambling_cues(
item["durationMs"] = duration_ms
item["seed"] = seed
repaired += 1
settled = secs_per_char(item["text"], duration_ms) / baseline
note = "" if settled <= RAMBLE_TOLERANCE else " STILL LONG: listen before publishing"
settled = secs_per_char(item["text"], duration_ms)
note = ""
if not within_pace(settled, baseline):
# Improved but still off-pace: same reasoning as above, stop here
# rather than re-litigating it on every render.
item["rambleRepairExhausted"] = True
note = " STILL OFF-PACE: listen before publishing"
print(
f"[synth] cue {item['cueIndex']}: {duration_ms}ms on seed {seed} "
f"({settled:.1f}x pace){note}",
f"({settled / baseline:.1f}x pace){note}",
flush=True,
)
return repaired

6
video/tts/uv.lock generated
View file

@ -1,12 +1,6 @@
version = 1
revision = 3
requires-python = ">=3.12"
resolution-markers = [
"python_full_version < '3.14' and sys_platform == 'linux'",
]
supported-markers = [
"python_full_version < '3.14' and sys_platform == 'linux'",
]
[[package]]
name = "property-map-video-tts"