codex/bound-transcode-segments
3
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
31a26b2554 |
fix(scanner): accept corroborated long video durations (#545)
* fix(scanner): accept corroborated long video durations * fix(scanner): harden long duration fallbacks * fix(scanner): address long duration review feedback * fix(scanner): align long duration seek semantics * fix(scanner): align legacy long media seeking * fix(scanner): preserve long timeline origins * fix(scanner): preserve long audio-switch timelines * fix(scanner): distinguish absolute-end timelines * fix(scanner): preserve long resume semantics * fix(scanner): reject ambiguous absolute ends * fix(scanner): preserve compat real-manifest resumes |
||
|
|
02203d9e40 |
fix(playback): trust the server's media runtime end to end (#482)
* fix(scanner): reject durations that imply an impossible bitrate The duration-plausibility rule only rejected videos of 10 seconds or less, so a feature film that probed as 61 seconds passed untouched and persisted. Clients then had nothing trustworthy to anchor on: Android's grow-only duration ratchet has no floor to hold when the catalog value is wrong, so the playback engine's growing-HLS-window duration won and a 90-minute movie displayed as ~1 minute. Size and duration together pin an implied bitrate, which separates the two cases the absolute floor conflates. A genuine short clip has an ordinary bitrate; a 100 GB file claiming 61 seconds implies ~13 Gbps. The ceiling sits far above any real medium, so legitimate content cannot trip it — and unlike the absolute floor, it does not false-positive on a genuine high-bitrate short. Also bump the repair-rule revision marker so rows judged by the previous, weaker rule are re-checked once under this one. Without that bump an improved rule never reaches the rows it was written for. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(playback): publish source runtime in v3 plans and stop faking the copy seek window Two defects with one root: a v3 plan described where playback sits without ever stating how long the media is. Add source.duration_seconds. It is the file's full runtime, never `total - source_start` and never adjusted by timeline_offset_seconds, and it is omitted rather than null when unknown — clients that coerce null to a numeric default would read it as zero, the exact value this field exists to stop them inventing. It is set in SourceDescriptorFromFileV3, the single place every delivery already flows through, so direct play, progressive remux, HLS remux and HLS transcode all carry it. Until now the v3 plan omitted duration entirely, so clients fell back to the playback engine. On an HLS copy remux the server intentionally serves FFmpeg's still-growing playlist, so the engine reports the length produced so far. With no server-supplied runtime to anchor on, a feature film played back as a couple of minutes. The legacy protocol already answered this correctly via fileDurationSeconds; this restores parity. Separately, the copy branch published seek_window_end_seconds as the media runtime. That made the window look *complete*, which clients read as proof that any target inside it is locally seekable, so they native-seek past the produced head of a growing playlist instead of asking for a reanchor. Leave the end open: an incomplete window plus can_seek_anywhere=false routes every seek through the server, which is what legacy did before v3 added the bound. Advertise plan_source_duration_v1 so a client can distinguish "this server does not populate the field" from "this server knows the runtime is genuinely unknown" — without it, both look like an absent field and a client cannot tell whether its own catalog fallback is still required. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(web): pair the exit position with the media runtime, not the element duration The player's exit state converts its position to media time but took the duration from the video element, which is player-local. On a remux or transcode stream the element only covers the window produced so far, so the two values live in different coordinate systems. Resuming a movie 50 minutes in makes that concrete: the exit position is ~3060s of media time while the element reports ~120s. The progress cache then evaluates `position >= duration`, marks the item completed, latches the watched badge, and — because completion clears the resume point — resets position to 0. Exiting a resumed movie destroyed the resume point and claimed it had been watched. The server's runtime is authoritative and already expressed in media time, so prefer it and fall back to the element only when no server value exists. The rule moves into mediaTimeline.ts next to the coordinate conversions it depends on, which is also what makes it testable — VideoPlayer itself has no test harness. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
2fb5e10de4 |
fix(scanner): recover malformed video durations (#416)
* fix(scanner): recover malformed video durations * fix(scanner): preserve probe failure semantics * fix(scanner): harden malformed-duration recovery after review Remediates the deep-review findings on the duration recovery machinery: - Ignore attached_pic cover-art streams when deciding whether a file is video: audiobooks/music with embedded artwork no longer fail import or persist 1-second durations, and never trigger the packet scan. - Cap the audio-only duration path (raised ceiling, not removed) so malformed audio containers cannot persist multi-year durations. - Keep the parsed probe when the packet fallback fails instead of discarding codecs/tracks/resolution with a hard ProbeFile error. - Apply the implausibly-short guard to the end-minus-start fallbacks so collapsed absolute-timestamp spans reach the packet scan too. - Make the legacy-duration repair one-shot: rows reprobed by the fixed parser are authoritative, ending the infinite reprobe loop for genuinely short large clips. - Teach the library-scan repair predicate (needsCriticalProbeRepairScanState) the same legacy signature so scans repair collapsed durations instead of deferring to request-time repair. - Grant the packet-scan timeout to any reprobe likely to hit the fallback (Duration<=0 video files), not just the legacy shape. - Share the implausibly-short thresholds between probe and repair layers (closes the 100-500MiB repair gap) and deduplicate frame-rate parsing within the scanner package. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: rxwatcher <rxwatcher@users.noreply.github.com> Co-authored-by: Quick104 <31828688+Quick104@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |