# Honest limitations and troubleshooting

Phase 182, `182.C.39.02`. Ten conditions the item names: profile, occlusion,
fast speech, singing, overlapping dialogue, tiny faces, rapid movement, weak
references, unsupported languages, and model drift.

Every number here is a measurement this repo holds, with the module that holds
it. Where nothing was measured, the entry says so instead of estimating.

## Start here: the three that fail silently

A limitation you can see is a limitation you can report. These three produce
output that looks correct to every check we run, which makes them the ones to
suspect when a take is wrong and nothing flagged it.

| Condition            | What the metrics say                              | What is actually wrong                                 |
| -------------------- | ------------------------------------------------- | ------------------------------------------------------ |
| Overlapping dialogue | Pronunciation score exactly 0.0 — clean           | Timing is 513.8 ms out, four times the reject boundary |
| A motionless cast    | Speaker attribution at maximum margin — confident | Nobody in the scene is reacting                        |
| Frames nobody scored | Aggregate sync high — passing                     | The score is only over the still, frontal frames       |

**Overlapping speech breaks the aligner silently** (`182.C.18.08`,
`human-video-delivery-conditions.ts`). A second voice starting half a second in
gives a 513.8 ms onset error while the goodness-of-pronunciation stays at
exactly 0.0. Forced alignment is given the words and asked where they are; it
will always find them somewhere. `assertAlignmentMeasurable` refuses a timing
claim on overlapping speech rather than discounting it, because a discounted
wrong number is still a wrong number.

**A frozen supporting cast buys a perfect attribution** (`182.C.20.03`,
`human-video-speaker-attribution.ts`). Nothing else in frame moves, so the
speaker is unambiguous: a reacting listener cuts the margin to 0.65 where a
still one leaves it at 1.00. The confident-looking number is _caused by_ the
defect, so both are reported together.

**The measurability filter is a sampling bias** (`182.C.20.02`,
`human-video-motion-sampling.ts`). Excluding windows where the face is turned or
occluded is correct, and the excluded frames are the moving ones — so the
aggregate is "sync, given the face was frontal and still". On a clip that is
half movement, the same band scores read 0.908 over what was scored and 0.750
under the clip's own motion mix. The figure is an upper bound, not an estimate.

## The ten conditions

### Profile

Sync is scorable on-camera only. Past 60° of head yaw the mouth geometry is
foreshortened; past 120° there is no visible speech at all
(`human-video-offscreen-dialogue.ts`, boundaries named provisional against a
1.55° pose-measurement noise floor). A back turn is reported **unevaluable**,
never as a pass — a shot of the back of a head passes every check there is.

_What to do:_ plan the window's visibility. A deliberate profile needs a stated
reason, and it is then excluded from the sync arithmetic rather than counted
against the take.

### Occlusion

A hand, a prop or a mask removes the mouth from measurement.
`human-video-measurability.ts` gives every window one of three verdicts and
never lets "no findings" read as "no problems". Intermittent occlusion — wind, a
passing hand — deliberately stays **scorable**: treating it as unevaluable would
excuse a real failure (`human-video-challenge-cases.ts`).

### Fast and slow speech

`182.C.18.08` measured it: onset error rises from 32.9 ms to 68.4 ms at 1.6×,
still inside the ITU boundary — the aligner survives. What breaks is the
**pronunciation** measure, which falls to −4.99 at 1.25× and −10.20 at 0.80× on
audio whose words and speaker are identical to the clean clip, against a floor
of −3.0. A phase vocoder's smearing looks like bad pronunciation to a
frame-level acoustic model, and slow is worse than fast.

_What to do:_ nothing, on the creator's side. `assertGopMeasurable` refuses the
pronunciation score on time-stretched audio instead of reporting a
mispronunciation that did not happen.

### Singing

