Transcoded videos stream through a live ffmpeg pipe with no byte ranges, so
the browser couldn't seek/rewind them at all. Fix it end to end:
- get_transcode accepts ?start=<secs> and passes -ss before -i (fast keyframe
seek), rebasing timestamps to 0 from there.
- The player gets a custom control bar for transcode sources: play/pause, a
scrubber driven by the known duration, current/total time, ±10s, mute +
volume, and fullscreen, plus space / arrows / j / l / f keyboard shortcuts.
Seeking re-requests the stream at the new offset; effective time is
offset + element.currentTime. Every seek path (scrubber, chapters,
transcript click, resume, save-position, chapter/transcript highlight) now
routes through one offset-aware playerSeek()/effTime().
- Direct /files/ videos keep native <video controls> (already seekable).
Verified server-side: start=0 vs start=120 yield different streams.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>