Index: branches/wmf/1.16wmf4/extensions/OggHandler/README |
— | — | @@ -6,35 +6,48 @@ |
7 | 7 | |
8 | 8 | require_once( "$IP/extensions/OggHandler/OggHandler.php" ); |
9 | 9 | |
10 | | -FFmpeg |
| 10 | +oggThumb |
| 11 | +-------- |
11 | 12 | |
12 | | -We use FFmpeg for creating still images of videos, you will need a copy on your |
13 | | -server. |
| 13 | +oggThumb is the best utility currently available for creating still images from |
| 14 | +Theora videos. Unfortunately, that's not saying much, it is quite immature. |
14 | 15 | |
15 | | -Some old versions of FFmpeg had a bug which made it extremely slow to seek in |
16 | | -large theora videos in order to generate a thumbnail. This is fixed in the |
17 | | -current version. If you are using an old version of FFmpeg and find that |
18 | | -performance is extremely poor (tens of seconds) to generate thumbnails of |
19 | | -theora videos that are several minutes or more in length, try applying our |
20 | | -ffmpeg-bugfix.diff. |
| 16 | +It can be found in the oggvideotools package in some Linux distributions, or |
| 17 | +you can download the source from: |
21 | 18 | |
22 | | -Download source: http://ffmpeg.mplayerhq.hu/download.html |
23 | | -About the bug: https://roundup.mplayerhq.hu/roundup/ffmpeg/issue159 |
| 19 | +http://dev.streamnik.de/oggvideotools.html |
24 | 20 | |
25 | | -Suggested configure line for minimal functionality: |
| 21 | +Versions 0.8 (which is the current release at the time of writing) and earlier |
| 22 | +are effectively unusable, due to the lack of an output filename parameter. A |
| 23 | +fix has been applied in the pre-release version, and is expected to be released |
| 24 | +in version 0.9. In the meantime, if you have a Subversion client, you can get |
| 25 | +the development version using: |
26 | 26 | |
27 | | -./configure --disable-demuxers --disable-muxers --disable-decoders --disable-encoders \ |
28 | | - --disable-ffserver --disable-ffplay --enable-encoder=mjpeg --enable-muxer=mjpeg \ |
29 | | - --enable-decoder=theora --enable-demuxer=ogg --disable-network --disable-devices \ |
30 | | - --disable-parsers --enable-parser=vp3 --build-suffix=-still |
| 27 | +svn co https://oggvideotools.svn.sourceforge.net/svnroot/oggvideotools oggvideotools |
31 | 28 | |
32 | | -Set the FFmpeg binary location with: |
| 29 | +For best results, oggThumb should be used with libtheora 1.1 or later. |
33 | 30 | |
| 31 | +To enable oggThumb, put the following after the require line in your |
| 32 | +LocalSettings.php: |
| 33 | + |
| 34 | + $wgOggThumbLocation = '/path/to/oggThumb'; |
| 35 | + |
| 36 | +FFmpeg |
| 37 | +------ |
| 38 | + |
| 39 | +FFmpeg can be used to produce still images from Theora videos, but it suffers |
| 40 | +from a number of bugs. Some are fixed in the current development version, some |
| 41 | +are not. The most serious of these is an inability to create thumbnails where no |
| 42 | +keyframe exists between the requested point and the end of the file -- a |
| 43 | +situation which is quite common for videos with only one keyframe. |
| 44 | + |
| 45 | +To enable FFmpeg, set the FFmpeg binary location with: |
| 46 | + |
34 | 47 | $wgFFmpegLocation = '/path/to/ffmpeg'; |
35 | 48 | |
36 | | -after the require line in LocalSettings.php. (The default is |
37 | | -'/usr/bin/ffmpeg'.) |
| 49 | +after the require line in LocalSettings.php. The default is "/usr/bin/ffmpeg". |
| 50 | +If $wgOggThumbLocation is set to something other than false, FFmpeg will not be |
| 51 | +used. |
38 | 52 | |
39 | 53 | Cortado |
40 | 54 | ------- |
— | — | @@ -53,11 +66,12 @@ |
54 | 67 | PEAR File_Ogg |
55 | 68 | ------------- |
56 | 69 | |
57 | | -I forked the PEAR File_Ogg package and improved it significantly in order to |
58 | | -support this extension. I have now taken over maintainership of File_Ogg and |
59 | | -merged my changes into the latest release. This extension will now work with |
60 | | -either the bundled File_Ogg class, or a File_Ogg package from PEAR with |
61 | | -version 0.3.0 or greater. It is licensed under the LGPL. |
| 70 | +OggHandler developer Tim Starling forked the PEAR File_Ogg package and improved |
| 71 | +it significantly in order to support this extension. He has now taken over |
| 72 | +maintainership of File_Ogg and merged his changes into the latest release. |
| 73 | +This extension will now work with either the bundled File_Ogg class, or a |
| 74 | +File_Ogg package from PEAR with version 0.3.0 or greater. It is licensed under |
| 75 | +the LGPL. |
62 | 76 | |
63 | 77 | http://pear.php.net/package/File_Ogg |
64 | 78 | |
— | — | @@ -72,5 +86,3 @@ |
73 | 87 | http://www.everaldo.com/crystal/ |
74 | 88 | |
75 | 89 | They are licensed under the LGPL. |
76 | | - |
Index: branches/wmf/1.16wmf4/extensions/OggHandler/OggHandler.php |
— | — | @@ -41,25 +41,45 @@ |
42 | 42 | |
43 | 43 | /******************* CONFIGURATION STARTS HERE **********************/ |
44 | 44 | |
45 | | -// Set the supported ogg codecs: |
| 45 | +/** |
| 46 | + * The names of the supported video types, as they appear in the PEAR module. |
| 47 | + */ |
46 | 48 | $wgOggVideoTypes = array( 'Theora' ); |
| 49 | + |
| 50 | +/** |
| 51 | + * The names of the supported audio types, as they appear in the PEAR module. |
| 52 | + * These types will be described as audio, but only Vorbis is widely supported |
| 53 | + * by the client-side plugins. |
| 54 | + */ |
47 | 55 | $wgOggAudioTypes = array( 'Vorbis', 'Speex', 'FLAC' ); |
48 | 56 | |
49 | | -// Location of the FFmpeg binary |
| 57 | +/** |
| 58 | + * Location of the FFmpeg binary, or false to use oggThumb. See the notes |
| 59 | + * about thumbnailer choices in the README file. |
| 60 | + */ |
50 | 61 | $wgFFmpegLocation = '/usr/bin/ffmpeg'; |
51 | 62 | |
52 | | -// Filename or URL path to the Cortado Java player applet. |
53 | | -// |
54 | | -// If no path is included, the path to this extension's |
55 | | -// directory will be used by default -- this should work |
56 | | -// on most local installations. |
57 | | -// |
58 | | -// You may need to include a full URL here if $wgUploadPath |
59 | | -// specifies a host different from where the wiki pages are |
60 | | -// served -- the applet .jar file must come from the same host |
61 | | -// as the uploaded media files or Java security rules will |
62 | | -// prevent the applet from loading them. |
63 | | -// |
| 63 | +/** |
| 64 | + * Location of the oggThumb binary, or false to use FFmpeg. Note that only |
| 65 | + * version 0.9 (expected release in May 2010) or later is supported. See the |
| 66 | + * README file for more details. |
| 67 | + */ |
| 68 | +$wgOggThumbLocation = false; |
| 69 | + |
| 70 | + |
| 71 | +/** |
| 72 | + * Filename or URL path to the Cortado Java player applet. |
| 73 | + * |
| 74 | + * If no path is included, the path to this extension's |
| 75 | + * directory will be used by default -- this should work |
| 76 | + * on most local installations. |
| 77 | + * |
| 78 | + * You may need to include a full URL here if $wgUploadPath |
| 79 | + * specifies a host different from where the wiki pages are |
| 80 | + * served -- the applet .jar file must come from the same host |
| 81 | + * as the uploaded media files or Java security rules will |
| 82 | + * prevent the applet from loading them. |
| 83 | + */ |
64 | 84 | $wgCortadoJarFile = "cortado-ovt-stripped-0.5.1.jar"; |
65 | 85 | |
66 | 86 | /******************* CONFIGURATION ENDS HERE **********************/ |
Index: branches/wmf/1.16wmf4/extensions/OggHandler/OggHandler_body.php |
— | — | @@ -37,11 +37,12 @@ |
38 | 38 | function parseTimeString( $seekString, $length = false ) { |
39 | 39 | $parts = explode( ':', $seekString ); |
40 | 40 | $time = 0; |
41 | | - for ( $i = 0; $i < count( $parts ); $i++ ) { |
| 41 | + $multiplier = 1; |
| 42 | + for ( $i = count( $parts ) - 1; $i >= 0; $i--, $multiplier *= 60 ) { |
42 | 43 | if ( !is_numeric( $parts[$i] ) ) { |
43 | 44 | return false; |
44 | 45 | } |
45 | | - $time += intval( $parts[$i] ) * pow( 60, count( $parts ) - $i - 1 ); |
| 46 | + $time += $parts[$i] * $multiplier; |
46 | 47 | } |
47 | 48 | |
48 | 49 | if ( $time < 0 ) { |
— | — | @@ -51,6 +52,8 @@ |
52 | 53 | wfDebug( __METHOD__.": specified near-end or past-the-end time {$time}s, using end minus 1s\n" ); |
53 | 54 | $time = $length - 1; |
54 | 55 | } |
| 56 | + // Round to nearest 0.1s |
| 57 | + $time = round( $time, 1 ); |
55 | 58 | return $time; |
56 | 59 | } |
57 | 60 | |
— | — | @@ -58,7 +61,11 @@ |
59 | 62 | if ( isset( $params['thumbtime'] ) ) { |
60 | 63 | $time = $this->parseTimeString( $params['thumbtime'] ); |
61 | 64 | if ( $time !== false ) { |
62 | | - return 'seek=' . $time; |
| 65 | + $s = sprintf( "%.1f", $time ); |
| 66 | + if ( substr( $s, -2 ) == '.0' ) { |
| 67 | + $s = substr( $s, 0, -2 ); |
| 68 | + } |
| 69 | + return 'seek=' . $s; |
63 | 70 | } |
64 | 71 | } |
65 | 72 | return 'mid'; |
— | — | @@ -167,7 +174,6 @@ |
168 | 175 | } |
169 | 176 | |
170 | 177 | function doTransform( $file, $dstPath, $dstUrl, $params, $flags = 0 ) { |
171 | | - global $wgFFmpegLocation; |
172 | 178 | |
173 | 179 | $width = $params['width']; |
174 | 180 | $srcWidth = $file->getWidth(); |
— | — | @@ -215,6 +221,7 @@ |
216 | 222 | return new OggVideoDisplay( $file, $targetFileUrl, $dstUrl, $width, $height, $length, $dstPath, $noIcon ); |
217 | 223 | } |
218 | 224 | |
| 225 | + |
219 | 226 | $thumbTime = false; |
220 | 227 | if ( isset( $params['thumbtime'] ) ) { |
221 | 228 | $thumbTime = $this->parseTimeString( $params['thumbtime'], $length ); |
— | — | @@ -226,16 +233,38 @@ |
227 | 234 | |
228 | 235 | wfMkdirParents( dirname( $dstPath ) ); |
229 | 236 | |
230 | | - wfDebug( "Creating video thumbnail at $dstPath\n" ); |
| 237 | + global $wgOggThumbLocation; |
| 238 | + if ( $wgOggThumbLocation !== false ) { |
| 239 | + $status = $this->runOggThumb( $file->getPath(), $dstPath, $thumbTime ); |
| 240 | + } else { |
| 241 | + $status = $this->runFFmpeg( $file->getPath(), $dstPath, $thumbTime ); |
| 242 | + } |
| 243 | + if ( $status === true ) { |
| 244 | + return new OggVideoDisplay( $file, $file->getURL(), $dstUrl, $width, $height, |
| 245 | + $length, $dstPath ); |
| 246 | + } else { |
| 247 | + return new MediaTransformError( 'thumbnail_error', $width, $height, $status ); |
| 248 | + } |
| 249 | + } |
231 | 250 | |
| 251 | + /** |
| 252 | + * Run FFmpeg to generate a still image from a video file, using a frame close |
| 253 | + * to the given number of seconds from the start. |
| 254 | + * |
| 255 | + * Returns true on success, or an error message on failure. |
| 256 | + */ |
| 257 | + function runFFmpeg( $videoPath, $dstPath, $time ) { |
| 258 | + global $wgFFmpegLocation; |
| 259 | + wfDebug( __METHOD__." creating thumbnail at $dstPath\n" ); |
232 | 260 | $cmd = wfEscapeShellArg( $wgFFmpegLocation ) . |
233 | | - ' -ss ' . intval( $thumbTime ) . ' ' . |
234 | | - ' -i ' . wfEscapeShellArg( $file->getPath() ) . |
235 | | - # MJPEG, that's the same as JPEG except it's supported by the windows build of ffmpeg |
| 261 | + # FFmpeg only supports integer numbers of seconds |
| 262 | + ' -ss ' . intval( $time ) . ' ' . |
| 263 | + ' -i ' . wfEscapeShellArg( $videoPath ) . |
| 264 | + # MJPEG, that's the same as JPEG except it's supported ffmpeg |
236 | 265 | # No audio, one frame |
237 | 266 | ' -f mjpeg -an -vframes 1 ' . |
238 | 267 | wfEscapeShellArg( $dstPath ) . ' 2>&1'; |
239 | | - |
| 268 | + |
240 | 269 | $retval = 0; |
241 | 270 | $returnText = wfShellExec( $cmd, $retval ); |
242 | 271 | |
— | — | @@ -250,11 +279,44 @@ |
251 | 280 | } |
252 | 281 | $lines = array_slice( $lines, $i ); |
253 | 282 | } |
254 | | - // Return error box |
255 | | - return new MediaTransformError( 'thumbnail_error', $width, $height, implode( "\n", $lines ) ); |
| 283 | + // Return error message |
| 284 | + return implode( "\n", $lines ); |
256 | 285 | } |
| 286 | + // Success |
| 287 | + return true; |
| 288 | + } |
257 | 289 | |
258 | | - return new OggVideoDisplay( $file, $file->getURL(), $dstUrl, $width, $height, $length, $dstPath ); |
| 290 | + /** |
| 291 | + * Run oggThumb to generate a still image from a video file, using a frame |
| 292 | + * close to the given number of seconds from the start. |
| 293 | + * |
| 294 | + * Returns true on success, or an error message on failure. |
| 295 | + */ |
| 296 | + function runOggThumb( $videoPath, $dstPath, $time ) { |
| 297 | + global $wgOggThumbLocation; |
| 298 | + wfDebug( __METHOD__." creating thumbnail at $dstPath\n" ); |
| 299 | + $cmd = wfEscapeShellArg( $wgOggThumbLocation ) . |
| 300 | + ' -t ' . floatval( $time ) . |
| 301 | + ' -n ' . wfEscapeShellArg( $dstPath ) . |
| 302 | + ' ' . wfEscapeShellArg( $videoPath ) . ' 2>&1'; |
| 303 | + $retval = 0; |
| 304 | + $returnText = wfShellExec( $cmd, $retval ); |
| 305 | + |
| 306 | + if ( $this->removeBadFile( $dstPath, $retval ) || $retval ) { |
| 307 | + // oggThumb spams both stderr and stdout with useless progress |
| 308 | + // messages, and then often forgets to output anything when |
| 309 | + // something actually does go wrong. So interpreting its output is |
| 310 | + // a challenge. |
| 311 | + $lines = explode( "\n", str_replace( "\r\n", "\n", $returnText ) ); |
| 312 | + if ( count( $lines ) > 0 |
| 313 | + && preg_match( '/invalid option -- \'n\'$/', $lines[0] ) ) |
| 314 | + { |
| 315 | + return wfMsgForContent( 'ogg-oggThumb-version', '0.9' ); |
| 316 | + } else { |
| 317 | + return wfMsgForContent( 'ogg-oggThumb-failed' ); |
| 318 | + } |
| 319 | + } |
| 320 | + return true; |
259 | 321 | } |
260 | 322 | |
261 | 323 | function canRender( $file ) { return true; } |
Index: branches/wmf/1.16wmf4/extensions/OggHandler/OggHandler.i18n.php |
— | — | @@ -47,6 +47,8 @@ |
48 | 48 | 'ogg-dismiss' => 'Close', |
49 | 49 | 'ogg-download' => 'Download file', |
50 | 50 | 'ogg-desc-link' => 'About this file', |
| 51 | + 'ogg-oggThumb-version' => 'OggHandler requires oggThumb version $1 or later.', |
| 52 | + 'ogg-oggThumb-failed' => 'oggThumb failed to create the thumbnail.', |
51 | 53 | ); |
52 | 54 | |
53 | 55 | /** Message documentation (Message documentation) |
Property changes on: branches/wmf/1.16wmf4/extensions/OggHandler |
___________________________________________________________________ |
Name: svn:mergeinfo |
54 | 56 | + /branches/wmf-deployment/extensions/OggHandler:60970 |
/trunk/extensions/OggHandler:65149,65156,65563 |
/trunk/phase3/extensions/OggHandler:63545-63546,63549,63643,63764,63897-63901 |