Skip to content

fix(mp4): preserve duplicate trak boxes during tag rewrite - #14

Merged
RouHim merged 1 commit into
mainfrom
fix/preserve-mp4-tracks-complete
Aug 30, 2026
Merged

RouHim merged 1 commit into
mainfrom
fix/preserve-mp4-tracks-complete

Conversation

@RouHim

@RouHim RouHim commented Aug 30, 2026

Copy link
Copy Markdown
Owner

Summary

Extends #13 to also fix the same duplicate-trak loss in RelocateMP4Editor.

  • ReplaceMP4Editor.copy: build the fallback MP4 output from the complete edited moov (new Movie(source.getFtyp(), edit, source.getOthers())) instead of iterating NodeBox.replaceBox per child.
  • RelocateMP4Editor.relocate: clear() + addAll instead of per-box replaceBox — same root cause (see below).
  • Add regression test testGrowingTagPreservesAllTracks (from fix: preserve MP4 tracks during tag rewrite #13) covering audio + chapter/data tracks.

Closes #13
Supersedes #13 — includes original fix by @Marcelwalter, adds Relocate patch and keeps attribution via Co-authored-by.

Why

NodeBox.replaceBox(Box) does removeChildren(fourcc) + add(box). Replacing trak boxes individually therefore removes every trak each iteration and leaves only the final track. For multi-track MP4/M4B (e.g. soun/odsm/sdsm chapter files) the fallback write path produces a much smaller file without playable audio.

Both editors had the same loop:

for (Box box : edit.getBoxes()) moovBox.replaceBox(box);

This PR fixes both:

  • ReplaceMP4Editor (fallback via Flatten) — the reported path
  • RelocateMP4Editor (fallback via writeMovie when moov is relocated to EOF)

InplaceMP4Editor.modify already uses clear()+addAll and is not affected.

Testing

  • ./mvnw -Dtest=org.jaudiotagger.tag.mp4.M4aWriteTagTest#testGrowingTagPreservesAllTracks — pass
  • ./mvnw -Dtest=org.jaudiotagger.tag.mp4.M4aWriteTagTest — 31 tests passed (30 + new)
  • Manual: original M4B from fix: preserve MP4 tracks during tag rewrite #13 retains audio + cover art + duration after growing comment

Credits

Original diagnosis, fix and test by @Marcelwalter in #13 — retained here with Co-authored-by. Relocate fix added in this PR.

Fixes #13

Build the fallback MP4 output from the complete edited moov instead
of iterating NodeBox.replaceBox per child. replaceBox removes every
child with the same fourcc, so replacing trak boxes individually leaves
only the final track and produces a truncated file without playable
audio.

- ReplaceMP4Editor.copy: construct new Movie from source ftyp/others +
  the fully-edited moov (includes all trak boxes)
- RelocateMP4Editor.relocate: clear + addAll instead of per-box
  replaceBox — same duplicate-fourcc loss (e.g. soun/odsm/sdsm in M4B)
- Add regression test testGrowingTagPreservesAllTracks (test16.m4a:
  soun, odsm, sdsm) that forces the grow-path via a large comment

Fixes #13
Supersedes #13
Co-authored-by: Marcelwalter <36072734+Marcelwalter@users.noreply.github.com>
@RouHim
RouHim merged commit 03bb24b into main Aug 30, 2026
6 checks passed
@RouHim
RouHim deleted the fix/preserve-mp4-tracks-complete branch August 30, 2026 08:15
github-actions Bot pushed a commit that referenced this pull request Aug 30, 2026
## [2.0.31](2.0.30...2.0.31) (2026-08-30)

### Bug Fixes

* **ci:** install missing semantic-release plugins for release ([a683f31](a683f31))
* **ci:** pin conventional-changelog-conventionalcommits to v9 ([2a89302](2a89302))
* **mp4:** preserve duplicate trak boxes during tag rewrite ([#14](#14)) ([03bb24b](03bb24b)), closes [#13](#13) [#13](#13)
@RouHim

RouHim commented Aug 30, 2026

Copy link
Copy Markdown
Owner Author

🎉 This PR is included in version 2.0.31 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant