fix(short): el prompt pedía tres cosas que no podían cumplirse a la vez
El modelo declaraba menos segundos de los que su propia línea necesitaba en 3 o 4 de cada 5 planos narrados — entre 3,8 y 8,2 s de deriva por Short. El vídeo salía con la duración correcta porque shortsmith estira, pero el ritmo visual que el spec escribía no era el que se renderizaba. No era pereza del modelo: era un juego de reglas insatisfacible. El prompt pedía a la vez líneas de hasta 18 palabras, planos de 6 s como mucho, y tiempo declarado suficiente para la propia voz. 18 palabras piden 7,3 s, así que las tres juntas son imposibles y el modelo rompía la única que nadie comprobaba. Tres capas, las tres deterministas y sin gastar una generación: - La regla enseñada llevaba el mismo error de clase que el estimador tenía antes del 2026-08-12: palabras por segundo a secas, sin el término de las pausas. Medida contra las 28 líneas que el bot ha narrado de verdad, `words/2.75 + 0.5` se quedaba corta en 14 y hasta 2,27 s — obedecerla al pie de la letra seguía infradeclarando. Ahora es de dos términos, como la voz, y el peor caso baja a 1,27 s en 5 de 28. - El tope de palabras por línea se DERIVA del plano más largo (`max_words_in`) en vez de escribirse a mano. La contradicción no puede volver. - El ejemplo de referencia incumplía su propia regla en 2 de sus 6 líneas, y el ejemplo es la señal más fuerte del prompt: le estábamos enseñando el fallo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -29,6 +29,9 @@ __all__ = [
|
||||
"editorial_notes",
|
||||
"estimated_duration",
|
||||
"spoken_seconds",
|
||||
"sentence_count",
|
||||
"teachable_seconds",
|
||||
"max_words_in",
|
||||
"describe_templates",
|
||||
"TARGET_MIN_DURATION",
|
||||
"TARGET_MAX_DURATION",
|
||||
@@ -350,11 +353,54 @@ NARRATION_PAD = 0.45
|
||||
#: le pide que recorte texto, no tiempo.
|
||||
NARRATION_WORDS_PER_SECOND = 2.75
|
||||
|
||||
#: El respiro redondeado hacia arriba, para la regla que se le enseña al modelo.
|
||||
#: `NARRATION_PAD` son 0,45 s; "medio segundo" se sostiene en la cabeza y va
|
||||
#: sobrado, que es la dirección correcta en la que equivocarse.
|
||||
NARRATION_ROUNDED_PAD = 0.5
|
||||
|
||||
#: Final de frase: un punto pegado a la palabra y seguido de espacio o de nada.
|
||||
#: El decimal de "1.5" no cuenta, y por eso mira lo que va detrás.
|
||||
_SENTENCE_END = re.compile(r"[.!?](?=\s|$)")
|
||||
|
||||
|
||||
def sentence_count(line: str) -> int:
|
||||
"""Frases de una línea, contadas como las cuenta Piper para sus pausas."""
|
||||
return max(1, len(_SENTENCE_END.findall(line))) if line.strip() else 0
|
||||
|
||||
|
||||
def teachable_seconds(words: int, sentences: int = 1) -> float:
|
||||
"""Lo que hay que DECLARAR para una línea, en las unidades que el modelo cuenta.
|
||||
|
||||
Es `spoken_seconds` traducido de caracteres a palabras. La traducción hace
|
||||
falta porque un LLM no cuenta caracteres de fiar, pero sí cuenta palabras y
|
||||
puntos — y la regla tiene que ser computable por quien debe obedecerla, o no
|
||||
es una regla, es un deseo.
|
||||
|
||||
Los dos términos son los mismos que los de la voz. La versión anterior del
|
||||
prompt colapsaba el segundo en un "+ medio segundo" fijo, y ese es el mismo
|
||||
error de clase que tenía el estimador antes del 2026-08-12: sin pausa por
|
||||
frase, una línea troceada en frases cortas se da por rápida. Medido contra
|
||||
las 28 líneas reales, aquella regla se quedaba corta en 14 y hasta 2,27 s —
|
||||
o sea que un modelo que la obedeciera al pie de la letra seguiría
|
||||
infradeclarando la mitad de sus planos. Con el término por frase el peor
|
||||
caso baja a 1,27 s y sólo en 5 de 28.
|
||||
"""
|
||||
return (words / NARRATION_WORDS_PER_SECOND
|
||||
+ sentences * NARRATION_SENTENCE_SILENCE
|
||||
+ NARRATION_ROUNDED_PAD)
|
||||
|
||||
|
||||
def max_words_in(seconds: float, sentences: int = 1) -> int:
|
||||
"""Cuántas palabras caben en un plano de esa duración, según la regla de arriba.
|
||||
|
||||
Existe para que el tope de palabras por línea y el tope de duración de plano
|
||||
no puedan volver a contradecirse: se deriva uno del otro en vez de escribir
|
||||
los dos a mano.
|
||||
"""
|
||||
room = seconds - sentences * NARRATION_SENTENCE_SILENCE - NARRATION_ROUNDED_PAD
|
||||
return max(1, int(room * NARRATION_WORDS_PER_SECOND))
|
||||
|
||||
|
||||
def spoken_seconds(line: str) -> float:
|
||||
"""Lo que tarda la voz en decir una línea, sin el respiro final.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user