Stille überspringen (Browser/Desktop): Pausen schnell durchspielen statt springen; sw v109
Ein Sprung im gestreamten Podcast wartet aufs Netz (hörbares Haken). Jetzt läuft eine Pause mit 4-facher Geschwindigkeit (höchstens 8x), je 0,12 s bleiben an beiden Enden; nur Pausen über 3 s werden noch übersprungen. Geprüft alle 40 ms statt mit timeupdate (alle 250 ms). Browser-Tab im Hintergrund (gedrosselte Timer): weiter mit Sprüngen, sonst liefe Sprache sekundenlang vierfach. Gemessen in der Desktop-App: Pausen 52,85–53,34 und 57,03–57,58 s schnell durchlaufen, kein Sprung. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
1c74e60224
commit
cac8027fb3
2 changed files with 57 additions and 8 deletions
|
|
@ -974,16 +974,65 @@
|
||||||
return silence.spans;
|
return silence.spans;
|
||||||
}
|
}
|
||||||
|
|
||||||
audio.addEventListener('timeupdate', () => {
|
// A pause is run through fast rather than jumped over: a jump in a streamed
|
||||||
if (!loaded || audio.paused || audio.seeking) return;
|
// file waits for the network again (a hitch you hear), a faster rate doesn't.
|
||||||
|
// A little of each pause stays at both ends; only a long one is still jumped.
|
||||||
|
// Checked every 40 ms while playing (timeupdate comes only every 250 ms, too
|
||||||
|
// late for a short pause). A browser tab in the background gets its timers
|
||||||
|
// slowed down to a second or more — speech at four times the speed for that
|
||||||
|
// long would be worse than a hitch, so there it jumps as before.
|
||||||
|
const SILENCE_RATE = 4; // × the podcast's own speed, inside a pause
|
||||||
|
const SILENCE_KEEP = 0.12; // s of each pause kept at either end
|
||||||
|
const SILENCE_JUMP = 3; // s: a pause longer than this is jumped over
|
||||||
|
let silenceFast = false;
|
||||||
|
let silenceTimer = null;
|
||||||
|
|
||||||
|
// The end of the pause the player is in (less what stays of it), or null.
|
||||||
|
function silenceEndAt(t) {
|
||||||
const spans = silenceSpans();
|
const spans = silenceSpans();
|
||||||
if (!spans || !spans.length) return;
|
if (!spans) return null;
|
||||||
const t = audio.currentTime;
|
|
||||||
for (const [start, end] of spans) { // in order
|
for (const [start, end] of spans) { // in order
|
||||||
if (start > t) break;
|
if (start + SILENCE_KEEP > t) return null;
|
||||||
if (t < end - 0.3) { try { audio.currentTime = end - 0.15; } catch (e) {} return; }
|
if (t < end - SILENCE_KEEP) return end - SILENCE_KEEP;
|
||||||
}
|
}
|
||||||
});
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function silenceNormal() {
|
||||||
|
if (!silenceFast) return;
|
||||||
|
silenceFast = false;
|
||||||
|
audio.playbackRate = speedFor(curFeed());
|
||||||
|
}
|
||||||
|
|
||||||
|
function silenceTick() {
|
||||||
|
if (!loaded || audio.paused || audio.seeking) { silenceNormal(); return; }
|
||||||
|
const t = audio.currentTime;
|
||||||
|
const endAt = silenceEndAt(t);
|
||||||
|
if (endAt === null) { silenceNormal(); return; }
|
||||||
|
const timersFine = !document.hidden || !!window.dioraDesktop; // the desktop app never slows them
|
||||||
|
if (endAt - t > SILENCE_JUMP || !timersFine) {
|
||||||
|
silenceNormal();
|
||||||
|
try { audio.currentTime = endAt; } catch (e) {}
|
||||||
|
} else {
|
||||||
|
const fast = Math.min(speedFor(curFeed()) * SILENCE_RATE, 8);
|
||||||
|
silenceFast = true;
|
||||||
|
if (audio.playbackRate !== fast) audio.playbackRate = fast; // also after applyKind reset it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function silenceWatch() {
|
||||||
|
clearInterval(silenceTimer);
|
||||||
|
silenceTimer = null;
|
||||||
|
silenceNormal();
|
||||||
|
if (loaded && !audio.paused && skipSilenceFor(curFeed())) silenceTimer = setInterval(silenceTick, 40);
|
||||||
|
}
|
||||||
|
audio.addEventListener('playing', silenceWatch);
|
||||||
|
audio.addEventListener('pause', silenceWatch);
|
||||||
|
audio.addEventListener('ended', silenceWatch);
|
||||||
|
audio.addEventListener('emptied', silenceWatch);
|
||||||
|
// Back from the background, or the setting changed: the timer may have to start.
|
||||||
|
document.addEventListener('visibilitychange', silenceWatch);
|
||||||
|
audio.addEventListener('timeupdate', () => { if (!silenceTimer && !audio.paused) silenceWatch(); else silenceTick(); });
|
||||||
|
|
||||||
// ---- radio and podcasts take turns ---------------------------------------------------
|
// ---- radio and podcasts take turns ---------------------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
* diora service worker — caches the app shell for offline use.
|
* diora service worker — caches the app shell for offline use.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const CACHE = 'diora-v108';
|
const CACHE = 'diora-v109';
|
||||||
const SHELL = [
|
const SHELL = [
|
||||||
'/static/css/app.css',
|
'/static/css/app.css',
|
||||||
'/static/js/app/01-core.js',
|
'/static/js/app/01-core.js',
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue