dts2ac3 revisited

Following up from this thread, there’s currently some error passing the output from dcadec to aften via shell pipe.

error allocating read buffer
Invalid count passed to aften_encode_frame
Error encoding frame 0

So been looking at an alternative to that method. And for what it’s worth, ffmpeg can do that too, even in one step.

# ffmpeg -i tmp.dts -acodec ac3 -ac 6 -ab 448k tmp.ac3 

So below is version 0.2 of the script, now depending on ffmpeg instead of dcadec and aften.

#!/usr/bin/perl
# 0.1 - dcadec, aften for dts2ac3
# 0.2 - ffmpeg for dts2ac3
# usage: cd into your working directory, put all sub directories containing mkv's with dts track to encode to ac3 over there and run it
use warnings;
use strict;
use File::Basename;

my $FFMPEG="/usr/bin/ffmpeg";
my $MKVMERGE="/usr/bin/mkvmerge";
my $MKVEXTRACT="/usr/bin/mkvextract";

my $TMP_DTS="tmp.dts";
my $TMP_AC3="tmp.ac3";
my $PATTERN_DTS="A_DTS";
my $PATTERN_AC3="A_AC3";

sub dts2ac3 {
        my ($dts, $ac3) = @_;
        `$FFMPEG -i $dts -acodec ac3 -ac 6 -ab 448k $ac3`;
}
sub info {
        my ($mkv) = @_;
        return `$MKVMERGE -i $mkv`;
}
sub demux {
        my ($mkv, $id) = @_;
        `$MKVEXTRACT tracks $mkv $id:$TMP_DTS`;
}
sub mux {
        my ($mkv, $new, $ac3) = @_;
        #remove all tracks with -A, only add new
        `$MKVMERGE -A -o $new $mkv $ac3`;
}
sub clean {
        # delete 1.dts, 1.ac3, old mkv
        my ($dts, $ac3, $old) = @_;
        system("rm -f $dts");
        system("rm -f $ac3");
        system("rm -f $old");
}
my $pwd=`pwd`;
print "Processing all matches in $pwd...nn";
my @dirs=<*>;
my $dir;
my @files;
my $file;
my @buf;
my $line;
my $id;
my $name;
my $ext=".mkv";;
my $output;

foreach $dir (@dirs) {
        chdir $dir;
        @files=<*>;
        foreach $file (@files) {
                if($file=~m/mkv/i) {
                        $id=-1;
                        # 1. get dts track id from info
                        @buf=info($file);
                        foreach $line (@buf) {
                                if($line=~m/$PATTERN_DTS/i) {
                                        $line=~m/(d+)/;
                                        $id = $1;
                                        # only the first
                                        print "found first match for DTS.n";
                                        last;
                                }
                                if($line=~m/$PATTERN_AC3/i) {
                                        print "AC3 track found.n";
                                }
                        }
                        next if($id<0);
                        # 2. demux dts track
                        print "Demuxing DTS track from $file...n";
                        demux($file,$id);
                        # 3. encode dts to ac3
                        print "Encoding DTS to AC3...n";
                        dts2ac3($TMP_DTS,$TMP_AC3);
                        # 4. parse old name, create new
                        if($file=~m/dts/i){
                                $output=$file;
                                $output=~s/DTS/AC3/g;
                                $output=~s/dts/AC3/g;
                        } else {
                                ($name, undef, $ext) = fileparse($file,qr".mkv");
                                $output="$name.AC3$ext";
                        }
                        # 5. mux
                        print "Creating new output with AC3 in $output...n";
                        mux($file, $output, $TMP_AC3);
                        # 6. clean
                        print "Deleting temp files and old mkv...n";
                        clean($TMP_DTS, $TMP_AC3, $file);
                        # 7. info
                        print info($output);
                }
        }
        chdir "../";
}