Convert .m4a files to .mp3 format (with tags)

A Perl utility I wrote to convert .m4a files to .mp3 format. It will also pull the tags over from m4a format. If there are no m4a tags, the script will die. (But of course you can just comment that part out.)

Here is the direct link to the script: m4a2mp3.pl

Note: I’ve updated the code to reflect my more current programming style. If I had time to re-do this, I’d have used IPC::Open3 or something else for IPC, instead of the system call used.


#! /usr/bin/perl
#
# name: m4a2mp3.pl
# description: Convert m4a file to mp3 format. Attempts to convert tags.
# developer: Nathan G. Marley
# date: 2011Sep10
# ========================================================================

use strict;
use warnings;
use feature qw(say);
use Carp;
use MP4::Info;
use MP3::Tag;
use Getopt::Long;

if ( !@ARGV ) {
croak("usage: $0 <...>\n");
}

my @m4atags = qw ( YEAR ARTIST GENRE TRACKNUM TIME
TITLE ALBUM ENCODING BITRATE );

sub main {

for my $file ( @ARGV ) {
my $m4atags = get_m4a_tags( $file );
my $mp3file = convert_m4a_2_mp3( $file );
my $rc = tag_mp3_file( $mp3file , $m4atags );
}

}

main();

sub get_m4a_tags {
my $filename = shift;
my $taginfo;

my $tag = get_mp4tag($filename)
or carp("No TAG info");

for my $t ( @m4atags ) {
$taginfo->{ $t } = $tag->{$t};
}

return $taginfo;
}

sub convert_m4a_2_mp3 {
my $m4afile = shift;
my $mp3file;

($mp3file = $m4afile) =~ s/\.m4a$/.mp3/;

if ( -e $mp3file ) {
carp("error: MP3 file '$mp3file' already exists.");
return;
}

my $faad_opts = "-q -o -";
my $lame_opts = "-S -v -V 0";
my $cmd = "faad $faad_opts \"$m4afile\" | lame $lame_opts - \"$mp3file\"";

my $rc = system($cmd) >> 8;
if ( 0 != $rc ) {
croak("error: Couldn't convert m4a file to mp3 format");
}

return $mp3file;
}

sub tag_mp3_file {
my ( $mp3file , $tags ) = (@_)[0,1];

my $mp3 = MP3::Tag->new($mp3file);

# scan file for existing tags
$mp3->get_tags;

if (exists $mp3->{ID3v1}) {
$mp3->{ID3v1}->remove_tag;
$mp3->new_tag("ID3v1");
}

if (exists $mp3->{ID3v2}) {
$mp3->{ID3v2}->remove_tag;
$mp3->new_tag("ID3v2");
}

$mp3->title_set ( $tags->{TITLE} );
$mp3->artist_set( $tags->{ARTIST} );
$mp3->album_set ( $tags->{ALBUM} );
$mp3->year_set ( $tags->{YEAR} );
$mp3->genre_set ( $tags->{GENRE} );
$mp3->track_set ( $tags->{TRACKNUM} );

$mp3->update_tags(); # Commit to file
$mp3->close();

return;
}