Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

make_m4b

by jfroebe (Parson)
on Mar 05, 2006 at 03:48 UTC ( [id://534556]=sourcecode: print w/replies, xml ) Need Help??
Category: Audio Related Programs
Author/Contact Info jasonATfroebeDOTnet
Description:

This is a work in progress but I've started downloading various podcasts so I can put them on my iPod.  I ran into two problems:

  1. The mp3 files were not bookmarkable, which means that I had to fast forward to where I left off if I wanted to listen to something else for while.  For long podcasts, this can be very annoying!
  2. My iPod can not play RealAudio files.
So I created make_m4b which is able to convert mp3 or realaudio files to a mpeg4 audiobook file.  The iPod is able to play the file and save a bookmark so I can go play it later if I want to without having to fast forward.

The requirements for make_m4b are:

While, this can be used with Windows, I have not tested it. 

This is a variation of Ryan Hayward's code.

Yes, I know system() is bad and I will clean it up later. (I've been sick for a number of days).

#!/usr/bin/perl

use warnings;
use strict;

use MP3::Info;
use Getopt::Long;
use Pod::Usage;

##########
##########
##########
sub convert_mp3 {
        my ($filename, $bitrate, %META_DATA) = @_;

        my $metadata = "";
        my $tmp_meta_ref = get_mp3tag($filename);

        ### override the mp3 tags if desired
        foreach my $key (%META_DATA) {
                next unless ($key && $META_DATA{$key});
                $tmp_meta_ref->{$key} = $META_DATA{$key};
        }

        foreach my $key (%$tmp_meta_ref) {
                next unless ($key && $tmp_meta_ref->{$key});
                next if ( lc($key) eq "tagversion" );

                if (lc($key) eq 'tracknum') {
                        $tmp_meta_ref->{'track'} = $tmp_meta_ref->{$ke
+y};
                        $key = 'track';
                }

                $tmp_meta_ref->{$key} =~ s/\"/\\\"/g; ### Escape out "
+s
                $metadata .= sprintf " --%s \"%s\"", lc($key), $tmp_me
+ta_ref->{$key};
        }

        my $outputfilename = $filename;
        $outputfilename =~ s/\.mp3$/\.m4b/;

        system "mpg123 -w - \"$filename\" | faac -w -b$bitrate $metada
+ta -o \"$outputfilename\" -";
}

##########
##########
##########
sub convert_realaudio {
        my ($filename, $bitrate, %META_DATA) = @_;

        require POSIX;

        my $metadata = "";
        my $outputfilename = $filename;
        my $my_fifo = "/tmp/make_m4b.$$";
        $outputfilename =~ s/\.(?:rm|ram|ra)$/\.m4b/i;

        POSIX::mkfifo($my_fifo, 0666)
                or die "ERROR: can't create named pipe $my_fifo\n";

        foreach my $key (%META_DATA) {
                next unless ($key && $META_DATA{$key});
                $META_DATA{$key} =~ s/\"/\\\"/g; ### Escape out "s
                $metadata .= sprintf " --%s \"%s\"", $key, $META_DATA{
+$key};
        }

        system("faac -w -b$bitrate $metadata -o \"$outputfilename\" $m
+y_fifo &") == 0
                or die "ERROR: unable to start faac: $?\n";
        `mplayer -nortc -vc null -vo null -ao pcm:file=$my_fifo $filen
+ame > /dev/null`;

        unlink $my_fifo;
}


##########
##########
##########
##########
##########
##########
##########

my $man = 0;
my $help = 0;
my ($bitrate, $artist, $title, $album, $genre, $comment, $year, $track
+, $writer, $cover_art);

GetOptions('help|?' => \$help, man => \$man, 'bitrate=s' => \$bitrate,
+ 'artist=s' => \$artist, 'writer=s' => \$writer, 'title=s' => \$title
+, 'album=s' => \$album, 'genre=s' => \$genre, 'comment=s' => \$commen
+t, 'year=s' => \$year, 'track=s' => \$track, 'cover_art=s' => \$cover
+_art)
        or pod2usage(2);

pod2usage(1) if $help;
pod2usage(-exitstatus => 0, -verbose => 2) if $man;

$bitrate = 64 unless $bitrate;

foreach my $filename (@ARGV) {
        $filename =~ m/\.(\w+)$/;
        my $suffix = $1;

        if ($suffix =~ /mp3/i) {
                convert_mp3($filename, $bitrate, ('artist' => $artist,
+ 'writer' => $writer, 'album' => $album, 'title' => $title, 'genre' =
+> $genre, 'comment' => $comment, 'year' => $year, 'track' => $track, 
+'cover-art' => $cover_art) );
        } elsif ($suffix =~ /(?:ra|rm|rv)/i) {
                convert_realaudio ($filename, $bitrate, ('artist' => $
+artist, 'writer' => $writer, 'album' => $album, 'title' => $title, 'g
+enre' => $genre, 'comment' => $comment, 'year' => $year, 'track' => $
+track, 'cover-art' => $cover_art) );
        }
}

__END__

=head1 NAME

 make_m4b - Converts mp3 and realaudio files to bookmarkable mpeg4 fil
+es

=head1 DESCRIPTION

B<make_m4b> will convert mp3 or realaudio files to bookmarkable m4b fi
+les (ipod).  If MP4 info is not supplied, we will attempt to pull the
+ info from the file (mp3 only).

=head1 SYNOPSIS

 make_m4b [options] [file ...]

=head1 OPTIONS

=over 8

=item B<--help>

 Print a brief help message and exits.

=item B<--man>

 Prints the manual page and exits.

=item B<--bitrate>

 Set the bps for the m4b file (default = 64)

=item B<--artist>

 Set artist to X

=item B<--writer>

 Set writer to X

=item B<--title>

 Set title to X

=item B<--album>

 Set album to X

=item B<--genre>

 Set genre to X

=item B<--comment>

 Set comment to X

=item B<--year>

 Set year to X

=item B<--track>

 Set track to X

=item B<--cover-art>

 Read cover art from file X.  Supported image formats are gif, jpg, an
+d png.

=back

=head1 AUTHOR

 Jason L. Froebe (jason<at>froebeD0Tnet)

=cut

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://534556]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (8)
As of 2024-04-23 14:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found