https://git.spwbk.site/swatson/yt-track-split/raw/master/yt-track-split
___________________________________
#!/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]);

}