Match capture strips: freeze video on every scrubber interaction
The point-capture and coach-review strips have a forcePause helper that pauses the video (and re-pauses 30ms later to beat HLS.js's async resume) whenever the slider is grabbed or scrubbed. It wasn't being called from the frame-step buttons or the typed-timestamp commit, so using the ± nudge to land on an exact moment while the video was playing would happily keep the video playing and drift past the target. Expose forcePause on both _pcbCtx and _rcbCtx and call it from: - pcbNudge / rcbNudge (frame-step buttons) - commitTimeInput / _rcbCommitTimeInput (typed timestamp on Enter) - _rcbSetActiveSlot (switching start/end slot re-scrubs the video) Playback now resumes only on an explicit play press. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3e18bd2150
commit
9f82d3cf31
@ -4756,6 +4756,9 @@
|
||||
timeInp.value = toMinuteSecondClock(video.currentTime || 0);
|
||||
return;
|
||||
}
|
||||
// Typing a timestamp is a scrubber interaction — freeze the
|
||||
// frame. Only the play button resumes playback.
|
||||
forcePause();
|
||||
const dur = Number(video.duration) || 0;
|
||||
const clamped = Math.max(0, dur > 0 ? Math.min(dur, secs) : secs);
|
||||
try { video.currentTime = clamped; } catch (_) {}
|
||||
@ -4808,6 +4811,10 @@
|
||||
_pcbCtx = { roundNumber, roundId, video, wrap, bar, slider,
|
||||
onSlide, onSlideCommit, onVideoTime, onKey, onSliderGrab,
|
||||
timeInp, commitTimeInput, onTimeInputKey,
|
||||
// Exposed so pcbNudge / commitTimeInput (defined
|
||||
// outside this closure) can guarantee the video
|
||||
// stays paused during any scrubber interaction.
|
||||
forcePause,
|
||||
existingId: existingSingle ? existingSingle.id : null,
|
||||
existingBlueId: existingBlue ? existingBlue.id : null,
|
||||
existingRedId: existingRed ? existingRed.id : null };
|
||||
@ -4991,7 +4998,11 @@
|
||||
}
|
||||
function pcbNudge(deltaSeconds) {
|
||||
if (!_pcbCtx) return;
|
||||
const { video, slider } = _pcbCtx;
|
||||
const { video, slider, forcePause } = _pcbCtx;
|
||||
// Any scrubber interaction must freeze the frame — the user is
|
||||
// trying to land on a precise moment. Playback resumes only when
|
||||
// they explicitly press the play button.
|
||||
if (forcePause) forcePause();
|
||||
// Direction only — nudge is always ±1 frame, at every zoom level
|
||||
const dir = deltaSeconds >= 0 ? 1 : -1;
|
||||
const step = FRAME_STEP() * dir;
|
||||
@ -5570,6 +5581,10 @@
|
||||
sliderS, sliderE, fillEl,
|
||||
onSlideStart, onSlideEnd, onSlideCommit, onVideoTime, onKey,
|
||||
onSliderGrabR,
|
||||
// Exposed for rcbNudge / commitStart / commitEnd so
|
||||
// every scrubber interaction freezes the frame — only
|
||||
// an explicit play press should resume playback.
|
||||
forcePause: forcePauseR,
|
||||
startInp, endInp, commitStart, commitEnd,
|
||||
noteInp, previewFn, overlay,
|
||||
// Seed from existing position when editing, else default
|
||||
@ -5686,6 +5701,9 @@
|
||||
const val = document.getElementById(which === 'end' ? 'rcbEnd' : 'rcbStart').value;
|
||||
const secs = parsePcbTimeInput(val);
|
||||
if (secs !== null && _rcbCtx && _rcbCtx.video) {
|
||||
// Switching the active slot re-scrubs the video — pause it
|
||||
// so the user doesn't unexpectedly resume playback.
|
||||
if (_rcbCtx.forcePause) _rcbCtx.forcePause();
|
||||
try { _rcbCtx.video.currentTime = secs; } catch (_) {}
|
||||
// Keep dual sliders in sync with the input value
|
||||
if (_rcbCtx.sliderS && which === 'start') _rcbCtx.sliderS.value = secs;
|
||||
@ -5711,6 +5729,9 @@
|
||||
inp.value = toMinuteSecondClock(_rcbCtx.video.currentTime || 0);
|
||||
return;
|
||||
}
|
||||
// Typing a timestamp is a scrubber interaction — freeze the
|
||||
// frame. Playback resumes only on an explicit play press.
|
||||
if (_rcbCtx.forcePause) _rcbCtx.forcePause();
|
||||
const dur = Number(_rcbCtx.video.duration) || 0;
|
||||
const clamped = Math.max(0, dur > 0 ? Math.min(dur, secs) : secs);
|
||||
inp.value = toMinuteSecondClock(clamped);
|
||||
@ -5787,7 +5808,10 @@
|
||||
// Nudge the LAST-TOUCHED scrubber (start or end) by ±1 frame.
|
||||
function rcbNudge(deltaSeconds) {
|
||||
if (!_rcbCtx) return;
|
||||
const { video, sliderS, sliderE, startInp, endInp } = _rcbCtx;
|
||||
const { video, sliderS, sliderE, startInp, endInp, forcePause } = _rcbCtx;
|
||||
// Freeze the frame — scrubber steps are for precise landing,
|
||||
// not incidental resume-playback triggers.
|
||||
if (forcePause) forcePause();
|
||||
const which = (typeof _rcbCtxLastTouched === 'function' ? _rcbCtxLastTouched() : 'start');
|
||||
const target = which === 'end' ? sliderE : sliderS;
|
||||
const otherVal = Number(which === 'end' ? sliderS.value : sliderE.value) || 0;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user