1: #!/usr/bin/perl
2:
3: use strict;
4: use POSIX;
5:
6: # Paths to stuff.
7: my $path_convert = '/usr/bin/convert';
8: my $path_ffmpeg = '/usr/bin/ffmpeg';
9: my $path_midentify = '/usr/bin/midentify';
10: my $path_montage = '/usr/bin/montage';
11: my $path_mplayer = '/usr/bin/mplayer';
12:
13: # Silly tests.
14: die "This program cannot run if 00000001.png exists.\n" if (-e '00000001.png');
15: die "This program cannot run if 00000002.png exists.\n" if (-e '00000002.png');
16: die "This program cannot run if 00000001.gif exists.\n" if (-e '00000001.gif');
17:
18: # Read command line options.
19: my $file = shift @ARGV || die "Specify input file.\n";
20: my $rows = shift @ARGV || 6;
21: my $cols = shift @ARGV || 4;
22: my $geom = shift @ARGV || '240x180+10+10';
23: my $is_mpeg = 0;
24: $is_mpeg = 1 if ($file =~ /\.mpe?g$/i && -e $path_ffmpeg);
25:
26: # Other settings.
27: my $text_font = '@/usr/share/fonts/msttcorefonts/trebuc.ttf';
28: my $text_colour = '#0080';
29: my $text_bg = 'AliceBlue';
30: my $text_size = '18';
31:
32: # Create temporary directory.
33: my $tmp_dir = $ENV{'TMPDIR'} || $ENV{'TMP'} || '/tmp';
34: $tmp_dir .= '/dhyana-' . int(rand(100_000)) . '/';
35: mkdir ($tmp_dir);
36:
37: # Info about the video.
38: my @info = split /\n/, `$path_midentify '$file'`;
39: my %info;
40: foreach (@info)
41: {
42: my $k;
43: my $v;
44: chomp;
45: ($k, $v) = split /\=/;
46: $v =~ s/\\//g;
47: $info{$k} = $v;
48: }
49: @info = undef;
50:
51: # Create image annotation
52: my $annotation = sprintf("Size: %.02f MB (%d bytes)\n",
53: (-s $file)/(1024*1024),
54: (-s $file))
55: . sprintf("Length: %d:%02d:%02d\n",
56: POSIX::floor($info{'ID_LENGTH'}/3600),
57: POSIX::floor(($info{'ID_LENGTH'}%3600)/60),
58: POSIX::floor($info{'ID_LENGTH'}%60)
59: )
60: . 'Video: '.$info{'ID_VIDEO_WIDTH'} . 'x' . $info{'ID_VIDEO_HEIGHT'}
61: . ' (' . $info{'ID_VIDEO_FORMAT'} . ', '
62: . int($info{'ID_VIDEO_FPS'}) . ' frames/sec, '
63: . int($info{'ID_VIDEO_BITRATE'}/1000) . " kb/sec)\n"
64: . 'Audio: '.$info{'ID_AUDIO_NCH'} . ' chan'
65: . ' (' . $info{'ID_AUDIO_CODEC'} . ', '
66: . int($info{'ID_AUDIO_RATE'}/1000) . ' kHz, '
67: . int($info{'ID_AUDIO_BITRATE'}/1000) . " kb/sec)\n"
68: ;
69:
70: # Find out how long the video is and thus when we need to capture frames.
71: my $n_frames = $rows * $cols;
72: my $length = $info{'ID_LENGTH'};
73: my $part_length = $length / ($n_frames - 1);
74: my @times = (1);
75: for (my $i=1; $i<$n_frames; $i++)
76: {
77: push @times, int($i * $part_length)-1;
78: }
79:
80: # For each frame, capture it and save it to the temp directory.
81: my $i = 1;
82: foreach (@times)
83: {
84: &debug("Capturing frame $i, at $_ seconds.");
85: if ($is_mpeg)
86: {
87: &debug("Using FFMPEG instead of MPLAYER. (Slow.)");
88: my $cmd = $path_ffmpeg . " -i '$file'"
89: . ' -f image -img gif'
90: . " -ss $_ -vframes 1"
91: . " -y '%08d.gif'";
92: my $cmd_out = `$cmd 2>&1`;
93: system(sprintf("$path_convert '00000001.gif' '%s/frame-%06d.png'",
94: $tmp_dir, $_));
95: system("rm -f '00000001.gif'");
96: }
97: else
98: {
99: my $cmd = $path_mplayer . ' -really-quiet -nosound'
100: . ' -vo png:z=3 -frames 2'
101: . " -ss $_ '$file'";
102: my $cmd_out = `$cmd 2>&1`;
103: system(sprintf("mv '00000002.png' '%s/frame-%06d.png'",
104: $tmp_dir, $_));
105: system("rm -f '00000001.png' '00000002.png'");
106: }
107: $i++;
108: }
109:
110: # Creating montage.
111: &debug("Creating montage.");
112: my $cmd = $path_montage
113: . " -geometry '$geom'"
114: . " -background '$text_bg'"
115: . " -fill '$text_colour'"
116: . " -tile '".$cols."x".$rows."'"
117: . " $tmp_dir/frame-*.png $tmp_dir/montage.png";
118: my $cmd_out = `$cmd 2>&1`;
119: die "Error creating montage!\n" unless (-e "$tmp_dir/montage.png");
120:
121: # Annotating montage
122: &debug("Annotating montage.");
123: my $cmd = $path_convert
124: . " -background '$text_bg'"
125: . " -fill '$text_colour'"
126: . " -font '$text_font'"
127: . " -pointsize '$text_size'"
128: . " -gravity North"
129: . " -trim +repage"
130: . " -bordercolor '$text_bg'"
131: . " -border 20x20"
132: . " text:- '$tmp_dir/annotation.png'";
133: open(CONVERT, "|$cmd");
134: print CONVERT "$file\n$annotation\n";
135: close(CONVERT);
136: system("$path_convert -background '$text_bg' '$tmp_dir/annotation.png' '$tmp_dir/montage.png' -append '$tmp_dir/final.png'");
137:
138: # Finalising
139: &debug("Saving final file.");
140: my $file_out = $file;
141: $file_out =~ s/\.[^\.]+$/.jpeg/;
142: system("$path_convert -quality 90 '$tmp_dir/final.png' '$file_out'");
143: &debug("Cleaning up temporary files.");
144: system("rm -fr '$tmp_dir'");
145:
146: # Debugging function.
147: sub debug
148: {
149: my $x = shift @_;
150: print "debug: $x\n";
151: }