Wire up the cuts: propose, play in order, publish

playCut steps one video element through the cut's clips. No render, no
upload, no cost - which is the whole reason ten proposals are worth looking
at rather than one.
This commit is contained in:
gator 2026-09-17 12:44:44 +00:00
parent 73a8f5d166
commit 7b4ee1895a

View file

@ -139,6 +139,7 @@
var RUN = null, DRAFTS = [], CUR = null, PKG = {}, NOTES = {}, REVIEWS = []; var RUN = null, DRAFTS = [], CUR = null, PKG = {}, NOTES = {}, REVIEWS = [];
var timer = null, EDITING = null; var timer = null, EDITING = null;
var PLAYING = null, STATS = {}, QUEUE = [], QAT = 0;
var runId = new URLSearchParams(location.search).get("run") || ""; var runId = new URLSearchParams(location.search).get("run") || "";
var audio = new Audio(); var audio = new Audio();
@ -326,6 +327,13 @@
+ 'Each other model reads ONLY this script - no book - and says what it understood.">' + 'Each other model reads ONLY this script - no book - and says what it understood.">'
+ (REVIEWS.length ? "Test it again" : "Does it make sense? Ask " + others + " readers") + (REVIEWS.length ? "Test it again" : "Does it make sense? Ask " + others + " readers")
+ '</button>'); + '</button>');
if ((PKG.shots || []).length >= 6 && String(PKG.cuts_state || "") !== "thinking")
out.push('<button type="button" class="btn" data-cuts="' + esc(meta.id)
+ '" title="Several shorter versions of what is already filmed. '
+ 'Costs nothing to propose or to watch.">'
+ ((PKG.cuts || []).length ? "Propose more cuts" : "Propose shorter cuts")
+ '</button>');
out.push('<button type="button" class="btn" data-measure="' + esc(meta.id) out.push('<button type="button" class="btn" data-measure="' + esc(meta.id)
+ '" title="Speaks every line in the cast voices and reports what the ' + '" title="Speaks every line in the cast voices and reports what the '
+ 'trailer really runs.">' + 'trailer really runs.">'
@ -678,6 +686,41 @@
r = await act("draw_storyboard", { draft_id: el.getAttribute("data-draw") }); r = await act("draw_storyboard", { draft_id: el.getAttribute("data-draw") });
if (r) await refresh(); return; if (r) await refresh(); return;
} }
if ((el = hit("data-cuts"))) {
el.disabled = true; el.textContent = "Working out what to drop…";
r = await act("propose_cuts", { draft_id: el.getAttribute("data-cuts") });
if (r) { showMsg("msg", "Asking for " + r.count + " different cuts.", "ok");
setTimeout(refresh, 25000); }
return;
}
if ((el = hit("data-play"))) {
var cid = el.getAttribute("data-play");
el.disabled = true;
var cc = await api("cut_clips", { draft_id: CUR, cut_id: cid });
el.disabled = false;
if (!cc.ok) { showMsg("msg", cc.error || "That would not play."); return; }
QUEUE = (cc.shots || []).filter(function (s) { return s.clip_url; });
if (!QUEUE.length) {
showMsg("msg", "None of the shots in this cut are filmed yet, so there "
+ "is nothing to play. Film them first.");
return;
}
if (cc.filmed < cc.of)
showMsg("msg", "Playing the " + cc.filmed + " of " + cc.of
+ " shots that are filmed. The rest are skipped.");
PLAYING = cid; QAT = 0; openTab(CUR);
setTimeout(playCut, 60);
return;
}
if ((el = hit("data-stop"))) { PLAYING = null; QUEUE = []; openTab(CUR); return; }
if ((el = hit("data-makecut"))) {
el.disabled = true;
r = await act("make_cut", { draft_id: CUR, cut_id: el.getAttribute("data-makecut") });
if (r) { showMsg("msg", "Joining " + r.shots + " shots into this version. "
+ "It appears in My videos with its own share page.", "ok");
await refresh(); }
return;
}
if ((el = hit("data-measure"))) { if ((el = hit("data-measure"))) {
el.disabled = true; el.textContent = "Speaking every line…"; el.disabled = true; el.textContent = "Speaking every line…";
r = await act("measure_script", { draft_id: el.getAttribute("data-measure") }); r = await act("measure_script", { draft_id: el.getAttribute("data-measure") });
@ -725,6 +768,28 @@
audio.pause(); audio.src = a.url; audio.play(); audio.pause(); audio.src = a.url; audio.play();
}); });
// Play the cut's clips one after another in a single element. This is the
// whole preview: no joining, no encoding, no upload, nothing to pay for.
function playCut() {
var v = document.getElementById("cutv");
if (!v || !QUEUE.length) return;
var at = document.getElementById("cutat");
function step() {
if (QAT >= QUEUE.length) {
if (at) at.textContent = "end of this cut";
return;
}
var s = QUEUE[QAT];
if (at) at.textContent = "shot " + s.id + " · " + (QAT + 1)
+ " of " + QUEUE.length + (s.title ? " · " + s.title : "");
v.src = s.clip_url;
v.play().catch(function () {});
}
v.onended = function () { QAT += 1; step(); };
v.onerror = function () { QAT += 1; step(); };
step();
}
var noteTimers = {}; var noteTimers = {};
document.getElementById("pane").addEventListener("input", function (e) { document.getElementById("pane").addEventListener("input", function (e) {
var ta = e.target; var ta = e.target;