Skip to content

Instantly share code, notes, and snippets.

@archydragon
Created December 30, 2012 22:28
Show Gist options
  • Save archydragon/4415682 to your computer and use it in GitHub Desktop.
Save archydragon/4415682 to your computer and use it in GitHub Desktop.
#!/usr/bin/env perl
# dedicated to hatred of High 10 H.264 profile
# finds all MKV files in current directory and re-encodes them to kawaii High@*
# WARNING: make sure that your x264 is built with ffmpeg support
use strict;
use warnings;
use 5.010;
use Math::Round; # must be installed from CPAN
use XML::XPath; # must be installed from CPAN
# files and directories
my $dirTmp = "v4tmp"; # directory for temporary files
my $dirOut = "tabletized"; # destination directory for encoded video
my $tmpEnc = "$dirTmp/encoded.x264"; # filename for encoded video stream
my $tmpAudio = "$dirTmp/audio.raw"; # filename for audio stream
my $tmpSubs = "$dirTmp/subs.raw"; # filename for subtitles stream
my $tmpTC = "$dirTmp/timecodes.txt"; # filename for timecodes data
# some encoding options
my $height = 480; # \
my $width = 800; # - default video encodig parameters; for my ONDA Vi10 Fashion with love
my $vbitrate = 1100; # /
##################################################
# find all MKV files in current directory
my @mkvFiles = <*.mkv>;
my $mkvFilesCount = @mkvFiles;
# if there are no suitable files, panic and exit
if ($mkvFilesCount == 0) {
say "No any MKV files found. Nothing to do here.";
exit 0;
}
# create temporary directory
`mkdir -p $dirTmp`;
# create output directory
`mkdir -p $dirOut`;
# process all the MKVs!
for my $mkv (@mkvFiles) {
process(quotemeta($mkv));
}
# remove all temporary data
`rm -rf $dirTmp`;
##################################################
## Main file processing subroutine
sub process {
my $file = $_[0];
my $xml = `mediainfo --Output=XML $file`;
my $parser = XML::XPath->new(xml=>$xml);
# getting video information
my %trackVideo;
for my $key ('ID', 'Width', 'Height') {
my $nodeValue = $parser->findvalue('//track[@type="Video"]/' . $key);
$nodeValue =~ s/[^0-9]//g;
$trackVideo{$key} = $nodeValue;
}
# getting audio information
my %trackAudio;
for my $key ('ID', 'Format') {
my $nodeValue = $parser->findvalue('//track[@type="Audio"]/' . $key);
$trackAudio{$key} = $nodeValue;
}
# getting subtitles ID
my $trackSubsId = $parser->findvalue('//track[@type="Text"]/ID');
destroyMkv($file, $trackVideo{ID}, $trackAudio{ID}, $trackSubsId);
x264("$file", "$tmpEnc", $trackVideo{Width}, $trackVideo{Height});
# lossless audio must be killed with fire^W^W^Wencoded to AAC
if ($trackAudio{Format} eq 'FLAC') {
flac2aac();
}
mergeMkv("$file");
}
## Extract audio, subtitles and timecode data from original MKV
sub destroyMkv {
my ($fileName, $videoId, $audioId, $subsId) = @_;
`mkvextract tracks $fileName $audioId:$tmpAudio $subsId:$tmpSubs`;
`mkvextract timecodes_v2 $fileName $videoId:$tmpTC`;
}
## Encode original video to downscaled (or upscaled if you have FullHD tablet) one
sub x264 {
my ($fileInput, $fileOutput, $srcWidth, $srcHeight) = @_;
my ($encWidth, $encHeight) = (0, 0);
# check do we need scale on long or short screen dimension
my $tabletRatio = $width/$height;
my $videoRatio = $srcWidth/$srcHeight;
if ($videoRatio > $tabletRatio) {
# scale on width
$encWidth = $width;
$encHeight = round($height/($videoRatio/$tabletRatio));
}
else {
# scale on height
$encHeight = $height;
$encWidth = round($width/($tabletRatio/$videoRatio));
}
# BE AWARE BEFORE EDITING VIDEO ENCODING PAREMETERS!
my $command = "x264 --output $fileOutput --input-res ${srcWidth}x${srcHeight} --profile high " .
"--preset medium --bitrate $vbitrate --crf 18 --video-filter " .
"resize:width=$encWidth,height=$encHeight,method=lanczos $fileInput";
`$command`;
}
## Convert FLAC to AAC
sub flac2aac {
my $tmpAac = "$dirTmp/audio.aac"; # filename for temporary encoded AAC stream
`ffmpeg -y -acodec flac -i $tmpAudio $tmpAac`;
`rm $tmpAudio`;
`mv $tmpAac $tmpAudio`;
}
## Merge destination MKV
sub mergeMkv {
my $file = $_[0];
`mkvmerge --timecodes 0:$tmpTC -o $dirOut/$file $tmpEnc $tmpAudio $tmpSubs`;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment