diff --git a/admin.html b/admin.html index c8cbe6f..c329bc4 100644 --- a/admin.html +++ b/admin.html @@ -68,11 +68,22 @@ function shotHtml(s) { + '

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

' + '
' + s.words + ' words' + (over ? ' (over 18)' : '') + ' · camera: ' + esc(s.camera || "—") + '
' + // The writer's performance direction. It used to reach the previz and + // never Veo, so a line written as "building outrage" was filmed flat. + // Showing both halves is the point: what was asked for, and what went. + + '
delivery: ' + (s.delivery_sent + ? '' + esc(s.delivery_sent) + ' — sent to Veo' + : (s.delivery + ? '' + esc(s.delivery) + ' — written but NOT sent' + : 'none written for this line')) + '
' // A redub that failed falls back to Veo's own audio on purpose. That is - // the right behaviour, but it must not be silent. + // the right behaviour, but it must not be silent. Deliberately skipping + // it is a third state and must not read as the failure. + '
voice: ' + (s.voice_used ? esc(s.voice_used) + ' (redubbed)' - : 'Veo original, not redubbed') + '
' + : (s.redub_skipped + ? 'Veo original — redub switched off for this run' + : 'Veo original, not redubbed')) + '' // The likeness chain, end to end: the owner's photograph, then the // opening frame built from it, which is what Veo actually receives. If // the frame is missing, Veo saw only the written description. @@ -103,6 +114,13 @@ function shotHtml(s) { + (s.prompt_sent ? '
Exact prompt sent
' + esc(s.prompt_sent) + '
' : '
no prompt recorded (filmed before prompts were stored)
') + // The prompt and the request are not the same claim. An earlier version of + // video_render validated its images and then posted only the prompt, which + // read as working code for weeks. This is the body as it went on the wire. + + (s.request_sent + ? '
The request body actually POSTed
'
+          + esc(s.request_sent) + '
' + : '') + ''; } @@ -130,6 +148,14 @@ function projHtml(p) { + 'source ' + esc((p.source_url || "").slice(0, 70)) + '' + (p.film_note ? '
note ' + esc(p.film_note) + '' : '') + '' + // Operator switch, for hearing the same script both ways. Not a customer + // control: the server refuses it to anyone without the admin role. + + '
redub on the next film: ' + + (p.skip_redub ? 'OFF — Veo keeps its own voice' : 'on') + ' ' + + '
' + (p.owner_notes ? '

notes ' + esc(p.owner_notes) + '

' : '') + '' + (p.full_text ? '
Full piece as written
' + esc(p.full_text) + '
' : '') @@ -162,6 +188,26 @@ async function load() { + '
' + pct + '%took first draft
' + '' + (r.projects || []).map(projHtml).join(""); + + // Delegated, because the list is re-rendered wholesale on every load. + document.getElementById("out").onclick = async function (ev) { + var b = ev.target.closest ? ev.target.closest("[data-redub]") : null; + if (!b) return; + b.disabled = true; + var was = b.textContent; + b.textContent = "Saving..."; + var res = await api("set_film_options", { + project_id: b.getAttribute("data-redub"), + skip_redub: b.getAttribute("data-want") === "1" + }); + if (!res.ok) { + showMsg("msg", res.error || "Could not change that."); + b.disabled = false; + b.textContent = was; + return; + } + load(); + }; } document.getElementById("go").onclick = function () {