**Not measured, and not fakeable.** Singing is one of six delivery conditions
with no fixture (`UNMEASURED_CONDITIONS`), because the conditions that _were_
built are transformations of a signal — a tempo change, a mix, an offset copy —
and singing is different phonation. Filtering a normal voice into "a whisper"
produces a quiet normal voice, and testing a detector against that proves the
detector reads the filter. No claim is made about sung dialogue in either
direction.

### Overlapping dialogue

See the silent-failure section. Beyond the aligner, attribution cannot work at
all: two people speaking at once is one envelope and two mouths moving with it,
so the correct answer is **not evaluable by this method**, not "ambiguous"
(`human-video-conversation-dynamics.ts`). Filing overlap as a defect makes the
ambiguous rate rise with how naturally people talk. Separating them needs
per-speaker audio, which no route supplies today.

### Tiny faces

Below 7% of frame height the landmarker declined entirely on the measured frame;
below 10% identity margin is under a quarter of its clean value
(`WARNING_THRESHOLDS` in `human-video-pre-generation-warnings.ts`). These are
warnings raised **before** generation, because the alternative is finding out
after paying for the render.

_What to do:_ change the shot size. The expected face height per shot size is
tabulated in `human-video-measurability.ts`.

### Rapid movement

At 21 px of motion blur only 4% of identity margin survives. At 31 px a face
scored **0.251 against its own clean self**, under the 0.282
two-different-people baseline (`182.C.19.08`). Past that point identity is not
low, it is **undecidable**, and the system declines rather than reporting a
failure — a take is not rejected for failing a test that could not be run on it.

### Weak references

The pack check refuses a pairwise cosine under 0.4. It has a **known false
negative** and the code says so: `182.C.07.03` measured two different subjects
at 0.261 and one subject against a degraded copy of itself at 0.739 and 0.819,
so 0.4 sits between those — but an earlier probe put two strangers at 0.422,
above the line. A pack that mixes two people who look alike passes this check.
It catches a gross mismatch before money is spent; **it is not an identity
gate.**

### Unsupported languages

A locale whose normalizer has no rules is a refusal, not a pass-through
(`localeNormalizable` in `human-video-pre-generation-warnings.ts`,
`hv.capability.locale_unsupported`). Silently sending unnormalised text produces
a take with the wrong words in it and no record of why.

### Model drift

A provider can change a model under a stable name. Re-runs are triggered by
change rather than by calendar, and the demotion tolerance is **derived from
measured noise** rather than chosen: a single window of eight scores spanned
0.0400 while three steady windows moved 0.0025 between them, so a tolerance of
0.02 would fire on the spread and demote a route for nothing
(`human-video-auto-demotion.ts`). Demotion is automatic because it is the safe
direction; promotion is not, because a bounded re-run cannot re-establish what a
promotion asserted.

## Troubleshooting: from symptom to cause

| Symptom                                             | Look at                                                                                               |
| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| "The words are right but the timing is off"         | Overlapping speech in the source audio — the aligner will not say so                                  |
| "It says mispronounced and it sounds fine"          | Time-stretched audio; the pronunciation score is refused, not scored                                  |
| "It says nothing about sync at all"                 | The window was unevaluable: profile, occlusion, or a back turn                                        |
| "Identity failed on an action shot"                 | Check the blur band; past 31 px the answer should be _undecided_                                      |
| "The scene looks dead"                              | A frozen non-speaking cast, which scores _better_ on attribution                                      |
| "The pass rate dropped with no release change"      | Model drift; the route's re-run is triggered by change, not by date                                   |
| "Two references of the same person were rejected"   | The 0.4 cosine floor is provisional and has a known false negative                                    |
| "A low-SNR warning on clean audio with music under" | Music under speech is not noise; the percentile SNR reads 16.8 dB at a 5 dB bed, against a gate at 20 |

## What this document does not cover

Everything here is measured on fixtures and committed frames. **No real
generated clip has been through this pipeline**, so none of these limits has
been confirmed against production output, and the pass rates a creator would
want — how often a take is good — are `182.C.30.03`'s, waiting on the corpus in
`182.C.33`.
