How to Convert wav to m4a with Tags Toyota Car Navigation Can Read
When playing an SD card on a Toyota factory navigation unit, an m4a made with ffmpeg plays sound, but the track title, artist name, and album name all show (NO DATA). If you remake it with afconvert, which comes standard with macOS, they become readable.
What works
afconvert -f m4af -d aac -b 256000 input.wav output.m4a
Write the tags with mutagen.
from mutagen.mp4 import MP4
f = MP4("output.m4a")
f["\xa9nam"] = ["Track Title"]
f["\xa9ART"] = ["Artist Name"]
f["aART"] = ["Artist Name"]
f["\xa9alb"] = ["Album Name"]
f["trkn"] = [(4, 25)]
f.save()
afconvert puts the moov atom at the head of the file from the start, and also reserves a free area for tags. No post-processing equivalent to -movflags +faststart is needed.
Do not pass the file through ffmpeg after writing the tags. Even with -c copy, the container is rebuilt in ffmpeg's format and it becomes unreadable again.
Why ffmpeg output fails
Because the navigation unit's parser hardcodes the hdlr atom as a fixed 34 bytes.
hdlr has a variable-length name field at the end, so its size changes depending on the writer.
meta > hdlr |
mdia > hdlr |
|
|---|---|---|
| iTunes / afconvert | 34 (name is two zero bytes) | 34 (empty name) |
| ffmpeg | 33 (name is one zero byte) | 45 (name is "SoundHandler") |
If you calculate the position of the next atom with 34 bytes hardcoded, then in an ffmpeg-made file you end up reading a place 1 byte off as the start of ilst. It picks up garbage there and decides there are no tags. Reading the audio track goes through a different path, so only playback succeeds.
ffmpeg also adds edts (edit list) to trak, and sgpd / sbgp to stbl. iTunes and afconvert write none of these.
What does not work
None of the following changed what the navigation unit displayed.
- Move moov to the head of the file with
-movflags +faststart - Make
ftypthe same as iTunes (setminor_versionto 0, includemp42incompatible_brands) - Add album art (
covr) - Remove extra tags (the
©cmtcomment, the©tooencoder name) - Lower the sampling rate from 48kHz to 44.1kHz. It plays at 48kHz anyway
- Rewrite the tags of the ffmpeg-made file with mutagen. mutagen does not rewrite
hdlr, so ffmpeg's 33 bytes stay as they are
I also tried a patch that rewrites hdlr from 33 to 34 bytes at the byte level, but this is not enough either. It cannot be read while mdia > hdlr is still 45 bytes. The approach of removing ffmpeg's differences one by one is not worth it.
Copy protection (CPRM / SD-Audio) is also unrelated. CPRM-protected music goes into the SD_AUDIO folder as encrypted files, and the key is written to the card's protected area. A file that was only copied with Finder cannot, in principle, take that form, and if the card has no SD_AUDIO folder it is a different matter to begin with.
Checking a file you already have
Look at the size of hdlr and you know before putting the card in the actual unit.
import struct
import sys
d = open(sys.argv[1], "rb").read(400000)
i = d.find(b"mdirappl") # the meta hdlr sits just before mdir/appl
h = d.rfind(b"hdlr", 0, i)
print("meta hdlr:", struct.unpack(">I", d[h - 4:h])[0])
f = d.find(b"hdlr") # the first hdlr in the file belongs to mdia
print("mdia hdlr:", struct.unpack(">I", d[f - 4:f])[0])
If both are 34, it can be read. If 33 or 45 comes out, it was made with ffmpeg and cannot be read as is.
Isolating the cause in the car
Playback itself succeeds, so just looking at the files does not get you to the cause. The fast way is to make a test folder lined up with files made under different conditions and try them all in one drive.
There are 2 tricks.
Put the condition name in the title tag. If you set the title tag of T2.m4a to TAG2 OK, you can tell at a glance from the driver's seat: if the screen shows TAG2 OK it is reading the tag, and if it shows T2 it is falling back to the file name.
Mix one MP3 with ID3v2 tags into the same folder as a control. If that MP3 can be read and the m4a cannot, the cause is narrowed down to the m4a container structure. Factors that apply equally to every file in the same folder, like the state of the card or the behavior of the navigation unit, are ruled out by this.
We look forward to discussing your development needs.