Overcoming Toyota USB Filesystem Limits

by kmoser

As a car owner who enjoys listening to music, I've dealt with various media formats over the decades, from cassette tapes to CDs to iPod/MP3 players.

Most of these suffer from one or more disadvantages:

  • Media prone to degradation (cassette, CD)
  • Media not compatible with the car's reader (I'm looking at you, cheap CD-ROMs!)
  • Poorly wired 1/8-inch (3.5 mm) jack connections subject to noise (external iPod/MP3 player)

My latest car, a Toyota Corolla, has a USB port which lets you insert a USB stick containing MP3 files as well as other audio formats.

Unlike plugging an external music player into the AUX audio jack, the car's built-in infotainment system ("automotive head unit" in engineer parlance) is capable of reading the MP3 files and displaying their metadata.

The advantages of a USB stick over other media are manifold:

  • Media less prone to degrading.
  • Most common audio formats are compatible.
  • USB connection more reliable than 1/8-inch (3.5 mm) jack.
  • Can store a ton of music on one stick.
  • For all the advantages of USB-based music, though, I've found the car's software has a few limitations.  According to the user manual:
    • Max directory hierarchy: 8 levels
    • Max number of folders in a device: 999 (including root)
    • Max files in a device: 9,999
    • Max files per folder: 255

Now, you may wonder what the problem is: surely even the most avid audiophile won't exceed these limits, right?

Well, it's not that simple.  Unlike most people, I don't have any playlists: my entire audio collection (many hundreds of songs) is the one and only playlist.  That means when I set the player to "shuffle," I want it to randomly pick one of those hundreds of songs.

Simple: just put the songs into separate folders, no more than 255 files per folder, right?  Nope!

Once the player plays a song from a given folder, it will continue to play (random) songs from that same folder.  In fact, even within a folder, the car will be "smart" enough to group songs by artist and album based on their ID3 tags.  This can be a blessing and a curse: on the one hand, it's nice to have songs organized into those categories.

On the other hand, if "random" behaves like "stay within this album/folder," then it's not what I want.

Once I noticed that the car grouped songs by artist and album, I began to experiment with changing their ID3 tags in the hopes of coercing the car to group them differently.  It turns out that you can indeed place more (way more!) than 255 files in a folder, and the car will even recognize them, but for it to consider everything one giant list (rather than multiple lists grouped by artist or album), you have to give every song the same artist and album name (thankfully the titles can be different!).

This discovery was a major breakthrough, so I wrote a script to make a car-compatible version of all my MP3s by changing all the artist names to Artist and all the album names to Album.

But I wasn't quite out of the woods yet.  With the artist and album names now effectively gone, how was I going to see them on the infotainment system?

Fortunately, my songs were already named in the format [Artist] - [Song].mp3 which should be good enough since I don't care to see album names anyway.

However, another annoying thing about the infotainment system is that the song title is only displayed on one line, and that means long songs get truncated.  (There's a way of scrolling it, but you have to do it manually by pressing a button on the infotainment system - not very safe when you're driving.)

I modified my script to also remove spaces from the song filename before updating the ID3 tag.

That means a song named: Foo Bar Baz Bat Fighters - I'm in Love with a German Film Star

Would be tagged with the (somewhat shorter) title: FooBarBazBatFighters-I'mInLoveWithAGermanFilmStar

PascalCase FTW!

I also did a few other text substitutions, such as removing unnecessary words like leading The (so The Beatles becomes just Beatles) and changing For to 4 (so Money For Nothing becomes Money4Nothing).

Now my car happily reads the entire USB stick and "random" happily cycles through random songs from the entire list.  Success!

Well, mostly.

Sometimes the car will stop reading the list of songs somewhere midway and only recognize the first few hundred.  However, a quick tap on the "random" button gets the car to instantly recognize all the songs again.

Upon starting the car, it will attempt to read the contents of the entire USB stick.  Fortunately, it will continue playing immediately where it left off while still reading the stick, which is good.

But if the song ends before it has finished reading the entire directory, the next song played will always be the first song in the directory.  But fortunately, the process of reading the directory only takes a minute or so.

My solution: just before turning off the car, skip to a new song, so next time the car starts I'll be at the beginning of a song, giving the car a few minutes to read the USB directory before the song ends.

My PHP script relies on the existence of the ID3.EXE executable for Windows; if you're using another OS, you'll have to tweak it.

mp3-rename.php:

<?php
function cook($s) {
  $r = preg_replace(
    [
      '/,/',
      '/\s+/',
      '/^The /',
      '/For /',
    ],
    [
      '',
      '',
      '',
      '4',
    ],
    ucwords($s)
  );
  return $r;
}

foreach (glob('*.mp3') as $filename) {
  // Filename is in this format: "Artist - Title.mp3"
  // Extract Title:
  $title = preg_replace('/^.*? - /', '', pathinfo($filename, PATHINFO_FILENAME));
  $artist = preg_replace('/ - .*$/', '', pathinfo($filename, PATHINFO_FILENAME));

  $title = cook($title);
  $artist = cook($artist);

  // Square brackets in filenames cause ID3.EXE to not find the file, so we have to replace them with "?" in our filespec:
  $cmd = 'id3.exe -a "Artist" -l "Album" -t ' . escapeshellarg($title . '-' . $artist ) . ' -M "' . preg_replace('/[\[\]]/','?', $filename) . '"';

  echo "$cmd\n";
  exec( $cmd );
}
?>

Code: mp3-rename.php




id3 0.78 (2006080)
usage: id3 [-1 -2 -3] [OPTIONS] filespec ...
 -v             give verbose output
 -d             clear existing tag
 -t <title>     set tag fields
 -a <artist>
 -l <album>             (i'th matched `*' wildcard  = %1-%9,%0
 -n <tracknr>            path/file name/counters    = %p %f %x %X
 -y <year>               value of tag field in file = %t %a %l %n %y %g %c)
 -g <genre>
 -c <comment>
 -D <filename   duplicate tags read from filename
 -f <template>  rename files according to template
 -q <format>    print formatted string on standard output
 -m             match variables in filespec
 -R             search recursively
 -M             preserve modification time of files
 -V             print version info
Only on last selected tag type:
 -s <size>      set tag size
 -E             only write if tag already exists
 -u             update all standard fields
 -rTYPE         erase all `TYPE' frames
 -wTYPE <data>  write a `TYPE' frame

Report bugs to <squell@alumina.nl>.
Return to $2600 Index