Skip to content

Fix: Video keeps playing after compression finishes#2266

Open
shomix wants to merge 1 commit into
mainfrom
shomix-p-improve-ux-when-object-is-replaced
Open

Fix: Video keeps playing after compression finishes#2266
shomix wants to merge 1 commit into
mainfrom
shomix-p-improve-ux-when-object-is-replaced

Conversation

@shomix

@shomix shomix commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

When a video is uploaded in Clips, it initially plays the raw uncompressed file while compression runs in the background. Once compression is done, the original file in GCS is replaced with the smaller compressed version. If someone was watching the video at that moment, two things could go wrong:

  • The browser would get a 416 Requested Range Not Satisfiable error if it tried to read bytes beyond the end of the new (smaller) file.
  • Or it would get a ERR_CONTENT_LENGTH_MISMATCH error if a response was already in flight when the file got swapped.

In both cases, playback would just stop with no recovery.

What changed

Smarter error detection in the MSE loader — the video player uses Media Source Extensions to stream raw fragmented MP4 files. The loader now detects when a 416 error arrives before the expected end of the file (which means the file was replaced, not that we actually reached the end). Both this case and the content-length mismatch case now trigger a clean recovery instead of silently stopping.

Seamless fallback to the native player — when the MSE stream breaks, the player now switches to the standard <video> element using the compressed file, seeks to where the viewer was, and resumes playback automatically if it was playing. From the viewer's perspective it looks like a brief buffer pause.

Fix for a false positive in fragmented MP4 detection — the player has logic to detect whether a file needs the MSE path or can play natively. That detection was doing a raw byte scan that could be fooled by regular MP4 files whose internal numeric data happened to contain the byte sequence it was looking for. It now parses the actual file structure instead, so only real fragmented MP4s go through the MSE path.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

Here's a visual recap of what changed:

Visual recap

Open the full interactive recap

@builder-io-integration builder-io-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Builder reviewed your changes and found 1 potential issue 🟡

Review Details

Code Review Summary

PR #2266 improves Clips playback resilience when an uploaded raw MP4 is replaced by its compressed GCS object. It adds structured fragmented-MP4 detection, distinguishes premature MSE range failures from true EOF when the total size is known, and attempts to recover through a cache-busted native <video> source while preserving position and autoplay state. The overall approach is sound, and the parser tests cover an important false-positive case. Risk level: Standard.

Key Findings

🟡 MEDIUM — The fallback effect only handles a direct mse → native transition. A normal compressed URL replacement can pass through mse → pending → native while the new source is sniffed, bypassing the effect and losing the viewer’s position and playing state. This should preserve the MSE-originated playback state across the pending transition and apply seek/resume when native mode becomes active.

Positive patterns

  • The MSE loader now fails loudly for a 416 that occurs before a known file boundary instead of treating it as EOF.
  • The fMP4 detector walks BMFF box structure rather than scanning arbitrary payload bytes.
  • Existing tests were extended for the false-positive detection regression.

🧪 Browser testing: Attempted after review; skipped as infra-unavailable because browser automation tools were not exposed. The dev server was running, but all planned UI test cases—including the source-replacement flow—were unable to execute.

Comment thread templates/clips/app/components/player/video-player.tsx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants