source: extensions/gsdl-video/trunk/perllib/plugins/AudioPlugin.pm@ 19828

Last change on this file since 19828 was 18556, checked in by davidb, 15 years ago

Restructing of VideoPlugin to be like ImagePlugin (with its supporting ImageConverter plugin). The pattern was then repeated for Audio, so we now have an AudioPlugin and AudioConverter. Where possible code is shared in a Multimedia base class

File size: 10.0 KB
Line 
1######################################################################
2#
3# AudioPlugin.pm -- plugin for processing video largely based on ImagePlug
4# A component of the Greenstone digital library software
5# from the New Zealand Digital Library Project at the
6# University of Waikato, New Zealand.
7#
8# Copyright (C) 1999 New Zealand Digital Library Project
9#
10# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 2 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program; if not, write to the Free Software
22# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23#
24###########################################################################
25
26package AudioPlugin;
27
28use strict;
29no strict 'refs'; # allow filehandles to be variables and viceversa
30no strict 'subs';
31
32use gsprintf;
33
34use MultimediaPlugin;
35use AudioConverter;
36
37sub BEGIN {
38 @AudioPlugin::ISA = ('MultimediaPlugin', 'AudioConverter');
39}
40
41
42my $arguments =
43 [ { 'name' => "process_exp",
44 'desc' => "{BasePlugin.process_exp}",
45 'type' => "regexp",
46 'deft' => &get_default_process_exp(),
47 'reqd' => "no" },
48 { 'name' => "converttotype",
49 'desc' => "{AudioPlugin.converttotype}",
50 'type' => "string",
51 'deft' => "",
52 'reqd' => "no" },
53 { 'name' => "converttobitrate",
54 'desc' => "{AudioPlugin.converttobitrate}",
55 'type' => "string",
56 'deft' => "128k",
57 'reqd' => "no" },
58 { 'name' => "streamingbitrate",
59 'desc' => "{AudioPlugin.streamingbitrate}",
60 'type' => "string",
61 'deft' => "200k",
62 'reqd' => "no" } ];
63
64my $options = { 'name' => "AudioPlugin",
65 'desc' => "{AudioPlugin.desc}",
66 'abstract' => "no",
67 'inherits' => "yes",
68 'args' => $arguments };
69
70
71sub new {
72 my ($class) = shift (@_);
73 my ($pluginlist,$inputargs,$hashArgOptLists) = @_;
74 push(@$pluginlist, $class);
75
76 push(@{$hashArgOptLists->{"ArgList"}},@{$arguments});
77 push(@{$hashArgOptLists->{"OptList"}},$options);
78
79 new AudioConverter($pluginlist, $inputargs, $hashArgOptLists);
80 my $self = new MultimediaPlugin($pluginlist, $inputargs, $hashArgOptLists);
81
82
83 return bless $self, $class;
84}
85
86
87sub begin {
88 my $self = shift (@_);
89 my ($pluginfo, $base_dir, $processor, $maxdocs) = @_;
90
91 $self->SUPER::begin(@_);
92 $self->AudioConverter::begin(@_);
93}
94
95
96sub init {
97 my $self = shift (@_);
98 my ($verbosity, $outhandle, $failhandle) = @_;
99
100 $self->SUPER::init(@_);
101 $self->AudioConverter::init(@_);
102}
103
104
105sub get_default_process_exp {
106 my $self = shift (@_);
107
108 return q^(?i)\.(mp3|au|aiff?|aifc|wav|ogg|flac|shn)$^;
109}
110
111
112
113# Create the keyframes, thumbnail and screenview images, and discover
114# the Video's size, width, and height using the ffmpeg utility.
115
116sub run_convert {
117 my $self = shift (@_);
118 my $base_dir = shift (@_);
119 my $filename = shift (@_); # filename with full path
120 my $file = shift (@_); # filename without path
121 my $doc_obj = shift (@_);
122
123 my $section = $doc_obj->get_top_section();
124
125 my $verbosity = $self->{'verbosity'};
126 my $outhandle = $self->{'outhandle'};
127
128 # check the filename is okay
129 return 0 if ($file eq "" || $filename eq "");
130
131 my $minimumsize = $self->{'minimumsize'};
132 if (defined $minimumsize && (-s $filename < $minimumsize)) {
133 print $outhandle "AudioPlugin: \"$filename\" too small, skipping\n"
134 if ($verbosity > 1);
135 }
136
137 my ($aduration,$asize,$atype,$afreq,$achan,$arate)
138 = &AudioConverter::identify($filename, $outhandle, $verbosity);
139
140 if ($aduration eq "N/A") {
141 print $outhandle "Unable to determine duration of $file\n";
142 $aduration = undef;
143 }
144
145 my ($dur_hour,$dur_min,$dur_sec)
146 = ($aduration =~ m/(\d+):(\d+):(\d+\.\d+)/);
147
148 my $total_dur_secs = undef;
149
150 if (defined $dur_hour && defined $dur_min && defined *dur_sec) {
151 $total_dur_secs = $dur_hour*3600 + $dur_min*60 + $dur_sec;
152 }
153
154
155 # Convert the video to a new type (if required).
156 my $converttotype = $self->{'converttotype'};
157 my $converttosize = $self->{'converttosize'};
158
159 # shorten duration prcessed for experimentation purposes
160 my $exp_duration = undef;
161
162 my $excerpt_duration = $self->{'excerpt_duration'};
163
164 if ((defined $excerpt_duration) && ($excerpt_duration ne "")) {
165 $exp_duration = $excerpt_duration;
166 my ($hh,$mm,$ss,$ms) = ($exp_duration =~ m/^(\d\d):(\d\d):(\d\d)\.?(\d\d)?/);
167 my $excerpt_dur_in_secs = $hh * 3600 + $mm * 60 + $ss;
168
169 if (defined $total_dur_secs) {
170 if ($excerpt_dur_in_secs > $total_dur_secs) {
171 # clip is already shorter than requested video excerpt duration
172 # set exp_duration back to undefined
173 $exp_duration = undef;
174 }
175 }
176 else {
177 $exp_duration = undef;
178 }
179 }
180
181
182 if (defined $exp_duration)
183 {
184 print $outhandle "Only encoding first $exp_duration of video.\n";
185 $self->{'exp_duration'} = $exp_duration;
186 }
187
188 my $ascii_only_filenames = $self->{'use_ascii_only_filenames'};
189
190 $self->init_cache_for_file($filename);
191
192
193 my $originalfilename = undef;
194 my $type = "unknown";
195
196 my $output_dir = $self->{'cached_dir'};
197 my $iaudio_root = $self->{'cached_file_root'};
198
199 my $convertto_regenerated = 0;
200 if (($converttotype ne "" && $filename !~ m/$converttotype$/i)) {
201
202 $originalfilename = $filename;
203
204 my $convertto_command = $self->audio_convertto_cmd($filename,$converttotype);
205
206 my $convertto_result;
207 my $convertto_error;
208
209 my $convertto_options = { @{$self->{'ffmpeg_monitor'}},
210 'message_prefix' => "Convert to",
211 'message' => "Converting audio to $converttotype" };
212
213 ($convertto_regenerated,$convertto_result,$convertto_error)
214 = $self->run_cached_general_cmd($convertto_command,$filename,$convertto_options);
215
216 $type = $converttotype;
217 }
218
219
220 # Add the audio metadata
221
222 my $file_unicode = pack("U0C*", map { ord($_) } split(//,$file)); # force explicitly to unicode
223
224 $file_unicode =~ s/\x{2018}|\x{2019}|\x{201C}|\x{201D}//g; # remove smart quotes as cause problem in URL for video server
225 $file_unicode =~ s/\x{2013}/\-/g; # change en-dash to '-' as again causes problems for video server
226
227## print STDERR "**** file metadata = ", &gsprintf::debug_unicode_string($file_unicode), "\n";
228
229
230 # split filename on char if specified
231 if ($file_unicode =~ m/\-/) {
232
233 my @file_split = split(/\s*\-\s*/,$file_unicode);
234 my $creator = shift @file_split;
235 my $title = shift @file_split;
236
237 $title =~ s/\..*?$//;
238 $title =~ s/^(.)/\u$1/;
239
240 $doc_obj->add_utf8_metadata($section,"Title",$title);
241
242 my @creator_split = split(/\s+and\s+/,$creator);
243 foreach my $c (@creator_split) {
244 $doc_obj->add_utf8_metadata($section,"Creator",$c);
245 }
246 }
247
248 $file = $file_unicode;
249 my $filemeta = $self->filename_to_utf8_metadata($file);
250 my $filemeta_url_safe = $self->url_safe($filemeta);
251
252 $doc_obj->add_utf8_metadata ($section, "Audio", $filemeta_url_safe);
253
254 # Also want to set filename as 'Source' metadata to be
255 # consistent with other plugins
256 $doc_obj->add_utf8_metadata ($section, "Source", $filemeta_url_safe);
257
258
259 if ($atype ne " ") {
260 $type = $atype;
261 }
262
263 $doc_obj->add_metadata ($section, "FileFormat", $type);
264 $doc_obj->add_metadata ($section, "FileSize", $asize);
265
266 $doc_obj->add_metadata ($section, "AudioType", $atype);
267 $doc_obj->add_metadata ($section, "AudioDuration", $aduration);
268
269 $doc_obj->add_metadata ($section, "AudioFreq", $afreq);
270 $doc_obj->add_metadata ($section, "AudioChannels", $achan);
271 $doc_obj->add_metadata ($section, "AudioRate", $arate);
272
273 $doc_obj->add_utf8_metadata ($section, "srclink",
274 "<a href=\"_httpprefix_/collect/[collection]/index/assoc/[assocfilepath]/[Audio]\">");
275 $doc_obj->add_utf8_metadata ($section, "/srclink", "</a>");
276 $doc_obj->add_metadata ($section, "srcicon", "[AudioType]");
277
278 # Add the image as an associated file
279 $doc_obj->associate_file($filename,$file,"audio/$type",$section);
280
281
282
283
284 my $streamable_regenerated = 0;
285 my $optionally_run_general_cmd
286 = ($convertto_regenerated) ? "regenerate_general_cmd" : "run_cached_general_cmd";
287
288 if ($self->{'enable_streaming'}) {
289
290 # Even if the original file or 'converttotype' is set to MP3
291 # we'll still go ahead and generate this MP3 as it might very
292 # well have different settings (such as a lower sample rate)
293
294 my $streaming_bitrate = $self->{'streamingbitrate'};
295 my $streaming_size = $self->{'streamingsize'};
296
297
298 my ($stream_cmd,$mp3_filename,$mp3_file)
299 = $self->audio_stream_cmd($originalfilename || $filename,
300 $streaming_bitrate, $streaming_size);
301
302
303 my $streamable_options = { @{$self->{'ffmpeg_monitor'}},
304 'message_prefix' => "Stream",
305 'message' => "Generating streamable audio: $mp3_file" };
306
307 my $streamable_result;
308 my $streamable_had_error;
309 ($streamable_regenerated,$streamable_result,$streamable_had_error)
310 = $self->$optionally_run_general_cmd($stream_cmd,$mp3_filename,$streamable_options);
311
312 if (!$streamable_had_error) {
313
314 my $streamable_url = $mp3_file;
315 my $streamable_url_safe = $self->url_safe($streamable_url);
316
317 $doc_obj->add_utf8_metadata ($section, "streamableaudio", $streamable_url_safe);
318 $doc_obj->associate_file($mp3_filename,$mp3_file,"audio/mpeg",
319 $section);
320 }
321
322 # The following aren't currently used
323
324 $self->{'mp3_file'} = $mp3_file;
325 $self->{'mp3_filename'} = $mp3_filename;
326 }
327
328
329 return $type;
330}
331
332
333
334
335
336
3371;
338
339
340
341
342
343
344
345
346
347
348
Note: See TracBrowser for help on using the repository browser.