Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Convert FLACs to MP3

by davis (Vicar)
on Oct 22, 2004 at 20:36 UTC ( [id://401680]=sourcecode: print w/replies, xml ) Need Help??
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.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://401680]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (3)
As of 2024-04-25 19:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found