1
0
mirror of https://github.com/moex3/flac2mp3.pl synced 2024-11-16 09:30:26 -05:00
This commit is contained in:
moex3 2021-04-14 22:47:44 +02:00
commit dfb21dfc2b
No known key found for this signature in database
GPG Key ID: ABC92E00CF59BB7A
2 changed files with 203 additions and 0 deletions

15
README.md Normal file
View File

@ -0,0 +1,15 @@
# flac2mp3.pl
Perl script to transcode flac into mp3, while keeping the tags. Because hundreds of these scripts aren't enough apparently.
Dependencies: `flac` `metaflac` `lame`
# Usage
```bash
flac2mp3.pl ~/flacs ~/mp3
```
Tags can be overridden with options. Only the genre tag is supported rith now.
```bash
flac2mp3.pl --genre 145 ~/flacs ~/mp3
```
This would add the genre as 'Anime'. Run `lame --genre-list` for the whole list. Can be specified multiple ones, with comma separation (i think).

188
flac2mp3.pl Executable file
View File

@ -0,0 +1,188 @@
#!/usr/bin/env perl
use strict;
use warnings;
use Getopt::Long;
use File::Find;
use Data::Dumper;
use File::Basename;
# this is a godsent page
# https://wiki.hydrogenaud.io/index.php?title=Tag_Mapping
# a lot of this may not work
my %idLookup = (
album => 'TALB',
albumsort => 'TSOA',
discsubtitle => 'TSST',
grouping => 'TIT1',
title => 'TIT2',
titlesort => 'TSOT',
subtitle => 'TIT3',
subtitle => 'TIT3',
albumartist => 'TPE2',
albumartistsort => 'TSO2', # Maybe?
artist => 'TPE1',
artistsort => 'TSOP',
arranger => 'TIPL=arranger',
author => 'TEXT',
composer => 'TCOM',
conductor => 'TPE3',
engineer => 'TIPL=engineer',
djmixer => 'TIPL=DJ-mix',
mixer => 'TIPL=mix',
#performer => 'TMCL', # This produces some really weird tags
producer => 'TIPL=producer',
publisher => 'TPUB',
label => 'TPUB',
remixer => 'TPE4',
discnumber => ['TPOS', sub {
my $t = shift;
return "$t->{discnumber}" if !exists($t->{disctotal});
return "$t->{discnumber}/$t->{disctotal}";
}],
disctotal => undef,
tracknumber => ['TRCK', sub {
my $t = shift;
return "$t->{tracknumber}" if !exists($t->{tracktotal});
return "$t->{tracknumber}/$t->{tracktotal}";
}],
tracktotal => undef,
date => 'TDRC', # This is for id3v2.4
originaldate => 'TDOR', # Also for 2.4 only
isrc => 'TSRC',
barcode => 'TXXX=BARCODE',
catalognumber => 'TXXX=CATALOGNUMBER',
catalog => 'TXXX=CATALOGNUMBER',
catalogid => 'TXXX=CATALOGNUMBER',
'encoded-by' => 'TENC',
encoder => 'TSSE',
encoding => 'TSSE',
'encoder settings' => 'TSSE',
media => 'TMED',
replaygain_album_gain => 'TXXX=REPLAYGAIN_ALBUM_GAIN',
replaygain_album_peak => 'TXXX=REPLAYGAIN_ALBUM_PEAK',
replaygain_track_gain => 'TXXX=REPLAYGAIN_TRACK_GAIN',
replaygain_track_peak => 'TXXX=REPLAYGAIN_TRACK_PEAK',
genre => ['TCON', sub {
return 24;
}],
#mood => ['TMOO', sub {
#}],
bpm => 'TBPM',
comment => 'COMM',
copyright => 'TCOP',
language => 'TLAN',
script => 'TXXX=SCRIPT',
lyrics => 'USLT',
);
my $opt_genre;
my $opt_help;
GetOptions(
"genre=s" => \$opt_genre,
"help" => \$opt_help
) or die("Error in command line option");
if ($opt_help) {
help();
}
if (scalar(@ARGV) != 2) {
print("Bad arguments\n");
usage();
}
my ($IDIR, $ODIR) = @ARGV;
find({ wanted => \&iterFlac, no_chdir => 1 }, $IDIR);
sub iterFlac {
# Return if file is not a file, or if it's not a flac
return if (!-f || !/\.flac$/);
my @required_tags = ("artist", "title", "album", "tracknumber");
my $flac = $_;
my $dest = "$ODIR/" . basename($flac);
$dest =~ s/\.flac$/\.mp3/;
my $tags = getFlacTags($flac);
my $has_req_tags = 1;
foreach (@required_tags) {
if (!exists($tags->{lc($_)})) {
$has_req_tags = 0;
last;
}
}
if (!$has_req_tags) {
print("WARNING: File: '$flac' does not have all the required tags. Skipping\n");
return;
}
argsToTags($tags);
my $tagopts = tagsToOpts($tags);
qx(flac -cd "$flac" | lame -V0 -S --vbr-new --add-id3v2 @$tagopts - "$dest");
}
sub argsToTags {
my $argTags = shift;
if (defined($opt_genre)) {
$argTags->{genre} = $opt_genre;
}
}
sub tagsToOpts {
my $tags = shift;
my @tagopts;
# TODO escape ' and =?
foreach my $currKey (keys (%$tags)) {
if (!exists($idLookup{$currKey})) {
print("Tag: '$currKey' doesn't have a mapping, skipping\n");
next;
}
my $tagName = $idLookup{$currKey};
my $type = ref($tagName);
if ($type eq "" && defined($tagName)) {
push(@tagopts, qq(--tv '$tagName=$tags->{$currKey}'));
} elsif ($type eq "ARRAY") {
my $tagCont = $tagName->[1]->($tags);
push(@tagopts, qq(--tv '$tagName->[0]=$tagCont'));
}
}
#print(Dumper(\@tagopts));
return \@tagopts;
}
sub getFlacTags {
my $flac = shift;
my %tags;
my @tagtxt = qx(metaflac --list --block-type=VORBIS_COMMENT -- "$flac");
foreach my $tagline (@tagtxt) {
if ($tagline =~ /comment\[\d+\]:\s(.*?)=(.*)/) {
$tags{lc($1)} = $2;
}
}
return \%tags;
}
sub usage {
print("Usage: flac2mp3.pl [-h | --help] [-g | --genre NUM] <input_dir> <output_dir>\n");
exit 1;
}
sub help {
my $h = <<EOF;
Usage:
flac2mp3.pl [options] <input_dir> <output_dir>
-h, --help print this help text
-g, --genre NUM force this genre as a tag (lame --genre-list)
EOF
print($h);
exit 0;
}
# vim: ts=4 sw=4 et sta