It was not long ago that I purchased a Samsung Admire as my first smartphone. I bought it for two reasons: 1) It runs on Linux 2) It multi-tasks. With the Android OS, I believed it was possible to ditch my GPS and my iPod while out on runs, rides, or for any other reason.
The Samsung has done well in both respects, but this is not a review of the Samsung nor of the Android OS. Instead, when I chose to use the Android as my ‘music player of choice’, I fell into a serious conflict problem…and it’s name is Amazon vs. iTunes.
I know of no iTunes app for the Android OS. In addition, I have a rather large collection of music already saved in a format for iTunes. However, I do have access to the individual music files because I was only running iTunes in a virtual XP box on my Ubuntu laptop. I thought that porting them over to an mp3 format and uploading to my free cloud drive on Amazon would be a breeze.
No way. Not happening. I could use gzip and ffmpeg to extract and convert the m4a files in my iTunes folder. The converted mp3 files also played fine and could be uploaded to the Amazon Cloud Drive. But, that is where happiness ended.
When I used the Amazon Cloud Player app on my Android OS phone, the files I had uploaded all got dumped into the ‘Unknown album’ folder. Most of the song names also ended up with a great deal of gobbledy-gook added to the song names and made it difficult to read. However, any songs I purchased on Amazon appeared just perfectly peachy in the Cloud Player as well as in the music player of the Samsung. OK, re-purchasing all my already purchased songs on Amazon was not an option.
I did no short amount of searching and looking for a solution for the problem when I happened to accidentally stumble upon the answer. It seems that Amazon’s Cloud Player does not care what the filename of the song is. It only cares what is kept in the “metadata tags” of the song. Metadata tags are text variables (my interpretation) that give descriptive information about the audio, video, or image file to which they belong. With an experiment, I discovered that when I ran ffmpeg to convert from the m4a to an mp3 file, metadata tags were not copied as well. After conversion, I ran a converted mp3 through mplayer and saw that only the song name was there; no artist, no album. Additionally, even if they had been, they would have been incorrect as m4a utilizes the ‘artist’ tag while the mp3 uses ‘author’ for the same variable.
Now, I did find a way to do the conversion and load the metadata tags all at once. However, that left me with the prospect of copying the m4a to a temp folder, extracting the m4a from the gzipped file, extracting the metadata tags, and then building a long command line for each of over 500 music files. This did not count also that I wished to strip out leading numerals, punctuation, and replace the spaces with underscores at the same time. I needed a script.
Since I have been trying to learn Perl, I thought this was a good time to try it out. It seemed easy…right? While it was not the easiest I have done, it only took about four hours total work on the scripts over two days. I wrote two scripts: one to correctly rename the music files how I wanted them, and one to create the conversion process. In between these, I would use gunzip to extract the compressed m4a files. If you are not concerned about oddly named files, you may only need the conversion script.
I did this on an Ubuntu laptop. I do know that one can run ffmpeg and Perl on a Windows machine. However, I do not know what changes might be required to accomplish this task on that platform. You will need another helper app also; exiftool. I don’t know if this is available on Windows or not. If you can find another command line tool that can extract metadata tags; you should be able to recreate this on Windows. I did try to use ffmpeg to extract tags, but it’s output does not correctly go to STDOUT, nor does it seem to go to STDERR.
Also, though I am publishing both of these scripts for anyone to use or modify, I ask for credit at least on the m4aconvert.pl if you do modify and re-publish. I am sure that both of these can be gussied up if someone were to take the time. The itunesren.pl script is based on answer given on Perl Monks forum by John Lawrence. All that I added is the extra substitution patterns I needed for my files. The bulk of that script is Mr. Lawrence’s.
Both of these scripts will work better if you add them into your local BIN folder which should be on your PATH. Look up how to do that if you need to. Also, both work best if the only files in the folder you are working on are the gzipped m4a files. The presence of other files will cause both to emit errors or malfunction entirely.
First step; ITUNESREN.PL
Usage: itunesren.pl *
#!/usr/bin/perl
#
# Renaming music files containing
# spaces, punctuation, and leading
# numbers.
#
# modified by DEV on 5/24/2012use strict;
use warnings;foreach $_ (@ARGV) {
my $oldfile = $_; #copy input record into oldfile
s/[0- 9] //g; #clean out numerals
s/\.ma\.gz/\.m4a\.gz/g; #put 4 back in m4a
s/^ //g; #remove leading space
s/& //g; #remove ampersands
s/[()]//g; #remove parentheses
s/-//g; #remove dashes
s/ /_/g; #replace spaces with underscore
rename($oldfile, $_); #now, rename the file $_ into $oldfile}
Some notes you will want to know are: the ‘s/ /_/g; line has an actual SPACE between the first two slashes, and the ‘s/-//g;’ substitution was not tested as I had used another substitution that removed the dashes (and most everything else as well). It might have to be ‘escaped’ instead (i.e. s/\-//g;).
If you notice that most of the lines in this script do not seem to be acting upon any variables, that is because Perl has a built in ‘input record’ variable ($_). Each of my substitutions is working upon this variable and so it does not have to be actually mentioned. I store the original filename at the beginning and then modify the input record during the script before loading it back into the real filename at the end.
Second Step: You now should have all your filenames like you like them (or how I like them). It’s possible not to use step one if you don’t wish to. At this point all you need is the command ‘gunzip *’) to extract the compressed files. You’ll be left with must the m4a native files.
Third Step: m4aconvert.pl
Usage: ls|m4aconvert.pl
#!/usr/bin/perl -w
#
# Convert itunes *.m4a files to *.mp3 files
# Will read entire directory contents as input
# Also reads m4a metadata and writes to new mp3 file
# Requires: ffmpeg and libmp3lame codec
# Written by: Dave Vest on 5/26/2012
#
# Usage: ls|m4aconvert.pl# Loop through all input files
while (<>){# Chomp is used liberally to remove \n from input
# Required in order to build final ffmpeg stream.
# exiftool extracts metadata tag according to value
# You supply the tagname and it extracts the valuechomp($tag1 = `exiftool -q -title $_ `);
# Build metadata tag variable from exiftool return
# exiftool returns; “Title : title”
# split at ‘:’ and return what is to its right$title = ” -metadata title=\”" . (split /: /, $tag1 )[-1] . “\”";
# Do it again for each tag.
chomp($tag1 = `exiftool -q -artist $_ `);
$author = ” -metadata author=\”" . (split /: /, $tag1 )[-1] . “\”";
chomp($tag1 = `exiftool -q -album $_ `);
$album = ” -metadata album=\”" . (split /: /, $tag1 )[-1] . “\”";
chomp($tag1 = `exiftool -q -year $_ `);
$year = ” -metadata year=\”" . (split /: /, $tag1 )[-1] . “\”";
chomp($tag1 = `exiftool -q -genre $_ `);
$genre = ” -metadata year=\”" . (split /: /, $tag1 )[-1] . “\”";# chomp removes ‘\n’ from input filename
# get input filename into a variable.chomp;
$infile = $_;# split the .m4a off of the filename
$fname = (split /\./, $_ )[0];
# Put .mp3 onto filename for output file of ffmpeg
# also add a space in front for the command line$outfile = ” ” . $fname . “\.mp3\n”;
# Now, build the command line string for ffmpeg
# for the current filename and set up all
# metadata tags. Note: ‘author’ is ‘artist’ for mp3 files.$ffmpegstr = “ffmpeg -i ” . $infile . ” /
/ -acodec libmp3lame -ab 160k “
/ . $title . $author . $album
/ . $year . $genre . $outfile;# Call system to run ffmpeg for the current file.
system($ffmpegstr);
}
Some important notes for this file are: The line continuations that I have used (/) in the line where the command is built should not be in your final script. My script line was too long for WordPress and needed shortening. Remember to remove these when you create your script, and the chomp’s are critically important. Everything that you read from exiftool or from the input record contains a newline character (\n) that must be stripped before it can be utilized in the command line. I spent several hours trying to figure out why ffmpeg kept telling me I had no output file. It was because I read in the $infile variable and it came with it’s own newline. That truncated my command and caused the rest of the variable to end up on the second line and thus, no output file name. Finally, those quote-looking things around the exiftool commands are back-quotes. They are not regular quotes. Back-quotes work like the system() function in the last line, but return the output value of the system command.
Both of these scripts should work as is, but I recommend segregating copies of your iTunes song files into a temp folder of some kind. DO NOT TAKE ACTION ON YOUR ORIGINAL FILES! These scripts are destructive.
When complete, you will be left with a folder of m4a and mp3 files with the same names. Do a wildcard delete (rm *.m4a) of the original iTunes files and you will now be ready to upload your mp3 files to the Amazon Cloud (or Cloud Player). The Cloud Player will interrogate the metadata tags and properly set up your song, album, and artist names so that things look correct. This will also allow the Cloud Player app on your Android phone to hunt down the album art. All except the album art will carry through as you download songs to your Android phone.
There are lots of possibilities from here. There could be a change to just allow you to specify the folder to take action upon as a command line argument. Someone could gussy it up for a GUI environment. It could also use some security features so if it discovers a file name that doesn’t end in m4a or if it encounters a folder name, then it could just bypass and go on to the next record. Lots of things that can be done and maybe I might get round to them, or you can.
This project helped me learn a lot of things. It gave me confidence in writing Perl scripts. It helped me learn a lot about the interaction between audio/video files and the apps that store and play them. It also helped me learn more about using Unix/Linux and the Android OS. Even though for me this is a one-shot app, it has been good for learning more about computers and the languages that program them. Hack on!