diff --git a/script.html b/script.html index fe1c37d..9e9bf17 100644 --- a/script.html +++ b/script.html @@ -377,7 +377,12 @@ function render(r) { + 'words costs about a hundredth of a cent. Run it through in your pet’s voice ' + 'over the opening stills first, and only film once the timing and the jokes land.

' + '' + + '' + '' + + '

Cutting to the clock speaks the whole piece once, ' + + 'measures where every word actually falls, and moves the shot boundaries to real word ' + + 'endings. It rewrites how the lines are divided — not the words themselves.

' + + '
' + '
' + '' + '

The shots

' @@ -531,6 +536,7 @@ function wire(locked) { }); bindPics(); bindPreviz(); + bindAlign(); bindFilm((DATA && DATA.project) || {}); bindPost(); if (locked) { bindBottom(); return; } @@ -1013,6 +1019,67 @@ function pzPaint(lines) { }; } +function bindAlign() { + var b = document.getElementById("alignbtn"); + if (!b) return; + var out = document.getElementById("alignout"); + + function paint(r) { + var bought = ((DATA && DATA.script && DATA.script.segments) || []).length * 8; + var filmed = r.filmed || 0; + out.innerHTML = '

Measured: ' + + (r.spoken || 0).toFixed(1) + 's spoken, about ' + filmed.toFixed(1) + + 's filmed, against ' + bought + 's of shots.

' + + (r.audio ? '' : '') + + (r.shots || []).map(function (s) { + var fit = Math.abs((s.filmed || 0) - 8) <= 1.2; + return '
' + + 'shot ' + s.index + ' · ' + (s.start || 0).toFixed(1) + '-' + + (s.end || 0).toFixed(1) + 's spoken · ~' + (s.filmed || 0).toFixed(1) + 's filmed' + + (fit ? '' : ' off the clock') + + '
' + esc(s.line || "") + '
'; + }).join("") + + (filmed < bought - 1.5 + ? '
The whole piece only runs about ' + + filmed.toFixed(1) + ' seconds filmed, but ' + bought + ' seconds are being shot. ' + + 'No arrangement of these words fills the video — it needs more written, or a ' + + 'shorter length.
' + : '') + + (filmed > bought + 1.5 + ? '
The whole piece runs about ' + + filmed.toFixed(1) + ' seconds filmed against ' + bought + ' seconds of video, so the ' + + 'end would be cut off. Trim it, or buy more length.
' + : ''); + } + + b.onclick = async function () { + hideMsg("msg"); + b.disabled = true; b.textContent = "Measuring…"; + var r = await api("align_script", { email: email, project_id: pid, refresh: true }); + if (r.ok && r.pending) { + var waited = 0; + r = await new Promise(function (done) { + var t = setInterval(async function () { + waited += 4; + var g = await api("align_script", { email: email, project_id: pid }); + if (g.ok && !g.pending) { clearInterval(t); done(g); return; } + if (waited > 240) { clearInterval(t); done({ ok: false, error: "That is taking unusually long." }); } + }, 4000); + }); + } + b.disabled = false; b.textContent = "Cut it to the clock"; + if (!r.ok) { showMsg("msg", r.error || "Could not measure that."); return; } + if (r.note) { showMsg("msg", r.note); return; } + paint(r); + showMsg("msg", "Shots re-cut at real word endings.", "ok"); + load(); + }; + + api("align_script", { email: email, project_id: pid }).then(function (r) { + if (r && r.ok && !r.pending && r.audio) paint(r); + }); +} + function bindPreviz() { var b = document.getElementById("pzmake"); if (!b) return;