diff --git a/trailer.html b/trailer.html
index 1686c8f..5a09afa 100644
--- a/trailer.html
+++ b/trailer.html
@@ -341,6 +341,26 @@
// A CHAPTER IS FILMED IN PARTS of about 25 shots that share one cast and the
// same rooms. This says where each part has got to, and joins them.
+ // A VOICE OVER SOMEBODY LISTENING. In a phone call the audience wants to see
+ // whoever is talking. One press re-frames those shots onto the speaker.
+ function heardNotSeen() {
+ return (PKG.shots || []).filter(function (sh) {
+ var l = (sh.audio || []).filter(function (a) { return String(a.text || "").trim(); });
+ return l.length === 1 && !l[0].lip_sync && l[0].character_id
+ && String(l[0].character_id) !== String(PKG.narrator || "")
+ && String(l[0].text).trim().split(/\s+/).length > 3;
+ });
+ }
+ function speakerNoticeHtml(draft) {
+ var st = PKG.show_speaker || {};
+ if (st.state === "working") return '
Re-framing those shots onto the person speaking… this takes a minute or two.
';
+ var n = heardNotSeen();
+ if (!n.length) return "";
+ return '
Shots ' + n.map(function (x) { return esc(x.id); }).join(", ") + '. In a conversation people expect to see whoever is talking. This rewrites those pictures to show the speaker, in the place where they are. Every word stays as it is. The pictures will need drawing again.
'
+ + '
';
+ }
+
function partsHtml(draft) {
var parts = DRAFTS.filter(function (d) { return /^part-/.test(String(d.writer)); });
var n = (PKG.shots || []).length;
@@ -957,7 +977,7 @@
DRAFTNOW = draft;
return head + partsHtml(draft) + contestHtml() + guideHtml(meta) + probs + '
' + barHtml(meta) + '
'
+ '
' + reelHtml() + '
'
- + spineHtml() + cutsHtml(meta) + reviewsHtml(meta) + wholeHtml() + castHtml + propsHtml() + body;
+ + spineHtml() + cutsHtml(meta) + reviewsHtml(meta) + wholeHtml() + speakerNoticeHtml(draft) + castHtml + propsHtml() + body;
}
// THINGS THAT MUST STAY THE SAME. A face is held steady by a reference
@@ -1600,6 +1620,11 @@
}
return;
}
+ if ((el = hit("data-showspeakers"))) {
+ r = await act("show_speakers", { draft_id: el.getAttribute("data-showspeakers") });
+ if (r) { showMsg("msg", "Re-framing " + (r.shots || []).length + " shots onto the person speaking. The words do not change.", "ok"); await refresh(); }
+ return;
+ }
if ((el = hit("data-splitparts"))) {
el.disabled = true;
r = await act("split_parts", { run_id: runId, draft_id: el.getAttribute("data-splitparts") });