Category: Audio Related Scripts
Author/Contact Info William Meyer
smgfc@mindspring.com
Description: A very simple program to catalog mp3s into a one table MySQL database. This is a port of a earlier program of mine which would do essentially the same thing, but would save the results to a text file instead of a database. The rest of the features in that program might be ported later (duplicate deletion, better method for choosing which mp3 to chose if id3 ==, renaming, etc.) and that new version will probably have a different table scheme.

The alias switch (a), changes the path to include on the root of the mp3 folder down. i.e. Path = /Volumes/Storage/MP3s/Cam'ron/Hey Ma.mp3 will become /MP3s/Cam'ron/Hey Ma.mp3. This way if you want to serve these mp3s from apache you can make an alias MP3s which points to /Volumes/Storage/MP3s/, and users will be able to get to the files even if they are outside you document root. Not very interesting but...

Any and all suggestions are welcome.

Will
#!/usr/bin/perl -w

use strict;

use DBI;
use File::Find;
use MP3::Info;
use Getopt::Std;

my (%options, $DBH, $STH, $tmp, %mp3s, $artist, $album, $title);

getopts("d:au:p:h", \%options);

if ($options{h}) {
    print <<'eof';
    -d dir:      Root MP3 directory
    -u username: Username for mysql
    -p password: Password for mysql
    -a:          Turn aliasing on
    -h:          This help file
eof
exit;
}

my (@dirs) =      $options{m} || ("Your mp3 dir");
my ($orig_path) = $dirs[0];

$orig_path =~ /(.+?)(\/(.+?)\/)/;
my ($alias) = $2;

my ($user_name) = $options{u} || 'user';
my ($password) =  $options{p} || 'password';
my ($database) =  'DBI:mysql:mp3';

find(\&id3info, @dirs);

sub id3info {
    return unless $File::Find::name =~ /^.+?\.[Mm][Pp]3$/;
    $tmp = get_mp3tag($File::Find::name);
    return unless defined $$tmp{'ARTIST'} && defined $$tmp{'TITLE'};

    $$tmp{'ALBUM'} = "Other" unless defined $$tmp{'ALBUM'};
    $$tmp{'TRACKNUM'} = 0 unless defined $$tmp{'TRACKNUM'};

    unless (exists $mp3s{$$tmp{'ARTIST'}}{$$tmp{'ALBUM'}}{$$tmp{'TITLE
+'}}) {
        %{$mp3s{$$tmp{'ARTIST'}}{$$tmp{'ALBUM'}}{$$tmp{'TITLE'}}} = (
            'PATH' => $File::Find::name,
            'TRACK' => $$tmp{'TRACKNUM'},
            'TIME' => $$tmp{'TIME'}
        );
    } else {
        if ($mp3s{$$tmp{'ARTIST'}}{$$tmp{'ALBUM'}}{$$tmp{'TITLE'}}{'TI
+ME'} < $$tmp{'TIME'}) {
            %{$mp3s{$$tmp{'ARTIST'}}{$$tmp{'ALBUM'}}{$$tmp{'TITLE'}}} 
+= (
                'PATH' => $File::Find::name,
                'TRACK' => $$tmp{'TRACK'},
                'TIME' => $$tmp{'TIME'}
            );
         }
    }

    if ($options{a}) {
        $mp3s{$$tmp{'ARTIST'}}{$$tmp{'ALBUM'}}{$$tmp{'TITLE'}}{'PATH'}
+ =~ s/^$orig_path(.+)$/$alias$1/;
    }

}

$DBH = DBI->connect ($database, $user_name, $password, { RaiseError =>
+ 1 });

$STH = $DBH->prepare (qq{ INSERT mp3s (artist,album,title,track,path) 
+VALUES(?,?,?,?,?)});

foreach $artist (keys %mp3s) {
    foreach $album (keys %{ $mp3s{$artist} }) {
        foreach $title (keys %{ $mp3s{$artist}{$album} }) {

             $STH->execute ($artist, $album, $title, $mp3s{$artist}{$a
+lbum}{$title}{'TRACK'}, $mp3s{$artist}{$album}{$title}{'PATH'});

        }
    }
}

$STH->finish();

$DBH->disconnect ();
Replies are listed 'Best First'.
Re: MP3/MySQL Cataloger
by Anonymous Monk on Dec 07, 2005 at 03:43 UTC
    Hello guru, Does this applicable for other language? Any way we can do this in perl to take care of filenames with other language? (not in letters) Seems usually if I have mp3 with chinese (let's say) file name.mp3, the output text will always appear to be ????.mp3 :-( Thanks, Melvin