Read and write the iTunes tmpo atom for M4A BPM#74
Merged
Conversation
ffmpeg/ffprobe can neither read nor write the iTunes `tmpo` atom, so the previous `movflags +use_metadata_tags` path wrote BPM as a non-standard `mdta/BPM` key that AVFoundation (and audioplayer) can't read. Add `Mp4Tmpo`, a hand-rolled MP4 atom reader/writer in the style of `AcidChunk`/`CueChunk`. It walks moov → udta → meta → ilst → tmpo → data, reading/writing BPM as a 16-bit big-endian integer — the form Apple Music writes and AVFoundation reads. It creates any missing udta/meta(mdir)/ilst boxes, replaces an existing tmpo rather than duplicating it, handles the meta FullBox quirk, and patches stco/co64 chunk offsets when moov precedes mdat so audio stays valid. Wire `Audio#bpm_from_m4a`/`#write_bpm_to_m4a` to `Mp4Tmpo` and drop the `mdta`-producing movflags line. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
wavesync did all tag I/O through ffmpeg/ffprobe, but ffmpeg can neither read nor write the iTunes
tmpoatom:-metadata BPM=…(with or without+use_metadata_tags, under any muxer/key) never emits atmpoatom. The old+use_metadata_tagspath instead wrote a non-standardmdta/BPMkey.tmpoatom as any tag.tmpois the de-facto standard for BPM in M4A (Apple Music, iTunes, Mp3tag, Picard), and it's what AVFoundation — and therefore audioplayer — reads. Themdta/BPMkey AVFoundation exposes only as an opaque index, so it couldn't be mapped to BPM.What
New
Wavesync::Mp4Tmpo— a hand-rolled MP4 atom reader/writer in the style ofAcidChunk/CueChunk:moov → udta → meta → ilst → tmpo → data, reading/writing BPM as a 16-bit big-endian integer.udta/meta(with anmdirhandler)/ilstboxes, and replaces an existingtmporather than duplicating it.metaFullBox quirk (vs. plain QuickTimemeta).moovprecedesmdat, patches everystco/co64chunk offset by the size delta so audio data stays valid.Audio#bpm_from_m4aand#write_bpm_to_m4anow useMp4Tmpo, and themdta-producingmovflags +use_metadata_tagsline is dropped.Testing
Mp4TmpoTest(round-trip, no-duplicate-atom, still-decodable, preserves existing string tags) + existingaudio_testm4a cases. Full suite: 417 runs, 0 failures. Rubocop and Steep clean.mdtafile, and an iTunesmoov-before-mdatfile: round-trips, stays decodable, and AVFoundation readsitsk/tmpo.Note
The reader now reads
tmpoonly. Files previously tagged by wavesync with the oldmdta/BPMkey will read as no-BPM until re-tagged (re-runningwrite_bpmmigrates them).Companion change in audioplayer reads the
tmpoatom for display.🤖 Generated with Claude Code