Sunday, February 3, 2008

Script to convert .m4a to .mp3

Put all your .m4a files (that you want to convert) into a folder and execute the following script from within this folder, make sure to make this script executable (chmod 777 m4a2mp3.sh)

#!/bin/sh
# name of this script: m4a2mp3.sh
# m4a to mp3

for i in *.m4a; do
  faad "$i"
  x=`echo "$i"|sed -e 's/.m4a/.wav/'`
  y=`echo "$i"|sed -e 's/.m4a/.mp3/'`
  lame -h -b 192 "$x" "$y"
  rm "$x"
done

Dependencies
faad2 and lame


12 comments:

  1. May I introduce ffmpeg? You can reduce your dependencies to just ffmpeg and skip creating the wav files.

    Also, using shell expansion to create your set will break when you get a dir with a very large number of files in it.

    Further, bash does substring matching, so sed is not needed.

    So you could simply do this:

    #!/bin/bash
    for i in $(ls -1 | grep '.*m4a'); do
    ffmpeg -i ${i} -sameq ${i%m4a}mp3
    done

    Also, world writable files are never a good idea, changing the mode to 755 would be a much better idea.

    ReplyDelete
  2. Anonymous:

    Small edit; You're completely right about the bash expansion, but you could've used it as well in the for loop. Here's one more small edit:

    #!/bin/bash
    for i in *.m4a
    do
    ffmpeg -i $i -sameq ${i%m4a}mp3
    done

    ...it's often a bit more legible this way, too. I wouldn't worry about large dirs too too much, you have about 125kB of space for any such argument under debian (and probably ubuntu) linux, and i believe under BSD flavors the xargs memory's dynamically allocated.

    In any case, xargs would break at the "grep '*.m4a'" anyhow; it would be smarter to detect large values ahead of time with 'ls' and break the job into pieces if that's the case.

    But at that point, most people will tell you to use perl instead...

    ReplyDelete
  3. Anonymous:

    Small edit; You're completely right about the bash expansion, but you could've used it as well in the for loop. Here's one more small edit:

    #!/bin/bash
    for i in *.m4a
    do
    ffmpeg -i $i -sameq ${i%m4a}mp3
    done

    ...it's often a bit more legible this way, too. I wouldn't worry about large dirs too too much, you have about 125kB of space for any such argument under debian (and probably ubuntu) linux, and i believe under BSD flavors the xargs memory's dynamically allocated.

    In any case, xargs would break at the "grep '*.m4a'" anyhow; it would be smarter to detect large values ahead of time with 'ls' and break the job into pieces if that's the case.

    But at that point, most people will tell you to use perl instead...

    ReplyDelete
  4. You saved my day. I just spent one hour and a half reading old threads suggested by Google about why ffmpeg keeps giving me the stupid error 'Unsupported codec for output stream #0.0'. Linux is such a pain at times. I have all codecs and dependencies and none of the threads I found was useful to me. Your article was useful, my files are converted now. Thanks.

    ReplyDelete
  5. Ryder, how about accommodating for spaces in the file names in your script?

    ReplyDelete
  6. Also got 'Unsupported codec for output stream #0.0' here, for no apparent reason - ffmpeg has made mp3 files for me often enough but today, no way and for no apparent reason. I would have just converted m4a to wav with ffmpeg, then wav to mp3 with lame - but I wanted something more automated and your script works.

    ReplyDelete
  7. Win! Thanks for your post Ryder! That sameq param is great!

    ReplyDelete
  8. #!/bin/bash
    for i in *.m4a
    do
    ffmpeg -i "$i" "${i%.m4a}.mp3"
    done

    Here's mine: it supports filenames with spaces like charm!

    ReplyDelete
  9. I would add -aq 192 (or something simillar) as ffmpeg seems to default to 64 which is too low even for my ears :)

    ReplyDelete
  10. this command:

    faad somefile.m4a

    gives this error (Ubuntu 10.04 Lucid):

    Unable to find correct AAC sound track in the MP4 file.

    Can't get around that.
    Using ffmpeg works, but you must be "careful with that axe, Eugene!":

    The bit rate is in bits/s, NOT kbits/s, therefore, for a constant bit rate of 320 kbps, and 2 channels:

    ffmpeg -i "myfile.m4a" -ab 320000 -ac 2 "myfile.mp3"

    --
    QED.

    ReplyDelete
  11. here is the full bash file contents, the one that works with ffmpeg (you need zenity installed for notification):

    http://pastebin.com/rqis6NX9

    Enjoy :)

    ReplyDelete