Skip to content

Read self-contained .m4s fragmented MP4 videos (#354) - #603

Merged
KnifeLemon merged 1 commit into
mainfrom
feature/m4s-reader
Oct 26, 2026
Merged

KnifeLemon merged 1 commit into
mainfrom
feature/m4s-reader

Conversation

@KnifeLemon

Copy link
Copy Markdown
Owner

Closes #354

What it does

  • .m4s is a read-only video (FormatRegistry: m4s, video, Writable: false). A self-contained one, ftyp + moov at the start and then styp / sidx / moof / mdat fragments (the layout in the report, written by GPAC), is a fragmented MP4 that FFmpeg reads directly, so it goes to every video and audio target like USM or the raw H.264 / H.265 streams.
  • A DASH media segment gets a clear message. When the top-level boxes of an .m4s reach a moof before any moov, the piece only plays with a separate init segment. DashSegment checks this at the start of MediaInfo.ProbeAsync, so every FFmpeg path (convert, cut a clip, merge, frames) refuses it with ConversionRefusedException("error.m4s_needs_init") before ffprobe runs, instead of showing FFmpeg's demuxer error. Files that aren't box structures, or are damaged, are still left to FFmpeg. Only .m4s files are checked.
  • Settings schema 48: existing libraries' video donut learns .m4s; custom claims stay put. (feat(fonts): read bitmap .fon and convert each size to TTF, OTF, WOFF, WOFF2 and EOT #561 also uses 47 and will need renumbering when it lands.)
  • i18n: error.m4s_needs_init in all 17 language files (Korean in 해요체).
  • Docs: a paragraph in docs/ENGINES.md next to USM. The README count goes 263 → 265 in all 14 READMEs: the registry now has 265 entries. The FIT reader (Read Garmin FIT activities into the geospatial formats (#451) #530) added one without bumping the count.

Tests

  • DashSegmentTests (no FFmpeg): init-segment detection on synthetic boxes (bare segment, ftyp+moov+fragments, moov at the end, non-BMFF and cut-short data), and only .m4s names are refused.
  • M4sFormatTests (Core): registry entry, video profile, the 47 → 48 migration runs once.
  • MediaTests: the route (m4s → mp4 is one FFmpeg step, nothing writes m4s). With FFmpeg installed, a 2 s fragmented MP4 is generated (frag_keyframe+empty_moov+default_base_moof) and rewritten to the reporter's layout with a styp before each moof. It converts to MP4 with video and audio. The same fragments without ftyp + moov fail with error.m4s_needs_init. No sample files are added.

Ran locally with FFmpeg 9.0.2 fetched by build/fetch-engines.ps1: Filee.Engines.Tests 1827 passed / 83 skipped / 0 failed, Filee.Core.Tests 627 passed, the App localization/settings tests 204 passed. dotnet format --verify-no-changes is clean.

🤖 Generated with Claude Code

An .m4s that starts with ftyp + moov and then holds styp / sidx / moof /
mdat fragments (GPAC and some downloaders save them) is a fragmented MP4
FFmpeg reads directly: it becomes a read-only video source with every
video and audio target, like USM and the raw H.264 / H.265 streams.

A DASH media segment, whose top-level boxes reach a moof before any moov,
only plays with its separate init segment. MediaInfo.ProbeAsync now
refuses such an .m4s before ffprobe runs, with error.m4s_needs_init in
all 17 languages, instead of FFmpeg's demuxer error.

Settings schema 48 adds .m4s to the video donut of existing libraries.
The README format count goes to 265, the registry's count (the FIT
reader had not bumped it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@KnifeLemon KnifeLemon added the formats New formats and engines label Oct 26, 2026
@KnifeLemon KnifeLemon self-assigned this Oct 26, 2026
@KnifeLemon
KnifeLemon merged commit d78666b into main Oct 26, 2026
9 checks passed
KnifeLemon pushed a commit that referenced this pull request Oct 26, 2026
Keep both schema steps: v47 learns .fit and .fon, v48 learns .m4s (#603).
Keep the error.fon_* and error.m4s_needs_init keys in every language file.
README format count 265 -> 266 (the registry now has .fon too).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ApPC2ToT2xB1UGEZCUBD4q
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

formats New formats and engines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Format request: .m4s

1 participant