Skip to content

feat: import footage from any common phone, camera or recorder container - #48

Merged
ralyodio merged 1 commit into
masterfrom
worktree-video-formats
Aug 11, 2026
Merged

feat: import footage from any common phone, camera or recorder container#48
ralyodio merged 1 commit into
masterfrom
worktree-video-formats

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

The bug

On a project page, the Footage picker showed only .mp4 files — an input.webm was unselectable even though .webm has been in the server's allowlist since the first commit.

The accept attribute filtered by MIME type alone:

accept="video/mp4,video/quicktime,video/x-matroska,video/webm"

The browser has to map those MIME types back to extensions through the platform's mime database, and on Linux that map is routinely incomplete. The drag-and-drop path applies no filter at all, which is why the same file imports fine when dropped — that asymmetry is what pins the fault to the dialog rather than the server.

The fix

  • Lead accept with explicit extensions. The browser matches those directly, with no platform lookup in the way. MIME entries stay for pickers that group by type, plus video/* so an unenumerated container is still reachable.
  • Widen the server allowlist past the five MVP containers to what phones, action cams, drones, camcorders, dashcams and broadcast bodies actually write: AVCHD (.mts/.m2ts/.m2t/.ts), 3GPP, .avi, the MPEG-program family, .wmv/.asf, .mxf, MiniDV, .ogv, .insv, and raw elementary streams.

Widening is safe because the extension is only a cheap pre-check, run before a byte moves so a 4 GB import fails in the dialog rather than twenty minutes later. ffprobe remains the authority on whether footage is usable — anything it cannot demux is still rejected on the real bytes. So the cost of a wide list is at most a slightly later error on a file that was never going to work, against the cost of a parent who cannot import what their camcorder produced.

Camera raw (.braw, .r3d, .ari) needs vendor SDKs ffmpeg does not ship, so it stays out and the docs say to transcode first.

Note on the duplicated list

apps/web/src/accept.ts restates the extensions rather than importing SUPPORTED_EXTENSIONS from @reeleel/core: that module is bundled for the browser by esbuild, and core reaches for node:fs. accept.test.ts asserts parity in both directions, so the picker filter and the server allowlist cannot drift.

Verification

  • pnpm test:run — 621 passed, 8 skipped (63 files), including 11 new tests
  • pnpm lint, pnpm typecheck — clean
  • pnpm build — clean, including the browser bundle, which confirms no node builtins leaked into accept.ts
  • prettier — the 4 modified files already failed on master (88 files repo-wide); the 3 new files pass, so no formatting debt is added

🤖 Generated with Claude Code

The project page's file picker filtered by MIME type alone
(video/mp4,video/quicktime,video/x-matroska,video/webm). The browser has to
map those back to extensions through the platform's mime database, and on
Linux that map is routinely incomplete — so the dialog showed only .mp4 and
an input.webm the server would have happily imported was unselectable. The
drag-and-drop path applies no filter, which is why the same file worked when
dropped.

Lead the accept attribute with explicit extensions, which the browser matches
directly with no platform lookup in the way, and keep the MIME entries for
pickers that group by type.

Widen the server allowlist past the five MVP containers to what phones,
action cams, drones, camcorders, dashcams and broadcast bodies actually
write: AVCHD (.mts/.m2ts/.m2t/.ts), 3GPP, .avi, the MPEG-program family,
.wmv/.asf, .mxf, MiniDV, .ogv, .insv and raw elementary streams. The
extension stays a cheap pre-check so a large import fails in the dialog
rather than after the bytes move; ffprobe remains the authority on whether
footage is usable, so a wider list costs at most a later error on a file that
was never going to work. Camera raw (.braw/.r3d/.ari) needs vendor SDKs
ffmpeg does not ship, so it stays out.

The picker list is duplicated in apps/web/src/accept.ts rather than imported
from core, because that module is bundled for the browser and core reaches
for node:fs; accept.test.ts asserts the two cannot drift.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ralyodio
ralyodio force-pushed the worktree-video-formats branch from 85f265a to d61f436 Compare August 11, 2026 09:40
@ralyodio
ralyodio merged commit dced50c into master Aug 11, 2026
4 checks passed
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.

1 participant