root/extensions/gsdl-video/trunk/perllib/plugins/AudioPlugin.pm @ 20003

Revision 20003, 10.4 KB (checked in by davidb, 10 years ago)

Some minor tweaks to better align the audio and video plugins

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 audio 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
335sub read_into_doc_obj {
336    my $self = shift (@_); 
337    my ($pluginfo, $base_dir, $file, $block_hash, $metadata, $processor, $maxdocs, $total_count, $gli) = @_;
338
339    $self->{'media_type'} = "audio";
340
341    my ($rv,$doc_obj) = $self->SUPER::read_into_doc_obj(@_);
342
343    if ($rv != 1) {
344    return ($rv,$doc_obj);
345    }
346   
347    $self->{'media_type'} = undef;
348
349    return ($rv,$doc_obj);
350}
351
352
353
3541;
355
356
357
358
359
360
361
362
363
364
365
Note: See TracBrowser for help on using the browser.