#!/usr/bin/perl use strict; use warnings; use Time::Piece; if ( ! defined $ARGV[0] || ! defined $ARGV[1] ) { print "Need to pass args\n"; exit 1; } my $ffmpegBin = `which ffmpeg`; chomp $ffmpegBin; if ( ! -e $ffmpegBin ) { print "You need ffmpeg installed to use this\n"; exit 1; } my $track_list_path = shift(@ARGV); my $full_file_path = shift(@ARGV); my $track_list_file = `cat $track_list_path`; chomp $track_list_file; # Key is track name - val is array ref containing start time and end time my %track_times; my %track_names; sub prepend_zeros($) { my $time = shift; if ( $time =~ m/^[0-9]{1,2}\:[0-9]{2}$/ ) { if ( length $time == 4 ) { $time = "00:0" . $time; } elsif ( length $time == 5 ) { $time = "00:" . $time; } elsif ( length $time == 7 ) { $time = "0" . $time; } elsif ( length $time == 8 ) { # Don't need to do anything } else { print "Couldn't prepend zero's for $time\n"; my $len = length $time; print "length of $time is $len\n"; exit 1; } } return $time; } sub remove_spaces($) { my $track_name = shift; if ( $track_name =~ m/\s/ ) { $track_name =~ s/\s/_/g; return $track_name; } return $track_name; } sub get_end_time($$) { my $start_time = shift; my $next_start_time = shift; my $end_time; if ( $next_start_time =~ m/^(.*)\:([0-9]{2})$/ ) { my $end_time_val = $2 - 1; if ( $end_time_val < 0 ) { $end_time_val = 0; } if ( length $end_time_val == 1 ) { $end_time_val = "0" . $end_time_val; } $end_time = $1 . ":" . $end_time_val; $end_time = prepend_zeros($end_time); return $end_time; } else { print "get_end_time couldn't match regex on $next_start_time - exiting\n"; exit 1; } } sub get_track_length() { my $ffmpegCmd = "$ffmpegBin -i '$full_file_path' 2>&1"; my $ffmpegOutput = `$ffmpegCmd`; chomp $ffmpegOutput; if ( ! defined $ffmpegOutput || $ffmpegOutput eq "" ) { print "Something went wrong with calling $ffmpegCmd\n"; exit 1; } my $duration; foreach my $line ( split("\n", $ffmpegOutput) ) { if ( $line =~ m/Duration:\ (.*)\.[0-9]{2},/ ) { $duration = $1; return $duration; } } print "Couldnt get duration of $full_file_path from $ffmpegCmd\n"; exit 1; } sub convert_to_mp3() { my $filename; if ( $full_file_path =~ m/^.*\/(.*)\.(mp4)$/ ) { $filename = $1 . ".mp3"; } else { print "Couldn't parse relative filename out of $full_file_path\n"; exit 1; } #my $ffmpegCmd = "ffmpeg -i '$full_file_path' -vn acodec libmp3lame -ac 2 -ab 160k -ar 48000 '$filename'"; my $ffmpegCmd = "ffmpeg -i '$full_file_path' -vn -acodec libmp3lame -ac 2 -qscale:a 4 -ar 48000 '$filename' > /dev/null 2>&1"; print "Converting $full_file_path to mp3...\n"; system("$ffmpegCmd") == 0 or die "Failed to convert $full_file_path to an mp3 with $ffmpegCmd\n"; return $filename; } sub run_split($$$$$) { # ffmpeg -i Ryo\ Fukui\ -\ Scenery\ 1976\ \(FULL\ ALBUM\)-Hrr3dp7zRQY.mp4 -acodec copy -ss 00:00:00 -to 00:04:15 shibz.mp4 my $mp3_file = shift; my $track_number = shift; my $track_name = shift; my $start_time = shift; my $end_time = shift; # Optionally covert to different codec? my $filename = "$track_number" . "-" . "$track_name" . ".mp3"; my $ffmpegCmd = "$ffmpegBin -i '$mp3_file' -acodec copy -ss $start_time -to $end_time '$filename' > /dev/null 2>&1"; system("$ffmpegCmd") == 0 or die "Failed to run $ffmpegCmd\n"; } foreach my $line ( split("\n",$track_list_file) ) { #if ( $line =~ m/^([0-9]{1,2})\.\ (.*)\ ([0-9]{1,2}:[0-9]{2})$/ ) { if ( $line =~ m/^([0-9]{1,2})\.\ (.*)\ (.*)$/ ) { my @times; # Start time my $start_time = prepend_zeros($3); push(@times, $start_time); $track_times{$1} = \@times; my $track_name = remove_spaces($2); $track_names{$1} = $track_name; } else { print "$line doesn't match regex, exiting\n"; exit 1; } } foreach my $track_number ( sort keys %track_times ) { my $next_track_val = $track_number + 1; my $next_start_time; my $end_time; if ( defined $track_times{$next_track_val} ) { $next_start_time = $track_times{$next_track_val}[0]; $end_time = get_end_time($track_times{$track_number}[0],$next_start_time); } else { $end_time = get_track_length; } push(@{$track_times{$track_number}}, $end_time); } my $mp3_file = convert_to_mp3(); foreach my $track_number ( sort keys %track_times ) { print "Splitting $track_number - $track_names{$track_number} - $track_times{$track_number}[0] - $track_times{$track_number}[1]\n"; run_split($mp3_file,$track_number,$track_names{$track_number},$track_times{$track_number}[0],$track_times{$track_number}[1]); }