#!/usr/local/bin/perl =head1 NAME B - transcode FLAC file to MP3 files =head1 SYNOPSIS B [B<--lame-options> I] [B<-q>] [B<-v>] I [...] =head1 DESCRIPTION B transcodes the FLAC files I to MP3 files. I may be the kind of FLAC file B generates. That is, it contains a cue sheet, one TITLE tag per track listed therein, and ARTIST, ALBUM, and DATE tags. Note that lame is retarded, and parses B directly itself! So, in order for it to transcode textual tags, you must specify the encoding in LANG, e.g. LANG=en_US.utf-8 =head1 OPTIONS =over 4 =item B<--lame-options> I Pass I to B. This ends up being passed to the shell, so feel free to take advantage of that. You'll almost certainly have to put I in single quotes. =item B<-q> [B<--quiet>] Suppress status information. This option is passed along to B and B. =item B<-v> [B<--verbose>] Print diagnostic information. This option is passed along to B and B. =back =head1 AUTHORS Written by Eric Gillespie . =cut package epg::flac::archive::mp3; use v5.12; use warnings; use File::Temp; use FindBin; require "$FindBin::Bin/tags.pl"; epg::flac::archive::tags->import( qw[ disc_tags read_tags mangle_for_file_name quote two_digits ]); sub flac2mp3 { my $quoted_flac = quote(shift); my $tags = shift; my ($album, $artist, $date, $discnumber) = disc_tags($tags); # TODO resurrect whole-disc FLAC? # Stupid hack: only a single-track file should have the # TRACKNUMBER tag, so use it if set for the first pass through # the loop. At the end of the loop, we'll set $track for the # next run, so this continues to work for multi-track files. # if track == None: # track = 1 # else: # track = int(track) my $tracknumber = epg::flac::archive::tags::one(TRACKNUMBER => $tags); my $title = epg::flac::archive::tags::one(TITLE => $tags); # TODO restore PARTNUMBER and VERSION next time i need them say('metaflac --export-picture-to=flac2mp3.cover.$$', " $quoted_flac && pic_options=", '"--ti flac2mp3.cover.$$"'); # This is an old TODO; what's wrong with --ty ? # TODO: Look at TDOR, TDRL, TDRC for date. say(join(' ', 'flac', '-cd', $quoted_flac, '|', 'lame', '--id3v2-only', '--id3v2-latin1', '--pad-id3v2-size', 0, '--preset standard', '--ta', quote($artist), '--tl', quote($album), '--tn', quote($tracknumber), '--tt', quote($title), '--ty', quote($date), '$pic_options', #(map { ('--tv', quote("TPE2=$_")) } @{$albumartist}), (map { ('--tv', quote("TPOS=$_")) } @{$discnumber}), '-', quote( mangle_for_file_name( join(' ', $artist, $album, (map { two_digits($_) } @{$discnumber}), two_digits($tracknumber), $title, )) . '.mp3' ) )); say('unset pic_options'); } sub read_tags_metaflac { my $fn = shift; open(my $fh, '-|', 'metaflac', '--no-utf8-convert', '--export-tags-to=-', $fn) || die("metalfac: $!"); my @result = read_tags($fh); if (!close($fh)) { if ($! == 0) { die("metaflac exited $?") } die("close(metaflac): $!") } @result } sub main { for my $fn (@_) { my ($tags) = read_tags_metaflac($fn); flac2mp3($fn, $tags); } say('rm -f flac2mp3.cover.$$'); return 0; } if (!caller) { exit(main(@ARGV)) } 1;