Skip to content

Instantly share code, notes, and snippets.

@fuba
Created December 24, 2011 20:37
Show Gist options
  • Save fuba/1518292 to your computer and use it in GitHub Desktop.
Save fuba/1518292 to your computer and use it in GitHub Desktop.
#!/usr/bin/perl
# libx264-hq-ts.preset -> http://d.hatena.ne.jp/munepi/20091227/1261941397
use strict;
use warnings;
use File::Basename;
use YAML::Syck;
use constant {
FFMPEG_DIR => '/home/ec/src/ffmpeg_x264/ffmpeg', # 自分でコンパイルした ffmpeg のあるディレクトリ, ffmpeg は FFMPEG_DIR/ffmpeg にあることになる
FFMPEG_DATADIR => '', # FFMPEG_DATADIR をここで指定, なければ FFMPEG_DIR/ffpresets
AUDIO_OPTIONS => '-acodec aac -ac 2 -ar 48000 -ab 128k',
};
$ENV{'FFMPEG_DATADIR'} = FFMPEG_DATADIR || FFMPEG_DIR.'/ffpresets';
my $ffmpeg = FFMPEG_DIR.'/ffmpeg';
my $preset = 'hq-ts';
my $ts = shift;
my $out = shift || $ts.'.mp4';
my $base = basename($ts);
# つぎは dd で TS の開始位置をちょっとずつずらしてまともに音声とれそうなところを探すのをやります
# dd if=/video/video/[二]BS世界のドキュメンタリー「ガスランド〜アメリカ 水汚染の実態〜」(前編)\ .ts skip=50000 | /home/ec/src/ffmpeg_x264/ffmpeg/ffmpeg -i -
my $cores = `/usr/bin/getconf _NPROCESSORS_ONLN`;
chomp $cores;
$cores--;
my ($program_id, $video_map, @audio_maps) = get_stream_id($ts, $ffmpeg);
my @maps = ($video_map, @audio_maps);
my $stream_ids = join " ", map {"-map ".$maps[$_].":0.$_"} (0..$#maps);
$stream_ids .= ' -programid '.$program_id;
my $audio_additional_options = '';
if (@audio_maps >= 2) {
$audio_additional_options .= join " ", map {'-newaudio '.AUDIO_OPTIONS} (0..@audio_maps - 2);
}
my $X264_HIGH_HDTV = " -f mp4 -vcodec libx264 -vpre \"${preset}\" -r 30000/1001 -aspect 16:9 -s 1280x720 -bufsize 500000k -maxrate 25000k -vsync 1 -async 100 -copyts -strict experimental -acodec aac -ac 2 -ar 48000 -ab 128k $stream_ids -threads ${cores}";
my $command = "$ffmpeg -y -i \"$ts\" ${X264_HIGH_HDTV} \"${out}\" $audio_additional_options";
warn $command;
`$command`;
exit;
sub get_stream_id {
my ($file, $ffmpeg) = @_;
my ($vstr, $program);#save StreamID
my ($vstr_line, $program_line);#save StreamID
my $astrs = [];
my $astr_lines = [];
my $brs = [];
my $ffmpeg_info = "$ffmpeg -i \"$file\" 2>&1";
warn $ffmpeg_info;
my $str = `$ffmpeg_info`;
warn $str;
my @lines = split(/\n/,$str);
my @programs;
for my $line (@lines){
if ($line =~ /Program\s+(\d+)(?:\s+\S+)?/) {
if (defined $program) {
push @programs, {
audio_bitrates => $brs,
video => $vstr,
audios => $astrs,
program => $program,
video_line => $vstr_line,
audio_lines => $astr_lines,
program_line => $program_line,
};
($vstr, $astrs, $program, $vstr_line, $astr_lines, $program_line, $brs) = (undef, [], undef, undef, [], undef, []);
}
$program = $1;
$program_line = $line;
}
#Get Video StreamID
if($line =~ /\#([0-9\.]+)\[.+mpeg2video/ && !$vstr){
$vstr = $1;
$vstr_line = $line;
}
#Get Audio StreamID
elsif($line =~ /\#([0-9\.]+)\[.+Audio.+, ([0-9]+) kb\/s/){
my $astr_cand = $1;
my $br_cand = $2;
if (defined $vstr) {
push @{$astrs}, $astr_cand;
push @{$astr_lines}, $line;
push @{$brs}, $br_cand;
}
}
}
push @programs, {
audio_bitrates => $brs,
video => $vstr,
audios => $astrs,
program => $program,
video_line => $vstr_line,
audio_lines => $astr_lines,
program_line => $program_line,
};
my @programs_sorted = sort {
$b->{audio_bitrates}->[0] <=> $a->{audio_bitrates}->[0]
|| (($a->{program} || 0) <=> ($b->{program} || 0))
} grep {defined $_->{video}} @programs;
warn Dump \@programs_sorted;
my $target_program = $programs_sorted[0];
return (
$target_program->{program},
$target_program->{video},
@{$target_program->{audios}},
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment