source: flacrip/trunk/flactrack @ 5

Last change on this file since 5 was 5, checked in by peter, 11 years ago
  • mbz: only print non-ref values of the info
  • use-cases: added note about submitting a new discid
  • flactrack:
    • hardcoded the library location for now
    • sort the supplied %TRACKS by their keys
    • remove special characters from the output filename using quotemeta
    • abort with an error message if no MusicBrainz info is found
    • abort with an error message if the flac decoding is canceled
  • MusicBrainz.pm: select the proper medium (by DiscID) as the context for querying the tracklist, so multi-disc releases get the proper tracklist
  • Property svn:executable set to *
File size: 3.4 KB
Line 
1#!/usr/bin/perl -w
2use strict;
3
4# extract one or more tracks from a FLAC file using its embedded cuesheet
5# save those tracks as wav or mp3 files
6# can also run them through a sox filter
7# TODO: separate sox filter for each track!
8
9use Getopt::Long qw{:config no_ignore_case};
10use File::Spec::Functions qw{catfile};
11use File::Path;
12use Audio::FLAC::Header;
13#TODO: put the MusicBrainz lib in a more common location
14use lib qw{/home/peter/projects/flacrip};
15use MusicBrainz;
16
17GetOptions(
18    'D=s' => \my %TRACKS,
19    't=s' => \my $TYPE,
20    'x=s' => \my $SOX_FILTER,
21    'all|a' => \my $ALL,
22    'dir|d=s' => \my $DIRECTORY,
23);
24
25my $FLAC_FILE = shift or die "Need a flac file to decode";
26
27# default to mp3
28$TYPE ||= 'mp3';
29
30# default the directory to be named like the flac file
31($DIRECTORY ||= $FLAC_FILE) =~ s/\.flac$//;
32
33my $flac = Audio::FLAC::Header->new($FLAC_FILE) or die "Can't read FLAC header from $FLAC_FILE\n";
34
35# for getting track metadata from MusicBrainz
36my $info;
37if ($ALL || $TYPE eq 'mp3') {
38    my $discid = $flac->tags('MBZ_DISCID') or warn "No MBZ_DISCID tag in $FLAC_FILE\n" if $flac;
39    #TODO: calculate TOC and DISCID from cuesheet if there is no MBZ_DISCID tag present
40
41    #TODO: also get the year from MBZ
42    $info = get_musicbrainz_info($discid);
43}
44
45if ($ALL) {
46    die "Use of --all requires a --directory\n" unless $DIRECTORY;
47    die "No track info found on MusicBrainz for $FLAC_FILE\n" unless $info;
48    use YAML;
49    my $cuesheet = $flac->cuesheet;
50    my $count = scalar grep { /TRACK \d\d/ } @{ $flac->cuesheet };
51    print "Found $count tracks\n";
52    #TODO: default to just 01, 02, etc. if there is no $info
53    %TRACKS = map {
54        $_ => catfile($DIRECTORY, sprintf('%02d.%s', $_, to_filename($info->{TRACKS}[$_]{TITLE})))
55    } (1 .. $count);
56    #print Dump(\%TRACKS);
57    for my $tracknum (sort { $a <=> $b } keys %TRACKS) {
58        printf "%2d: %s\n", $tracknum, $TRACKS{$tracknum};
59    }
60    mkpath($DIRECTORY);
61}
62
63#TODO: all the option of sorting by tracknum or not
64#while (my ($tracknum, $title) = each %TRACKS) {
65for my $tracknum (sort { $a <=> $b } keys %TRACKS) {
66    if ($tracknum !~ /^\d+$/) {
67        warn "Don't know what to do with track number '$tracknum'";
68        next;
69    }
70    my $start = $tracknum . '.1';
71    my $end = $tracknum + 1 . '.1';
72    my $cmd = qq{flac -d --cue $start-$end $FLAC_FILE -o - };
73
74    if ($SOX_FILTER) {
75        $cmd .= qq{| sox -t wav - -t wav - $SOX_FILTER };
76    }
77
78    my $title = quotemeta($TRACKS{$tracknum});
79    if ($TYPE eq 'mp3') {
80        # bitrate of 192
81        $cmd .= qq{| lame -b 192};
82        # if there is track info, add it as ID3 tags
83        if ($info) {
84            my $track = $info->{TRACKS}[$tracknum];
85            $cmd .= sprintf q{ --tt %s --ta %s --tl %s --tn %d},
86                quote($track->{TITLE}),
87                quote($track->{ARTIST}),
88                quote($info->{ALBUM}),
89                $tracknum;
90        }
91        $cmd .= qq{ - $title.mp3};
92    } elsif ($TYPE eq 'wav') {
93        $cmd .= qq{> $title.wav};
94    } else {
95        die "Unknown type: $TYPE\n";
96    }
97    #die $cmd;
98    system $cmd;
99    die "\nFLAC decoding canceled\n" if ($? & 127);
100
101    print "\n" if $SOX_FILTER;
102}
103
104sub quote {
105    my ($string) = @_;
106    $string =~ s/"/\\"/g;
107    return qq{"$string"};
108}
109
110sub to_filename {
111    my @strings = @_;
112    #TODO: deal with non-ascii characters (unidecode) e.g. ü --> ue
113    return map {
114        s/[^a-z0-9-_ ]+//gi;
115        s/ +/_/g;
116        lc;
117    } @strings;
118}
Note: See TracBrowser for help on using the repository browser.