-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathflac2opus.pl
executable file
·105 lines (95 loc) · 3.25 KB
/
flac2opus.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/usr/bin/perl -w
use strict;
use Getopt::Long;
use File::Path qw(make_path);
use File::Basename;
use File::Spec::Functions qw(splitdir);
use File::Copy;
use Cwd;
use v5.10;
use Parallel::ForkManager;
# Process cmdline options
my (@sources, $dest, $help);
my $bitrate = 64;
my $tmpdir = '/tmp';
my $processes = 6;
GetOptions ("s|sources=s{,}" => \@sources,
"d|dest=s" => \$dest,
"b|bitrate=s" => \$bitrate,
"p|processes=s" => \$processes,
"t|tmp=s" => \$tmpdir,
"h|help" => \$help);
if ($help) {
say basename($0) . " -sources <dir where flacs are> -dest <dir where opuses go> [-bitrate <number 6-256>] [-tmp <tmp dir>] [-processes #] [-help]";
exit;
}
# in case users give comma-separated options instead of space separation
@sources = split(/,/,join(',',@sources));
# verify that the directories specified in -sources and -dest are actually directories
map {check_dir(\$_, '-sources')} @sources;
check_dir(\$dest, '-dest');
# Look for flac files
my @src_files = map {find_files ($_)} @sources;
my $pm = new Parallel::ForkManager($processes);
# encode/copy each flac file
for my $src (@src_files) {
$pm->start and next; # do the fork
my @srcdirs = splitdir(dirname($src));
my $opusdir = "$dest/$srcdirs[-2]/$srcdirs[-1]";
make_path ($opusdir) unless (-d $opusdir);
my $basename = basename($src, '.flac');
if ($basename eq 'cover.jpg') {
say "Copying Album Art: $srcdirs[-2] - $srcdirs[-1]";
system "cp \"$src\" \"$opusdir\"";
} else {
my $opusfile = "$basename.opus";
my @meta = `metaflac --show-tag=artist --show-tag=title "$src"`;
chomp @meta;
map {s/\"/\\\"/g} @meta; # escape " in any metadata
map {s/(\w+)=(.*)/\L--$1\E="$2"/} @meta; # \L makes the characters lower case until \E, which ends case conversion
say "Encoding $basename";
my $command = "/usr/bin/flac -scd \"$src\" | /usr/bin/opusenc --quiet --bitrate $bitrate " . join(' ', @meta ) . " - \"$tmpdir/$opusfile\"";
system $command;
move ("$tmpdir/$opusfile", $opusdir);
}
$pm->finish; # do the exit in the child process
}
$pm->wait_all_children;
#subs
sub check_dir {
my ($dir_ref, $option) = @_;
$$dir_ref =~ s{([^/]+)/$}{$1};
if (defined $$dir_ref) {
if (substr($$dir_ref, 0,1) ne '/') {
$$dir_ref = cwd() . "/$$dir_ref";
}
die "$option is not a valid directory" unless (-d $$dir_ref);
} else {
die "Please specify $option";
}
}
sub find_files {
my ($path) = @_;
my (@files, $found_flac, $cover);
opendir (my $path_h, $path);
while (my $file = readdir $path_h){
next if ($file eq '.' or $file eq '..');
my $full_path = "$path/$file";
if ($file eq 'cover.jpg') {
$cover = $full_path;
} elsif (-d $full_path) {
push (@files, find_files($full_path));
} else {
my @fn = split(/\./, basename($file));
if (defined $fn[-1] and $fn[-1] eq 'flac') {
push(@files, $full_path);
$found_flac = 1;
}
}
}
if ($cover and $found_flac) {
push(@files, $cover);
}
closedir $path_h;
return @files;
}