Category: Audio Related Programs
Author/Contact Info /msg me
Description: Hand it a playlist, and it'll convert the files in that playlist to MP3 format. This is a script I hacked up and intended to finish properly (add ability to convert to Ogg Vorbis), but never did. FLAC's file attributes (tags) are decided by whoever encoded the file, so you may need to adjust it to suit your needs.
#!/usr/bin/perl

use warnings;
use strict;
use Data::Dumper;
use File::Basename;
use File::Path;
use Audio::FLAC::Header;
use Getopt::Long;

my $selected_output = "mp3";
my $mp3_dir = "../mp3";

my %flac_attribs = (
        file_extension => qr/\.flac/,
        binary         => "/usr/bin/flac",
        decode_arg     => "-d",
        input_arg      => "",
        output_arg     => "-o",
        tags           => {
                year         => { vital => 1, name => "DATE" },
                track_title  => { vital => 1, name => "TITLE" },
                track_number => { vital => 1, name => "TRACKNUMBER" },
                track_artist => { vital => 1, name => "TRACKARTIST" },
                album_title  => { vital => 1, name => "ALBUM" },
                album_artist => { vital => 1, name => "DISCARTIST" },
                genre        => { vital => 1, name => "GENRE" },
                cddb_id      => { vital => 1, name => "CDDB" },
        },
);

my %outputs = (
        mp3 => {
                base_dir         => "../mp3",
                file_extension   => ".mp3",
                binary           => "/usr/bin/lame",
                standard_args    => [ "-h", "-V", "--vbr-new", "--nohi
+st" ],
                input_arg        => "",
                output_arg       => "",
                tags => {
                        year         => "--ty",
                        track_title  => "--tt",
                        track_number => "--tn",
                        track_artist => "--ta",
                        album_title  => "--tl",
                        #album_artist => "",   # Not used by lame
                        genre        => "--tg",
                },
        },
);
foreach my $playlist (@ARGV) {
        open(PLAY, "<", $playlist)
                or die "Unable to open $playlist: $!\n";
        TRACK: while(<PLAY>) {
                chomp;
                my $filename = $_;
                print "Checking $filename...\n";
                unless(check_file($filename)) {
                        warn "Problem with $filename from playlist $pl
+aylist: unreadable/non-existent file!\n";
                        next TRACK;
                }

                my $flac = Audio::FLAC::Header->new($filename);
                unless($flac) {
                        warn "Extracting tags from $filename failed!\n
+";
                        next;
                }
                my $flac_tag_ref     = $flac->tags;

                my @required_tags;
                my %input_tags = %{$flac_attribs{tags}};
                for (keys %input_tags) {
                        push @required_tags, $input_tags{$_}{name} if(
+$input_tags{$_}{vital});
                }

                foreach my $req (@required_tags) {
                        unless($flac_tag_ref->{$req}) {
                                warn "Tag $req not found in $filename\
+n" unless($flac_tag_ref->{$req});
                                next TRACK;
                        }
                }

                my %output_tags;
                foreach my $tag (keys %input_tags) {
                        next unless($outputs{$selected_output}{tags}{$
+tag});
                        $output_tags{$tag} = $flac_tag_ref->{$input_ta
+gs{$tag}{name}};
                }
                my $dirname     = dirname($filename);
                my $target_dir  = $mp3_dir ."/". $dirname . "/";

                unless(-d $target_dir) {
                        unless(mkpath($target_dir)) {
                                warn "Couldn't make path $target_dir: 
+$!\n";
                        }
                }

                unless(-d $target_dir) {
                        warn "Unable to find $target_dir\n";
                        next TRACK;
                }

                my $flac_ext = $flac_attribs{file_extension};
                my $wav_filename = $target_dir . basename($filename);
                $wav_filename =~ s/$flac_ext$/.wav/;

                ## Build the decode command line and run it.
                my @decode_cmd = (@flac_attribs{"binary","decode_arg",
+"input_arg"}, $filename, $flac_attribs{output_arg}, $wav_filename);

                #Remove undef args
                my @temp_cmd = @decode_cmd;
                @decode_cmd = ();
                for (@temp_cmd) {
                        push @decode_cmd, $_ if($_);
                }
                print "Going to decode $filename to $wav_filename\n";
                #print Dumper(\@decode_cmd);
                system(@decode_cmd) == 0
                        or die "Conversion to wav file failed for $fil
+ename: $?\n";
                unless(-e $wav_filename) {
                        die "$wav_filename does not exist\n";
                }


                ## Build the encode command line and run it.
                my %output_attribs = %{$outputs{$selected_output}};
                my $output_ext     = $output_attribs{file_extension};
                my $output_filename = $wav_filename;
                $output_filename =~ s/\.wav$/$output_ext/;
                my @encode_cmd = ($output_attribs{binary});
                push @encode_cmd, @{$output_attribs{standard_args}};
                push @encode_cmd, ($output_attribs{input_arg}, $wav_fi
+lename, $output_attribs{output_arg}, $output_filename);
                foreach my $tag (keys %output_tags) {
                        my $arg = $output_attribs{tags}{$tag};
                        push @encode_cmd, ($arg, $output_tags{$tag});
                }

                @temp_cmd = @encode_cmd;
                @encode_cmd = ();
                for (@temp_cmd) {
                        push @encode_cmd, $_ if($_);
                }
                print "Going to encode $wav_filename to $output_filena
+me\n";
                print Dumper(\@encode_cmd);
                system(@encode_cmd) == 0
                        or die "Conversion to $selected_output file fa
+iled for $filename: $?\n";
                unless(-e $wav_filename) {
                        die "$output_filename does not exist\n";
                }
                unlink($wav_filename);
        }
        close(PLAY);
}

sub check_file {
        my $filename = shift;
        unless(-e $filename) {
                return 0;
        }
        if(-z $filename) {
                return 0;
        }
        unless(-r $filename) {
                return 0;
        }
        return 1;
}
Replies are listed 'Best First'.
Re: Convert FLACs to MP3
by Anonymous Monk on Dec 18, 2004 at 13:37 UTC
    Looks good but Audio::FLAC seems to have disappeared from CPAN.

      Audio::FLAC seems to have moved to Audio::FLAC::Header. I've updated the code to suit. Cheers


      davis
      It wasn't easy to juggle a pregnant wife and a troubled child, but somehow I managed to fit in eight hours of TV a day.