Correct the previz for the difference between spoken and filmed pace

The run-through is spoken by ElevenLabs, but the finished audio is Veo's
performance re-voiced, and Veo enunciates more slowly - it was asked to, to
make the mouth movement readable. Measured on a real clip: 17 words ran 7.02s
filmed (about 2.4 words a second) against roughly 3.0 words a second spoken.

So the raw previz number understates the filmed length by about a quarter, and
the dead-air warning was correspondingly overstated - it claimed 2.4 seconds of
silence per shot where the filmed figure is nearer one. Show both numbers and
name the factor rather than quietly applying it.
This commit is contained in:
gator 2026-09-08 13:05:14 +00:00
parent 447368e355
commit c26efbbea7

View file

@ -939,7 +939,12 @@ function pzPaint(lines) {
if (!PZ.length) { el.innerHTML = ""; return; }
var total = PZ.reduce(function (a, b) { return a + (b.seconds || 0); }, 0);
var bought = segs.length * 8;
var over = PZ.filter(function (x) { return x.over; });
// Spoken here, but filmed by Veo, which was asked to over-enunciate so the
// mouth is readable and therefore runs slower. Measured on a real clip:
// 17 words took 7.02s filmed against about 5.7s spoken, so ~1.25x.
var FILMED = 1.25;
var filmed = total * FILMED;
var over = PZ.filter(function (x) { return (x.seconds || 0) * FILMED > 8.0; });
el.innerHTML = '<div class="stage" style="margin-bottom:12px">'
+ '<img id="pzimg" alt="opening still" style="width:100%;aspect-ratio:9/16;'
@ -948,32 +953,35 @@ function pzPaint(lines) {
+ '<audio id="pzaud"></audio>'
+ '<button type="button" class="btn" id="pzplay">&#9654; Play the run-through</button>'
+ '<span class="foot" style="margin-left:12px" id="pzwhere">'
+ PZ.length + ' lines &middot; ' + total.toFixed(1) + 's spoken, '
+ bought + 's of shots</span>'
+ (total > bought
? '<div class="warn" style="margin-top:12px">Spoken, this runs '
+ total.toFixed(1) + ' seconds but only ' + bought + ' seconds are being '
+ 'filmed. Something will be cut off. Shorten the words, or buy more length.</div>'
: (total < bought * 0.85
? '<div class="warn" style="margin-top:12px">Spoken, this runs only '
+ total.toFixed(1) + ' seconds across ' + bought + ' seconds of video, '
+ 'so roughly ' + ((bought - total) / PZ.length).toFixed(1) + ' seconds of '
+ 'every shot is silence. That is where trailing sound effects and echo come '
+ 'from: the model is handed a gap and fills it. More words per shot is the fix.</div>'
+ PZ.length + ' lines &middot; ' + total.toFixed(1) + 's spoken, about '
+ filmed.toFixed(1) + 's once filmed, against ' + bought + 's of shots</span>'
+ (filmed > bought
? '<div class="warn" style="margin-top:12px">Filmed, this would run about '
+ filmed.toFixed(1) + ' seconds but only ' + bought + ' seconds are being '
+ 'shot. Something will be cut off. Shorten the words, or buy more length.</div>'
: (filmed < bought * 0.88
? '<div class="warn" style="margin-top:12px">Filmed, this would run about '
+ filmed.toFixed(1) + ' seconds across ' + bought + ' seconds of video, '
+ 'leaving roughly ' + ((bought - filmed) / PZ.length).toFixed(1) + ' seconds '
+ 'of silence at the end of every shot. That is where trailing sound effects '
+ 'and echo come from: the model is handed a gap and fills it. More words per '
+ 'shot is the fix.</div>'
: ''))
+ (over.length
? '<div class="warn" style="margin-top:12px">Shot' + (over.length > 1 ? 's ' : ' ')
+ over.map(function (x) { return x.index; }).join(", ")
+ ' will not fit in eight seconds: '
+ over.map(function (x) { return x.index + " runs " + x.seconds.toFixed(1) + "s"; }).join(", ")
+ ' will not fit in eight seconds once filmed: '
+ over.map(function (x) { return x.index + " would run " + (x.seconds * FILMED).toFixed(1) + "s"; }).join(", ")
+ '. Trim those lines before filming.</div>'
: '')
+ '<div style="margin-top:14px">'
+ PZ.map(function (x) {
var f = (x.seconds || 0) * FILMED;
return '<div class="foot" style="padding:6px 0;border-top:1px solid var(--line)">'
+ 'shot ' + x.index + ' &middot; ' + x.seconds.toFixed(1) + 's'
+ (x.over ? ' <span style="color:var(--accent2)">over</span>' : '')
+ ' &middot; ' + esc(x.line.slice(0, 64)) + '</div>';
+ 'shot ' + x.index + ' &middot; ' + x.seconds.toFixed(1) + 's spoken, ~'
+ f.toFixed(1) + 's filmed'
+ (f > 8 ? ' <span style="color:var(--accent2)">over</span>' : '')
+ ' &middot; ' + esc(x.line.slice(0, 60)) + '</div>';
}).join("")
+ '</div>';