Updated for Ubuntu 22.04. Also fixed merge videos cmin check
[videoscripts/.git] / mkv_extract_chapter
index 142b8ecb496722677a64d561bed10dfe07827938..273484b82c7ed0cb299e39d8f3ff5303e5fe36bd 100755 (executable)
@@ -3,6 +3,13 @@
 # Description: Extract the given chapter(s) from an mkv file into separate video files
 # Requires: Newer version of ffmpeg to be installed that supports MKV chapters
 
+# Howto compile the latest FFMPEG from src under Linux
+# FFMPEG - http://ubuntuforums.org/showthread.php?t=786095
+
+# Howto eliminate the non-monotonically increasing dts to muxer error
+# Comment out the error message in ffmpeg src tree in libavformat/utils.c
+# http://ffmpeg.zeranoe.com/forum/viewtopic.php?f=7&t=49
+
 # MOV:
 # major_brand : qt
 # Video: h264 (avc1 / 0x31637661) 
@@ -32,12 +39,12 @@ use Getopt::Std;
 ####################################################################################################
 # Configuration parameters - CHANGE THESE TO SUITE YOUR NEEDS
 my $ffmpeg=`which ffmpeg`; chomp($ffmpeg);
-my $tmpfile = `tempfile`; chomp($tmpfile);
+my $tmpfile = `mktemp`; chomp($tmpfile);
 ####################################################################################################
 
 ####################################################################################################
 # Command Line Options
-getopts("c:i:o:se:");
+getopts("c:i:o:kse:");
 
 if(! -x $ffmpeg) { die "-E- Unable to find required program: ffmpeg\n"; }
 if(! defined $opt_i) { &usage(); die "-E- Missing required argument input video name: -i <input.mkv>\n"; }
@@ -57,6 +64,7 @@ sub usage {
     print "  -e <ext>                  Specify the extension that should be used on the output files.\n";
     print "                            This is automatically determined. You only need to specify it if autodetection fails.\n";
     print "  -s                        Simulate mode. Don't actually make the video, but tell us what you will do\n";
+    print "  -k                        Keep intermediate mkv file created during the extraction/conversion of mp4 clips\n";
     print "\n";
     return 1;
 }
@@ -65,7 +73,7 @@ sub usage {
 # SUBROUTINES
 
 sub detect_ext {
-    my ($ffmpeg_info) = @_;
+    my ($ffmpeg_info, $progressive) = @_;
 
     my $h264 = 0;
     my $h264_high = 0;
@@ -86,9 +94,9 @@ sub detect_ext {
     # Quicktime/MOV
     if($h264 && $pcm_s16le) { return "mov"; }
     # MTS
-    if($h264_high && $ac3) { return "mp4"; }
+    if($h264_high && $ac3) { if(!$progressive) { return "mkv"; } else { return "mp4"; } }
     # 3GP/MP4
-    if($h264 && $aac) { return "mp4"; }
+    if($h264 && $aac) { if(!$progressive) { return "mkv"; } else { return "mp4"; } }
 
     return "UNKNOWN";
 }
@@ -110,11 +118,18 @@ my $all_chapters = 0;
 if($opt_c =~ /all/) { $all_chapters = 1; }
 print "-> Extracting the following chapters from $opt_i: @chapters\n";
 
+my $progressive = system('ffmpeg -i "$opt_i" 2>&1 | grep -q "frame rate differs"');
+if(!$progressive) {
+    print "   Detected interlaced video content\n";
+} else {
+    print "   Detected progressive video content\n";
+}
+
 # Use ffmpeg to extract the list of chapters available to rip
 # For each chapter specified on the command line, use ffmpeg to extract a video clip from that chapter
 my @ffmpeg_info = `$ffmpeg -i $opt_i 2>&1`;
 foreach $line (@ffmpeg_info) {
-    if($line =~ /Chapter #\d+\.(\d+): start (\S+), end (\S+)/) {
+    if($line =~ /Chapter #\d+\:(\d+): start (\S+), end (\S+)/) {
        $chapter = $1;
        $start = $2;
         if($start > 0) { $start += 1; } # Add some margin to prevent taking a piece of the previous clip
@@ -124,10 +139,10 @@ foreach $line (@ffmpeg_info) {
        if($all_chapters || &export_chapter(\@chapters,$chapter)) {
            $ext = "UNKNOWN"; 
            if(defined $opt_e) { $ext = $opt_e; }
-           else { $ext = &detect_ext(\@ffmpeg_info); } 
+           else { $ext = &detect_ext(\@ffmpeg_info, $progressive); } 
            if($ext =~ /UNKNOWN/) { die "-E- Unable to determine the file type/extension to use for the output videos. Specify it with the -e <ext> option.\n"; }
            $dstfile = $opt_o . ".c" . sprintf("%03d",$chapter) . "." . $ext;
-           print "-> Exporting $chapter to $dstfile: ";
+           print "-> Exporting $chapter to $dstfile:\n";
            $cmd = "ffmpeg -ss $start -t $duration -i $opt_i -map 0 -vcodec copy -acodec copy $dstfile 2>&1";
            if(defined $opt_s) {
                print "$cmd\n";
@@ -138,6 +153,22 @@ foreach $line (@ffmpeg_info) {
                $errno = $errno >> 8;
                if($errno > 0) { die "-E- ffmpeg encountered some errors with exit code $errno\n"; }
            }
+           if(!$progressive && $ext =~ /mkv/i) {
+               $ext = "mp4";
+               $srcfile = $dstfile;
+               $dstfile = $dstfile = $opt_o . ".c" . sprintf("%03d",$chapter) . "." . $ext;
+               $cmd = "mencoder -oac copy -ovc copy -of lavf -lavfopts format=mp4 -o $dstfile $srcfile";
+               if(defined $opt_s) {
+                   print "$cmd\n";
+               } else {
+                   print "\n";
+                   print "$cmd\n";
+                   $errno = system("$cmd");
+                   $errno = $errno >> 8;
+                   if(! defined $opt_k) { unlink "$srcfile"; }
+                   if($errno > 0) { die "-E- mencoder encountered some errors with exit code $errno\n"; }
+               }
+           }
        }
     }
 }