diff --git a/script.html b/script.html index ae2ac0b..4db270d 100644 --- a/script.html +++ b/script.html @@ -88,6 +88,24 @@ function shotHtml(s, locked) { : '' + ''; + // A cutaway belonging to this shot straddles the cut into the next one, so + // the registration jump happens off screen. + var br = s.broll || {}; + var brollBlock = ''; + if (br.subject) { + brollBlock = '
' + + '' + + '

' + esc(br.subject) + ' · ' + esc(br.kind || 'image') + '

' + + (s.broll_url + ? (s.broll_kind === 'video' + ? '' + : 'cutaway') + : '') + + (locked ? '' : '') + + '
'; + } + var controls = locked ? '' : toggle + settingLabel @@ -109,6 +127,7 @@ function shotHtml(s, locked) { + '

' + esc(s.line || "") + '

' + '

' + (s.word_count || 0) + ' words · about ' + (s.est_seconds || 0) + 's

' + '
' + controls + '
' + + brollBlock + ''; } @@ -151,6 +170,22 @@ function render(r) { var cams = '' + PRESETS.map(function (c) { return ''; + // Post production only exists once there is footage to cut. + var post = ''; + if (p.status === 'ready' || p.cut_url) { + post = '

The cut

' + + (p.cut_url + ? '' + : '') + + '

Cutaways are laid across the joins between shots, ' + + 'so the picture changes while the voice keeps going and the join is never on screen.

' + + '' + + '' + + '
' + + '
'; + } + var actions = locked ? '

Approved. Filming is switched on once payment is live. Nothing has been charged.

' : '
' @@ -167,12 +202,14 @@ function render(r) { out.innerHTML = cams + head + warn + full + '

The shots

' + s.segments.map(function (x) { return shotHtml(x, locked); }).join("") + + post + actions; wire(locked); } function wire(locked) { + bindPost(); if (locked) { bindBottom(); return; } // Save edits when the field loses focus, so typing is never interrupted. @@ -204,6 +241,29 @@ function wire(locked) { }); }); + [].forEach.call(document.querySelectorAll("[data-broll]"), function (b) { + b.addEventListener("click", async function () { + hideMsg("msg"); + var idx = parseInt(b.getAttribute("data-broll"), 10); + b.disabled = true; b.textContent = "Making…"; + var r = await api("make_broll", { email: email, project_id: pid, index: idx }); + if (!r.ok) { b.disabled = false; b.textContent = "Make cutaway"; showMsg("msg", r.error || "Could not make that."); return; } + var waited = 0; + var t = setInterval(async function () { + waited += 5; + var g = await api("get_project", { email: email, project_id: pid }); + var seg = (g.ok && g.script && g.script.segments || []).filter(function (x) { + return parseInt(x.index, 10) === idx; })[0]; + if (seg && seg.broll_url) { clearInterval(t); load(); return; } + if (waited > 180) { + clearInterval(t); + b.disabled = false; b.textContent = "Make cutaway"; + showMsg("msg", "That cutaway is taking unusually long."); + } + }, 5000); + }); + }); + [].forEach.call(document.querySelectorAll("[data-make]"), function (b) { b.addEventListener("click", async function () { hideMsg("msg"); @@ -249,6 +309,51 @@ function wire(locked) { bindBottom(); } +function bindPost() { + var sb = document.getElementById("seams"); + if (sb) sb.onclick = async function () { + sb.disabled = true; sb.textContent = "Measuring…"; + var r = await api("seam_report", { email: email, project_id: pid }); + sb.disabled = false; sb.textContent = "Measure the joins"; + var el = document.getElementById("seamout"); + if (!r.ok) { showMsg("msg", r.error || "Could not measure."); return; } + if (!r.seams || !r.seams.length) { + el.innerHTML = '

' + esc(r.status_text || "Nothing to measure.") + '

'; + return; + } + el.innerHTML = '

' + esc(r.status_text || "") + '

' + + r.seams.map(function (x) { + var col = x.verdict === "smooth" ? "var(--good)" + : (x.verdict === "visible" ? "var(--accent2)" : "var(--bad)"); + return '
' + + 'shot ' + x.after_shot + ' → ' + x.before_shot + ' at ' + x.at_seconds + 's · ' + + 'shift ' + x.shift_x + ',' + x.shift_y + ' · drift ' + x.drift + ' · ' + + '' + esc(x.verdict) + '' + + (x.recommend_broll ? ' · worth a cutaway' : '') + + '
'; + }).join(""); + }; + + var cb = document.getElementById("cut"); + if (cb) cb.onclick = async function () { + hideMsg("msg"); + cb.disabled = true; cb.textContent = "Cutting…"; + var r = await api("render_cut", { email: email, project_id: pid }); + if (!r.ok) { cb.disabled = false; cb.textContent = "Cut the B-roll in"; showMsg("msg", r.error || "Could not cut."); return; } + var waited = 0; + var t = setInterval(async function () { + waited += 5; + var g = await api("get_project", { email: email, project_id: pid }); + if (g.ok && g.project && g.project.cut_url) { clearInterval(t); load(); return; } + if (waited > 300) { + clearInterval(t); + cb.disabled = false; cb.textContent = "Cut the B-roll in"; + showMsg("msg", "That is taking unusually long. Try again shortly."); + } + }, 5000); + }; +} + function bindBottom() { var rv = document.getElementById("revise"); if (rv) rv.onclick = async function () {