Transcripts: a podcast episode gets its transcript going as soon as you play it (published, else made on your server)
build-container / build (push) Successful in 4m6s
build-container / build (push) Successful in 4m6s
This commit is contained in:
1 parent
747002924d
commit
e7bd24bbaa
2 files changed
+20
-4
No files matched your search
+19
-3
@@ -43,12 +43,15 @@ async function lyrFromPlex(t) { // lyrics stored with the song (embedded, a .lrc
|
||||
/** A transcript: the show's own if it publishes one, else (on request) one made on this server. Polls while that is being made. */
|
||||
async function lyrSpoken(t, start) {
|
||||
const q = new URLSearchParams({ key: t.key, src: t.src || '' });
|
||||
for (let n = 0; ; n++) {
|
||||
for (let n = 0; ; n++) { // (n restarts at -1 after an automatic start, so the POST goes out once)
|
||||
if (!lyr.el || lyr.key !== t.key) return null;
|
||||
let r; try { r = await jfetch('/api/transcript?' + q, start && n === 0 ? { method: 'POST' } : undefined); } catch (e) { return { found: false, error: e.message }; }
|
||||
let r; try { r = await jfetch('/api/transcript?' + q, start && n <= 0 ? { method: 'POST' } : undefined); } catch (e) { return { found: false, error: e.message }; }
|
||||
if (r.state === 'ready') { r.transcript.spoken = true; return r.transcript; }
|
||||
if (r.state === 'error') return { found: false, error: r.error, canTranscribe: r.canTranscribe, none: true };
|
||||
if (r.state === 'none') return { found: false, none: true, canTranscribe: r.canTranscribe, why: r.why };
|
||||
if (r.state === 'none') {
|
||||
if (r.canTranscribe && !start && String(t.key).startsWith('pod:') && !lyrPref().noAuto) { start = true; n = -1; continue; } // nothing published: make one (an episode, not a whole book)
|
||||
return { found: false, none: true, canTranscribe: r.canTranscribe, why: r.why };
|
||||
}
|
||||
const body = lyr.el.querySelector('#lyrbody'); if (body) body.innerHTML = `<p class="empty">Making a transcript on your server… ${Math.max(0, Math.round((Date.now() - r.since) / 60000))} min so far.<br><small>You can close this: it keeps going, and it is kept for next time.</small></p>`;
|
||||
await new Promise(ok => setTimeout(ok, 4000));
|
||||
}
|
||||
@@ -147,3 +150,16 @@ function lyrTick() { // follows the song: which line is current, and how far int
|
||||
if (l.words) on.querySelectorAll('.w').forEach((w, j) => { const x = l.words[j]; if (!x) return; const p = pos >= x.e ? 1 : pos <= x.t ? 0 : (pos - x.t) / Math.max(1, x.e - x.t); w.classList.toggle('sung', p >= 1); w.style.setProperty('--p', p); });
|
||||
else { const e = l.e && l.e > l.t ? l.e : l.t + 4000, p = Math.max(0, Math.min(1, (pos - l.t) / Math.max(400, Math.min(e - l.t, 7000)))); on.style.setProperty('--p', p); } // (no word timing: the colour sweeps across the line)
|
||||
}
|
||||
|
||||
// Playing a podcast episode is also the signal to get its transcript going in the background (the published one if there is one, else one made on this
|
||||
// server), so the words are usually ready, or well on the way, by the time Transcript is opened. Once per episode per visit; nothing for audiobooks.
|
||||
const lyrAsked = new Set();
|
||||
pl.a.addEventListener('playing', async () => {
|
||||
const t = typeof cur === 'function' ? cur() : null;
|
||||
if (!t || !String(t.key).startsWith('pod:') || !t.src || lyrAsked.has(t.key) || !cfg.transcribe || lyrPref().noAuto) return;
|
||||
lyrAsked.add(t.key);
|
||||
try {
|
||||
const q = new URLSearchParams({ key: t.key, src: t.src }), r = await jfetch('/api/transcript?' + q);
|
||||
if (r.state === 'none' && r.canTranscribe) await jfetch('/api/transcript?' + q, { method: 'POST' });
|
||||
} catch { lyrAsked.delete(t.key); }
|
||||
});
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// App-shell cache only; Seafile/API traffic always goes to the network.
|
||||
const CACHE = 'hub-v31';
|
||||
const CACHE = 'hub-v32';
|
||||
const SHARE = 'hub-share'; // files shared into the app from other apps, held until the person picks a folder
|
||||
const SHELL = ['/icon.svg', '/manifest.webmanifest', '/icons/icon-192.png', '/icons/apple-touch-icon.png'];
|
||||
|
||||
|
||||
Reference in new issue
Block a user