A still worth texting, with the link that goes under it
Sending the video itself by MMS puts it through carrier transcoding and it arrives looking far worse than it left. So the picture carries the hook and a link carries the video at full quality. The still is 720x1280 and lands around 90KB at near-maximum quality — carrier limits are typically 600KB and up, so there is no reason to compress hard. The frame is chosen by sampling several moments and keeping the one that compresses largest, which in practice means eyes open and in focus rather than mid-blink. The play button sits at two thirds height so it never covers the face.
This commit is contained in:
parent
4d553585d6
commit
b94b0557c2
1 changed files with 80 additions and 0 deletions
80
script.html
80
script.html
|
|
@ -341,6 +341,15 @@ function render(r) {
|
|||
+ (p.cut_url ? 'Cut it again' : 'Cut the B-roll in') + '</button>'
|
||||
+ '<div id="seamout" style="margin-top:14px"></div>'
|
||||
+ '<div id="takes" style="margin-top:20px"></div>'
|
||||
+ '</div>'
|
||||
+ '<h2 class="sec" style="margin-top:34px">Send it to someone</h2>'
|
||||
+ '<div class="card">'
|
||||
+ '<p class="foot" style="margin:0 0 14px">Texting the video itself puts it through '
|
||||
+ 'carrier transcoding and it arrives looking worse than it left. Send the picture as '
|
||||
+ 'the hook and let the link carry the video at full quality.</p>'
|
||||
+ '<button type="button" class="btn ghost" id="sharebtn">Make the picture</button>'
|
||||
+ '<span class="foot" style="margin-left:12px" id="sharenote"></span>'
|
||||
+ '<div id="shareout" style="margin-top:16px"></div>'
|
||||
+ '</div>';
|
||||
}
|
||||
|
||||
|
|
@ -1119,8 +1128,79 @@ function bindPreviz() {
|
|||
});
|
||||
}
|
||||
|
||||
// The picture is the hook; the link carries the video. Never the video itself
|
||||
// over MMS - carriers transcode it into mush.
|
||||
function bindShare() {
|
||||
var b = document.getElementById("sharebtn");
|
||||
if (!b) return;
|
||||
var note = document.getElementById("sharenote"),
|
||||
out = document.getElementById("shareout");
|
||||
|
||||
function paint(r) {
|
||||
var kb = Math.round((r.bytes || 0) / 1024);
|
||||
var link = r.video || "";
|
||||
var msg = ((DATA && DATA.script && DATA.script.title)
|
||||
? DATA.script.title + " — " : "")
|
||||
+ ((DATA && DATA.project && DATA.project.pet_name) || "your pet")
|
||||
+ " has something to say. " + link;
|
||||
out.innerHTML = '<div style="display:flex;gap:18px;flex-wrap:wrap;align-items:flex-start">'
|
||||
+ '<img src="' + esc(r.image) + '" alt="share picture" '
|
||||
+ 'style="width:190px;border-radius:10px;border:1px solid var(--line);display:block">'
|
||||
+ '<div style="flex:1 1 260px">'
|
||||
+ '<p class="foot" style="margin:0 0 10px">' + esc(r.size || "") + ' · ' + kb + ' KB'
|
||||
+ ' · well inside the 600KB most carriers allow, so it will not be '
|
||||
+ 'downsampled.</p>'
|
||||
+ '<label class="mini">The message</label>'
|
||||
+ '<textarea id="sharemsg" style="min-height:70px">' + esc(msg) + '</textarea>'
|
||||
+ '<button type="button" class="btn ghost" id="sharecopy" style="margin-top:8px">Copy the message</button>'
|
||||
+ '<a class="btn ghost" style="margin-left:8px;display:inline-block;text-decoration:none" '
|
||||
+ 'href="' + esc(r.image) + '" download>Download the picture</a>'
|
||||
+ '</div></div>';
|
||||
var c = document.getElementById("sharecopy");
|
||||
if (c) c.onclick = function () {
|
||||
var t = document.getElementById("sharemsg");
|
||||
t.select();
|
||||
navigator.clipboard.writeText(t.value).then(function () {
|
||||
c.textContent = "Copied";
|
||||
setTimeout(function () { c.textContent = "Copy the message"; }, 1600);
|
||||
}).catch(function () { c.textContent = "Select it and copy"; });
|
||||
};
|
||||
}
|
||||
|
||||
b.onclick = async function () {
|
||||
hideMsg("msg");
|
||||
b.disabled = true; b.textContent = "Choosing a frame…";
|
||||
var r = await api("share_image", { 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("share_image", { email: email, project_id: pid });
|
||||
if (g.ok && !g.pending) { clearInterval(t); done(g); return; }
|
||||
if (waited > 180) { clearInterval(t); done({ ok: false, error: "That is taking unusually long." }); }
|
||||
}, 4000);
|
||||
});
|
||||
}
|
||||
b.disabled = false; b.textContent = "Pick another frame";
|
||||
if (!r.ok) { showMsg("msg", r.error || "Could not make that picture."); return; }
|
||||
if (r.note) { showMsg("msg", r.note); return; }
|
||||
note.textContent = r.status_text || "";
|
||||
paint(r);
|
||||
};
|
||||
|
||||
api("share_image", { email: email, project_id: pid }).then(function (r) {
|
||||
if (r && r.ok && !r.pending && r.image) {
|
||||
b.textContent = "Pick another frame";
|
||||
note.textContent = r.status_text || "";
|
||||
paint(r);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function bindPost() {
|
||||
loadTakes();
|
||||
bindShare();
|
||||
// The editing bay is opt-in. Most people want to watch the thing and leave.
|
||||
var eo = document.getElementById("edlopen");
|
||||
if (eo) eo.onclick = function () {
|
||||
|
|
|
|||
Loading…
Reference in a new issue