summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xtools/gen_frikanalen_video.pl190
1 files changed, 100 insertions, 90 deletions
diff --git a/tools/gen_frikanalen_video.pl b/tools/gen_frikanalen_video.pl
index d01bd15..26ca45c 100755
--- a/tools/gen_frikanalen_video.pl
+++ b/tools/gen_frikanalen_video.pl
@@ -1,8 +1,24 @@
#!/usr/bin/perl
+#
+# Script for adding start/end poster and convert to frikanalen
+# acceptable avi format anamporphic PAL with pillarboxing
+#
+# DV PAL Anamophic i en AVI-fil eller på en DV/DVCam-tape (25 Mbit DV,
+# 25 fps, interlaced, lower field first, 720x576
+#
+# See also
+# http://www.frikanalen.tv/lage-tv/mange-spør-om-formater-og-logistikk
+# http://kevinlocke.name/bits/2012/08/25/letterboxing-with-ffmpeg-avconv-for-mobile/
+# (export INPUT_FILE=Nina_Paley_tribute-to-EFF.m4v OUTPUT_FILE=Nina_Paley_tribute-to-EFF.avi MAX_WIDTH=720 MAX_HEIGHT=576; avconv -i "$INPUT_FILE" -map 0 -vf "scale=iw*sar*min($MAX_WIDTH/(iw*sar)\,$MAX_HEIGHT/ih):ih*min($MAX_WIDTH/(iw*sar)\,$MAX_HEIGHT/ih),pad=$MAX_WIDTH:$MAX_HEIGHT:(ow-iw)/2:(oh-ih)/2" -c:v libx264 -vprofile baseline -level 30 -c:a libvo_aacenc "$OUTPUT_FILE")
-# Script for adding start/end poster and convert to frikanalen acceptable avi format anamporphic PAL with pillarboxing
# Script is work in progress 2010-09-04 /JB
-# standard backggrund for NUUG is in ./lib/graphic/tv-bg.png (relative to script location in svn-tree)
+# standard backggrund for NUUG is in ./lib/graphic/tv-bg.png (relative
+# to script location in svn-tree)
+#
+# ffmpeg tip for videos with wrong field order
+# http://ffmpeg.org/ffmpeg-all.html#yadif-1
+# -vf yadif=parity=tff or bff (top field first or bottom field first)
+#
# metafile format is like this:
#
#title=Radioamatørenes sporingssystem
@@ -19,15 +35,20 @@
#videomixer=Ole Kristian Lien
#sound=?
#spokenlanguage=no
+#clipin=1:20
+#clipout=1:20:20
#
-# PS: IF this script is used on an sshfs mounted filesystem, the option sshfs -o workaround=rename must be used .
-# If not, normalize-audio will just silently fail and no audio normalization will take place.
+# PS: If this script is used on an sshfs mounted filesystem, the
+# option sshfs -o workaround=rename must be used . If not,
+# normalize-audio will just silently fail and no audio normalization
+# will take place.
use strict;
use warnings;
use Data::Dumper;
use Getopt::Std;
+use File::Spec;
my %opts;
my $intro_length = 10;
@@ -36,12 +57,11 @@ my $pid = $$;
getopts('di:m:o:b:s:S:', \%opts);
my $debug = $opts{d} || 0;
my $workdir = "./fk-temp-$pid";
-#my $startposter = "$workdir/startposter.png";
my $startposter = "$workdir/startposter.jpg";
-#my $endposter = "$workdir/endposter.png";
my $endposter = "$workdir/endposter.jpg";
my $startposter_dv = "$workdir/startposter.dv";
my $endposter_dv = "$workdir/endposter.dv";
+my $outxml = "$workdir/playout.xml";
my $metafile;
my $srcfile;
my $srtfile;
@@ -51,6 +71,9 @@ my $normalize_cmd = "/usr/bin/normalize-audio";
# http://normalize.nongnu.org/
my $soundlevel_dbfs = '-18dBFS';
+my $MAX_WIDTH = 720;
+my $MAX_HEIGHT = 576;
+
#foreach (keys %opts ) { print "$_\n"; };
if ( $opts{'m'} ) {
$metafile = $opts{'m'} ;
@@ -69,8 +92,6 @@ if ( $opts{'b'} ) {
}
-`mkdir -p $workdir`;
-
if ( $ARGV[0] && $ARGV[0] eq 'front' ) {
create_startposter_png($startposter,$bgfile);
print "Frontpage in $startposter\n";
@@ -86,7 +107,9 @@ if ( $opts{'o'} ) {
}
if ( $opts{'i'} ) {
- $srcfile = $opts{'i'} ;
+ # Convert to absolute path to make sure file names with colon in them are
+ # not interpreted as URLs.
+ $srcfile = File::Spec->rel2abs($opts{'i'});
} else {
usage();
exit 1;
@@ -95,31 +118,86 @@ my $subdelay = "";
if ( $opts{'s'} ) {
$srtfile = getsrtfile();
- if ( ! -f $srtfile ) {
+ if ( ! -f $srtfile ) {
print "$srtfile does not exist\n";
exit 1 ;
}
if ( $opts{'S'} ) {
$subdelay = "-subdelay $opts{'S'}";
- }
+ }
}
+`mkdir -p $workdir`;
create_startposter_png($startposter,$bgfile);
create_endposter_png($endposter,$bgfile);
-gen_dv_from_png($startposter,$intro_length,$startposter_dv);
-gen_dv_from_png($endposter,$intro_length,$endposter_dv);
-my $normalized_video_body = gen_video_body($srcfile);
-glue_dv($opts{'o'},$startposter_dv,$normalized_video_body,$endposter_dv);
+my $outfile = File::Spec->rel2abs($opts{'o'});
+
+my $framerate = 25; # frames per second
+my $durationframes = $intro_length * $framerate;
+my @cmd = ("melt");
+
+# Define output profile
+push(@cmd, "-profile", "dv_pal_wide");
+
+# Do audio normalization (also require xml consumer and second run)
+push(@cmd, "-filter", "sox:analysis");
+
+# Add intro page for a few seconds.
+push(@cmd, $startposter, "out=$durationframes");
+
+# Then the video itself
+push(@cmd, "$srcfile");
+
+push(@cmd, "in=" . duration2sec($meta->{'clipin'}) * $framerate)
+ if (exists $meta->{'clipin'});
+push(@cmd, "out=" . duration2sec($meta->{'clipout'}) * $framerate)
+ if (exists $meta->{'clipout'});
+
+# Next, the out image
+push(@cmd, $endposter, "out=$durationframes");
+
+# Finally the XML consumer to handle the audio normalization
+push(@cmd, "-consumer", "xml:$outxml", "video_off=1", "all=1");
+
+# FIXME missing subtitle handling
+runcmd(@cmd);
+
+# The outfile must be a .dv file for melt to pick good defaults. If
+# it is .avi, the video quality is very bad.
+runcmd("melt", $outxml,
+ "-consumer", "avformat:$outfile",
+ # http://www.mltframework.org/bin/view/MLT/ConsumerAvformat#field_order
+ # http://www.frikanalen.tv/lage-tv/mange-spør-om-formater-og-logistikk
+ # lower field first
+# "field_order=tb",
+ );
+
+if ( -d $workdir ) {
+ `rm -rf $workdir`;
+}
#### Functions #########
sub usage {
- print"Usage: $0 -i inputfile.dv -m metafile -o outputfile.avi -b backgroundfile.png [-s /dir/where/srtfiles/are ] \n\n";
- print "If -s is given the script expects a file named <basename_of_raw_file>.srt \n";
- print "located in the path given as arg to -s option\n\n";
+ print <<EOF;
+Usage: $0 -i inputfile.dv -m metafile -o outputfile.avi -b backgroundfile.png [-s /dir/where/srtfiles/are ]
+
+If -s is given the script expects a file named <basename_of_raw_file>.srt
+located in the path given as arg to -s option
+EOF
+}
+
+sub duration2sec {
+ my $str = shift;
+ my $duration = 0.0;
+ for my $part (split(/:/, $str)) {
+ $duration *= 60.0;
+ $duration += $part;
+ }
+ return $duration;
}
sub read_meta {
@@ -128,7 +206,7 @@ sub read_meta {
# Set some default values
$ret->{'url'} = 'http://www.nuug.no/';
$ret->{'email'} = 'sekretariat@nuug.no';
- $ret->{'editor'} = 'Jarle Bjørgeengen';
+# $ret->{'editor'} = 'Petter Reinholdtsen';
open M, "$metafile" or die "Cannot open $metafile for read :$!";
while (<M>) {
@@ -152,7 +230,7 @@ sub count_words_n_space {
sub break_title {
my $title = shift;
- print $title;
+# print $title;
my $cols = 30;
my $count = 0 ;
my $ln = 0;
@@ -163,7 +241,7 @@ sub break_title {
if ($count < $cols ) {
$lines[$ln] .= "$word ";
} else {
- print "$lines[$ln]\n";
+# print "$lines[$ln]\n";
$count = 0;
$ln++;
$count += count_words_n_space($word);
@@ -201,7 +279,7 @@ sub create_endposter_png {
# $cmd_body .= " -draw "text $left_margin,$pos \'$n: $meta->{$n}\'"
my %keyword_map = (
"introduction" => "Introdusert av",
- "editor" => "Redaktør",
+# "editor" => "Redaktør",
"venue" => "Lokaler",
"organizer" => "Organisert av",
"camera" => "Kamera",
@@ -244,74 +322,6 @@ sub create_endposter_png {
if ( !runcmd(@cmd) ) { die "Failed to execute system command in" . (caller(0))[3] ."\n"; }
}
-sub gen_dv_from_png {
-
- my $png_file = shift;
- my $length = shift;
- my $outputvid = shift;
- my $f = "ffmpeg -loop_input -t $length -i $png_file -f image2 -f s16le -i /dev/zero -target pal-dv -padleft 150 -padright 150 -s 420x576 -y $outputvid";
- if ( !runcmd($f) ) { die "Failed to execute system command in" . (caller(0))[3] ."\n"; }
-}
-
-sub gen_video_body {
- my $source = shift;
- my $mod_dv;
- if ( $meta->{'aspect'} eq "4:3" || $opts{'s'} ) {
- my $cmd ;
- $mod_dv = "$workdir/mod.dv";
- $cmd = "mencoder -oac pcm -of lavf -ovc lavc -lavcopts vcodec=dvvideo:vhq:vqmin=2:vqmax=2:vme=1:keyint=25:vbitrate=2140 ";
- if ( $meta->{'aspect'} eq "4:3" ) {
- $cmd .= "-vf-add expand=1000::::: -vf-add scale=720:576 ";
- }
- if ( $srtfile ) {
- $cmd .= " -sub $srtfile -utf8 $subdelay -sub-bg-alpha 80 -sub-bg-color 50 -subfont-text-scale 3 -subpos 90 -subwidth 90 ";
- }
- $cmd .= "-o $mod_dv $source ";
- if ( !runcmd($cmd) ) { die "Failed to execute system command in" . (caller(0))[3] ."\n"; }
- $source = $mod_dv;
- }
- my $dest = normalize_sound($source);
- return $dest;
-}
-
-sub normalize_sound {
- my $dvfile = shift;
- my $new_dvfile = "$workdir/normalized-body.dv";
- my $f = "ffmpeg -i $dvfile -ac 2 -vn -f wav -y $workdir/sound.wav";
- if ( !runcmd($f) ) { die "Failed to execute system command in" . (caller(0))[3] ."\n"; }
- $f = "$normalize_cmd -a $soundlevel_dbfs $workdir/sound.wav";
- if ( !runcmd($f) ) { die "Failed to execute system command in" . (caller(0))[3] ."\n"; }
- $f = "ffmpeg -i $workdir/sound.wav -ac 2 -acodec copy -i $dvfile -vcodec copy -map 1:0 -map 0.0 -f dv -y $new_dvfile";
- if ( !runcmd($f) ) { die "Failed to execute system command in" . (caller(0))[3] ."\n"; }
- return $new_dvfile;
-}
-
-
-sub glue_dv {
- my $outfile = shift;
- my @infiles = @_;
- my $cat = 'cat '.join(' ',@infiles)." > $workdir/complete.dv ";
- if ( !runcmd($cat) ) { die "Failed to execute system command in" . (caller(0))[3] ."\n"; }
- my $ffmpeg = "ffmpeg -i $workdir/complete.dv -aspect 16:9 -acodec pcm_s16le -vcodec dvvideo -y ".$outfile.' -f avi' ;
- if ( !runcmd($ffmpeg) ) { die "Failed to execute system command in" . (caller(0))[3] ."\n"; }
-# my $cmd = 'cat '.join(' ',@infiles).' | dvgrab -size 0 -stdin -f dv2 -opendml '.$outfile ;
-#savetemp();
- if ( -d $workdir ) {
- `rm -rf $workdir`;
- }
-}
-
-
-sub savetemp {
- my $outfile_base = $opts{'o'};
- $outfile_base =~ s/.+\.avi$//;
- print $outfile_base;
- my $f = "mv \"$workdir/startposter.dv\" \"$outfile_base-starposter.dv\"";
- if ( !runcmd($f) ) { die "Failed to execute system command in" . (caller(0))[3] ."\n"; }
- $f = "mv \"$workdir/endposter.dv\" \"$outfile_base-endposter.dv\"";
- if ( !runcmd($f) ) { die "Failed to execute system command in" . (caller(0))[3] ."\n"; }
-}
-
sub getsrtfile {
$opts{'i'} =~ /.+\/(.+)\..+$/; # Could be .dv or .avi or whatnot. This strips it off anyway.
return "$opts{'s'}/$1.srt";