FAILURE MAP
← Case archive

FA-78271 / Subtitle cue timing / Open access

Recommended cue duration on frame grid: duration clamp · case 01

Long subtitles are held on screen beyond the maximum duration.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

Only the lower clamp is applied.

VERIFIED REPAIR

Clamp to both min and max.

Unsuccessful approach: Applying only the upper clamp leaves short cues below the minimum.

Case contract

rules [base,per_char,min,max]. Count characters other than spaces and line breaks; duration = base + count*per_char, clamped to [min,max]; then rounded up to whole frames at fps [N,D]. Return [frames, ceil(frames*1000*D/N)].

Why this case matters

Subtitle timing defects shift, hide or overlap captions that viewers depend on for comprehension and accessibility.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(text, fps, rules):
    base,per,lo,hi=rules
    n=len(text.replace(' ','').replace('\n',''))
    d=base+n*per
    d=max(lo,d)
    num,den=fps
    fr=-((-d*num)//(1000*den))
    return [fr,-((-fr*1000*den)//num)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: duration clamp', ['A much longer subtitle line to read', [25, 1], [500, 60, 1000, 2000]], [50, 2000]), ('regression variant: duration clamp', ['A much longer subtitle line to read', [30, 1], [300, 50, 1200, 1500]], [45, 1500]), ('partial repair probe: duration clamp', ['Two\nlines here', [25, 1], [300, 50, 1200, 1500]], [30, 1200]), ('partial repair variant: duration clamp', ['   ', [24000, 1001], [0, 70, 800, 7000]], [20, 835]), ('boundary control', ['Two\nlines here', [30000, 1001], [0, 70, 800, 7000]], [26, 868]), ('normal control', ['Hello world', [30, 1], [700, 100, 1000, 2000]], [51, 1700]), ('normal control', ['Two\nlines here', [24000, 1001], [700, 100, 1000, 2000]], [46, 1919]), ('normal control', ['A much longer subtitle line to read', [24, 1], [0, 70, 800, 7000]], [49, 2042])], [('regression: duration clamp', ['A much longer subtitle line to read', [24000, 1001], [300, 50, 1200, 1500]], [36, 1502]), ('regression variant: duration clamp', ['A much longer subtitle line to read', [24000, 1001], [700, 100, 1000, 2000]], [48, 2002]), ('partial repair probe: duration clamp', ['ok', [24, 1], [0, 70, 800, 7000]], [20, 834]), ('partial repair variant: duration clamp', ['Two\nlines here', [30000, 1001], [300, 50, 1200, 1500]], [36, 1202]), ('boundary control', ['Two\nlines here', [30000, 1001], [0, 70, 800, 7000]], [26, 868]), ('normal control', ['Two\nlines here', [24, 1], [0, 70, 800, 7000]], [21, 875]), ('normal control', ['Hello world', [30000, 1001], [700, 100, 1000, 2000]], [51, 1702]), ('normal control', ['A much longer subtitle line to read', [30, 1], [0, 70, 800, 7000]], [61, 2034])], [('regression: duration clamp', ['A much longer subtitle line to read', [30, 1], [700, 100, 1000, 2000]], [60, 2000]), ('regression variant: duration clamp', ['A much longer subtitle line to read', [30000, 1001], [700, 100, 1000, 2000]], [60, 2002]), ('partial repair probe: duration clamp', ['Hi', [24, 1], [0, 70, 800, 7000]], [20, 834]), ('partial repair variant: duration clamp', ['Hello world', [30, 1], [0, 70, 800, 7000]], [24, 800]), ('boundary control', ['Two\nlines here', [30000, 1001], [0, 70, 800, 7000]], [26, 868]), ('normal control', ['Two\nlines here', [24, 1], [500, 60, 1000, 6000]], [30, 1250]), ('normal control', ['Two\nlines here', [24000, 1001], [500, 60, 1000, 6000]], [30, 1252]), ('normal control', ['A much longer subtitle line to read', [24000, 1001], [500, 60, 1000, 6000]], [54, 2253])], [('regression: duration clamp', ['A much longer subtitle line to read', [24, 1], [700, 100, 1000, 2000]], [48, 2000]), ('regression variant: duration clamp', ['A much longer subtitle line to read', [25, 1], [300, 50, 1200, 1500]], [38, 1520]), ('partial repair probe: duration clamp', ['Hi', [24, 1], [500, 60, 1000, 6000]], [24, 1000]), ('partial repair variant: duration clamp', ['Hello world', [30000, 1001], [0, 70, 800, 7000]], [24, 801]), ('boundary control', ['Two\nlines here', [30000, 1001], [0, 70, 800, 7000]], [26, 868]), ('normal control', ['Two\nlines here', [25, 1], [500, 60, 1000, 6000]], [31, 1240]), ('normal control', ['Hello world', [24, 1], [700, 100, 1000, 2000]], [41, 1709]), ('normal control', ['A much longer subtitle line to read', [30000, 1001], [0, 70, 800, 7000]], [61, 2036])], [('regression: duration clamp', ['A much longer subtitle line to read', [30000, 1001], [300, 50, 1200, 1500]], [45, 1502]), ('regression variant: duration clamp', ['A much longer subtitle line to read', [24, 1], [300, 50, 1200, 1500]], [36, 1500]), ('partial repair probe: duration clamp', ['Hello world', [25, 1], [300, 50, 1200, 1500]], [30, 1200]), ('partial repair variant: duration clamp', ['Hello world', [30, 1], [300, 50, 1200, 1500]], [36, 1200]), ('boundary control', ['Two\nlines here', [30000, 1001], [0, 70, 800, 7000]], [26, 868]), ('normal control', ['A much longer subtitle line to read', [24, 1], [500, 60, 1000, 6000]], [54, 2250]), ('normal control', ['Two\nlines here', [30, 1], [0, 70, 800, 7000]], [26, 867]), ('normal control', ['A much longer subtitle line to read', [25, 1], [500, 60, 1000, 6000]], [56, 2240])]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: duration clamp[56, 2240][50, 2000]Failed
regression variant: duration clamp[53, 1767][45, 1500]Failed
partial repair probe: duration clamp[30, 1200][30, 1200]Passed
partial repair variant: duration clamp[20, 835][20, 835]Passed
boundary control[26, 868][26, 868]Passed
normal control[51, 1700][51, 1700]Passed
normal control[46, 1919][46, 1919]Passed
normal control[49, 2042][49, 2042]Passed

SHA-256 / 3fd5a659270a1840ae1bc7ae75b755571e7d454dfe682059196b41d81acd3f36

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(text, fps, rules):
    base,per,lo,hi=rules
    n=len(text.replace(' ','').replace('\n',''))
    d=base+n*per
    d=min(hi,d)
    num,den=fps
    fr=-((-d*num)//(1000*den))
    return [fr,-((-fr*1000*den)//num)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: duration clamp', ['A much longer subtitle line to read', [25, 1], [500, 60, 1000, 2000]], [50, 2000]), ('regression variant: duration clamp', ['A much longer subtitle line to read', [30, 1], [300, 50, 1200, 1500]], [45, 1500]), ('partial repair probe: duration clamp', ['Two\nlines here', [25, 1], [300, 50, 1200, 1500]], [30, 1200]), ('partial repair variant: duration clamp', ['   ', [24000, 1001], [0, 70, 800, 7000]], [20, 835]), ('boundary control', ['Two\nlines here', [30000, 1001], [0, 70, 800, 7000]], [26, 868]), ('normal control', ['Hello world', [30, 1], [700, 100, 1000, 2000]], [51, 1700]), ('normal control', ['Two\nlines here', [24000, 1001], [700, 100, 1000, 2000]], [46, 1919]), ('normal control', ['A much longer subtitle line to read', [24, 1], [0, 70, 800, 7000]], [49, 2042])], [('regression: duration clamp', ['A much longer subtitle line to read', [24000, 1001], [300, 50, 1200, 1500]], [36, 1502]), ('regression variant: duration clamp', ['A much longer subtitle line to read', [24000, 1001], [700, 100, 1000, 2000]], [48, 2002]), ('partial repair probe: duration clamp', ['ok', [24, 1], [0, 70, 800, 7000]], [20, 834]), ('partial repair variant: duration clamp', ['Two\nlines here', [30000, 1001], [300, 50, 1200, 1500]], [36, 1202]), ('boundary control', ['Two\nlines here', [30000, 1001], [0, 70, 800, 7000]], [26, 868]), ('normal control', ['Two\nlines here', [24, 1], [0, 70, 800, 7000]], [21, 875]), ('normal control', ['Hello world', [30000, 1001], [700, 100, 1000, 2000]], [51, 1702]), ('normal control', ['A much longer subtitle line to read', [30, 1], [0, 70, 800, 7000]], [61, 2034])], [('regression: duration clamp', ['A much longer subtitle line to read', [30, 1], [700, 100, 1000, 2000]], [60, 2000]), ('regression variant: duration clamp', ['A much longer subtitle line to read', [30000, 1001], [700, 100, 1000, 2000]], [60, 2002]), ('partial repair probe: duration clamp', ['Hi', [24, 1], [0, 70, 800, 7000]], [20, 834]), ('partial repair variant: duration clamp', ['Hello world', [30, 1], [0, 70, 800, 7000]], [24, 800]), ('boundary control', ['Two\nlines here', [30000, 1001], [0, 70, 800, 7000]], [26, 868]), ('normal control', ['Two\nlines here', [24, 1], [500, 60, 1000, 6000]], [30, 1250]), ('normal control', ['Two\nlines here', [24000, 1001], [500, 60, 1000, 6000]], [30, 1252]), ('normal control', ['A much longer subtitle line to read', [24000, 1001], [500, 60, 1000, 6000]], [54, 2253])], [('regression: duration clamp', ['A much longer subtitle line to read', [24, 1], [700, 100, 1000, 2000]], [48, 2000]), ('regression variant: duration clamp', ['A much longer subtitle line to read', [25, 1], [300, 50, 1200, 1500]], [38, 1520]), ('partial repair probe: duration clamp', ['Hi', [24, 1], [500, 60, 1000, 6000]], [24, 1000]), ('partial repair variant: duration clamp', ['Hello world', [30000, 1001], [0, 70, 800, 7000]], [24, 801]), ('boundary control', ['Two\nlines here', [30000, 1001], [0, 70, 800, 7000]], [26, 868]), ('normal control', ['Two\nlines here', [25, 1], [500, 60, 1000, 6000]], [31, 1240]), ('normal control', ['Hello world', [24, 1], [700, 100, 1000, 2000]], [41, 1709]), ('normal control', ['A much longer subtitle line to read', [30000, 1001], [0, 70, 800, 7000]], [61, 2036])], [('regression: duration clamp', ['A much longer subtitle line to read', [30000, 1001], [300, 50, 1200, 1500]], [45, 1502]), ('regression variant: duration clamp', ['A much longer subtitle line to read', [24, 1], [300, 50, 1200, 1500]], [36, 1500]), ('partial repair probe: duration clamp', ['Hello world', [25, 1], [300, 50, 1200, 1500]], [30, 1200]), ('partial repair variant: duration clamp', ['Hello world', [30, 1], [300, 50, 1200, 1500]], [36, 1200]), ('boundary control', ['Two\nlines here', [30000, 1001], [0, 70, 800, 7000]], [26, 868]), ('normal control', ['A much longer subtitle line to read', [24, 1], [500, 60, 1000, 6000]], [54, 2250]), ('normal control', ['Two\nlines here', [30, 1], [0, 70, 800, 7000]], [26, 867]), ('normal control', ['A much longer subtitle line to read', [25, 1], [500, 60, 1000, 6000]], [56, 2240])]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: duration clamp[50, 2000][50, 2000]Passed
regression variant: duration clamp[45, 1500][45, 1500]Passed
partial repair probe: duration clamp[23, 920][30, 1200]Failed
partial repair variant: duration clamp[0, 0][20, 835]Failed
boundary control[26, 868][26, 868]Passed
normal control[51, 1700][51, 1700]Passed
normal control[46, 1919][46, 1919]Passed
normal control[49, 2042][49, 2042]Passed

SHA-256 / f44863907c1b72e3d4ec10e952f9ebfdbed65dddc071a4d7ca7aa84fe3f6476a

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(text, fps, rules):
    base,per,lo,hi=rules
    n=len(text.replace(' ','').replace('\n',''))
    d=base+n*per
    d=max(lo,min(hi,d))
    num,den=fps
    fr=-((-d*num)//(1000*den))
    return [fr,-((-fr*1000*den)//num)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: duration clamp', ['A much longer subtitle line to read', [25, 1], [500, 60, 1000, 2000]], [50, 2000]), ('regression variant: duration clamp', ['A much longer subtitle line to read', [30, 1], [300, 50, 1200, 1500]], [45, 1500]), ('partial repair probe: duration clamp', ['Two\nlines here', [25, 1], [300, 50, 1200, 1500]], [30, 1200]), ('partial repair variant: duration clamp', ['   ', [24000, 1001], [0, 70, 800, 7000]], [20, 835]), ('boundary control', ['Two\nlines here', [30000, 1001], [0, 70, 800, 7000]], [26, 868]), ('normal control', ['Hello world', [30, 1], [700, 100, 1000, 2000]], [51, 1700]), ('normal control', ['Two\nlines here', [24000, 1001], [700, 100, 1000, 2000]], [46, 1919]), ('normal control', ['A much longer subtitle line to read', [24, 1], [0, 70, 800, 7000]], [49, 2042])], [('regression: duration clamp', ['A much longer subtitle line to read', [24000, 1001], [300, 50, 1200, 1500]], [36, 1502]), ('regression variant: duration clamp', ['A much longer subtitle line to read', [24000, 1001], [700, 100, 1000, 2000]], [48, 2002]), ('partial repair probe: duration clamp', ['ok', [24, 1], [0, 70, 800, 7000]], [20, 834]), ('partial repair variant: duration clamp', ['Two\nlines here', [30000, 1001], [300, 50, 1200, 1500]], [36, 1202]), ('boundary control', ['Two\nlines here', [30000, 1001], [0, 70, 800, 7000]], [26, 868]), ('normal control', ['Two\nlines here', [24, 1], [0, 70, 800, 7000]], [21, 875]), ('normal control', ['Hello world', [30000, 1001], [700, 100, 1000, 2000]], [51, 1702]), ('normal control', ['A much longer subtitle line to read', [30, 1], [0, 70, 800, 7000]], [61, 2034])], [('regression: duration clamp', ['A much longer subtitle line to read', [30, 1], [700, 100, 1000, 2000]], [60, 2000]), ('regression variant: duration clamp', ['A much longer subtitle line to read', [30000, 1001], [700, 100, 1000, 2000]], [60, 2002]), ('partial repair probe: duration clamp', ['Hi', [24, 1], [0, 70, 800, 7000]], [20, 834]), ('partial repair variant: duration clamp', ['Hello world', [30, 1], [0, 70, 800, 7000]], [24, 800]), ('boundary control', ['Two\nlines here', [30000, 1001], [0, 70, 800, 7000]], [26, 868]), ('normal control', ['Two\nlines here', [24, 1], [500, 60, 1000, 6000]], [30, 1250]), ('normal control', ['Two\nlines here', [24000, 1001], [500, 60, 1000, 6000]], [30, 1252]), ('normal control', ['A much longer subtitle line to read', [24000, 1001], [500, 60, 1000, 6000]], [54, 2253])], [('regression: duration clamp', ['A much longer subtitle line to read', [24, 1], [700, 100, 1000, 2000]], [48, 2000]), ('regression variant: duration clamp', ['A much longer subtitle line to read', [25, 1], [300, 50, 1200, 1500]], [38, 1520]), ('partial repair probe: duration clamp', ['Hi', [24, 1], [500, 60, 1000, 6000]], [24, 1000]), ('partial repair variant: duration clamp', ['Hello world', [30000, 1001], [0, 70, 800, 7000]], [24, 801]), ('boundary control', ['Two\nlines here', [30000, 1001], [0, 70, 800, 7000]], [26, 868]), ('normal control', ['Two\nlines here', [25, 1], [500, 60, 1000, 6000]], [31, 1240]), ('normal control', ['Hello world', [24, 1], [700, 100, 1000, 2000]], [41, 1709]), ('normal control', ['A much longer subtitle line to read', [30000, 1001], [0, 70, 800, 7000]], [61, 2036])], [('regression: duration clamp', ['A much longer subtitle line to read', [30000, 1001], [300, 50, 1200, 1500]], [45, 1502]), ('regression variant: duration clamp', ['A much longer subtitle line to read', [24, 1], [300, 50, 1200, 1500]], [36, 1500]), ('partial repair probe: duration clamp', ['Hello world', [25, 1], [300, 50, 1200, 1500]], [30, 1200]), ('partial repair variant: duration clamp', ['Hello world', [30, 1], [300, 50, 1200, 1500]], [36, 1200]), ('boundary control', ['Two\nlines here', [30000, 1001], [0, 70, 800, 7000]], [26, 868]), ('normal control', ['A much longer subtitle line to read', [24, 1], [500, 60, 1000, 6000]], [54, 2250]), ('normal control', ['Two\nlines here', [30, 1], [0, 70, 800, 7000]], [26, 867]), ('normal control', ['A much longer subtitle line to read', [25, 1], [500, 60, 1000, 6000]], [56, 2240])]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: duration clamp[50, 2000][50, 2000]Passed
regression variant: duration clamp[45, 1500][45, 1500]Passed
partial repair probe: duration clamp[30, 1200][30, 1200]Passed
partial repair variant: duration clamp[20, 835][20, 835]Passed
boundary control[26, 868][26, 868]Passed
normal control[51, 1700][51, 1700]Passed
normal control[46, 1919][46, 1919]Passed
normal control[49, 2042][49, 2042]Passed

SHA-256 / 7ffdff62e1d98bb9e4a318f26d317c427a075954c3357fef8687bfca97998f47

Verification & scope

A deterministic bounded teaching model with a stipulated toy contract; it does not claim conformance to any subtitle standard. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:49:33.784465+00:00.

Case digest / 869a663febc0ffab95a9d913403111c99229615af2752394d90cfd9a4555e607