r82345 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r82344‎ | r82345 | r82346 >
Date:19:23, 17 February 2011
Author:dale
Status:deferred
Tags:
Comment:
* refactored getBitRate into a method
* added global wgExcludeFromThumbnailPurge to keep video encodes around on ?action=purge requests
* moved supported extensions into a global for easy mapping
* added isAudio method to main TimedMediaHandler
* tweeked encoding settings for ENC_OGV_2MBS profile
* fixed getSources to do the right thing ( adds just one ogg and one webm per stream )
* fixes to ffmpeg maxSize support
Modified paths:
  • /trunk/extensions/TimedMediaHandler/TimedMediaHandler.hooks.php (modified) (history)
  • /trunk/extensions/TimedMediaHandler/TimedMediaHandler.i18n.php (modified) (history)
  • /trunk/extensions/TimedMediaHandler/TimedMediaHandler.php (modified) (history)
  • /trunk/extensions/TimedMediaHandler/TimedMediaHandler_body.php (modified) (history)
  • /trunk/extensions/TimedMediaHandler/TimedMediaThumbnail.php (modified) (history)
  • /trunk/extensions/TimedMediaHandler/WebVideoTranscode/WebVideoTranscode.php (modified) (history)
  • /trunk/extensions/TimedMediaHandler/WebVideoTranscode/WebVideoTranscodeJob.php (modified) (history)
  • /trunk/extensions/TimedMediaHandler/handlers/OggHandler/OggHandler.php (modified) (history)
  • /trunk/extensions/TimedMediaHandler/handlers/WebMHandler/WebMHandler.php (modified) (history)

Diff [purge]

Index: trunk/extensions/TimedMediaHandler/handlers/WebMHandler/WebMHandler.php
@@ -88,7 +88,10 @@
8989
9090 return $streamTypes;
9191 }
92 -
 92+ function getBitrate($file ){
 93+ $metadata = self::unpackMetadata( $file->getMetadata() );
 94+ return $metadata['bitrate'];
 95+ }
9396 function getLength( $file ) {
9497 $metadata = $this->unpackMetadata( $file->getMetadata() );
9598 if ( !$metadata || isset( $metadata['error'] ) ) {
@@ -110,7 +113,15 @@
111114 }
112115
113116 function getLongDesc( $file ) {
114 - return 'long desc';
 117+ global $wgLang;
 118+ return wfMsg('timedmedia-webm-long-video',
 119+ implode( '/', $this->getStreamTypes( $file ) ),
 120+ $wgLang->formatTimePeriod( $this->getLength($file) ),
 121+ $wgLang->formatBitrate( $this->getBitRate( $file ) ),
 122+ $wgLang->formatNum( $file->getWidth() ),
 123+ $wgLang->formatNum( $file->getHeight() )
 124+ );
 125+
115126 }
116127
117128 }
\ No newline at end of file
Index: trunk/extensions/TimedMediaHandler/handlers/OggHandler/OggHandler.php
@@ -159,13 +159,27 @@
160160 $size += $stream['size'];
161161 }
162162 }
163 - $bitrate = $length == 0 ? 0 : $size / $length * 8;
164163 return wfMsg( $msg, implode( '/', $streamTypes ),
165164 $wgLang->formatTimePeriod( $length ),
166 - $wgLang->formatBitrate( $bitrate ),
 165+ $wgLang->formatBitrate( $this->getBitRate( $file ) ),
167166 $wgLang->formatNum( $file->getWidth() ),
168167 $wgLang->formatNum( $file->getHeight() )
169168 );
170169 }
171170
 171+ function getBitRate( &$file ){
 172+ $size = 0;
 173+ $unpacked = $this->unpackMetadata( $file->getMetadata() );
 174+ if ( !$unpacked || isset( $metadata['error'] ) ) {
 175+ $length = 0;
 176+ } else {
 177+ $length = $this->getLength( $file );
 178+ foreach ( $unpacked['streams'] as $stream ) {
 179+ if( isset( $stream['size'] ) )
 180+ $size += $stream['size'];
 181+ }
 182+ }
 183+ return $length == 0 ? 0 : $size / $length * 8;
 184+ }
 185+
172186 }
\ No newline at end of file
Index: trunk/extensions/TimedMediaHandler/TimedMediaHandler_body.php
@@ -111,11 +111,13 @@
112112 function isMetadataValid( $image, $metadata ) {
113113 return $this->unpackMetadata( $metadata ) !== false;
114114 }
115 -
116115 function getThumbType( $ext, $mime, $params = null ) {
117116 return array( 'jpg', 'image/jpeg' );
118117 }
119 -
 118+ // checks if a given file is an audio file
 119+ function isAudio( $file ){
 120+ return ( $file->getWidth() == 0 && $file->getHeight() == 0 );
 121+ }
120122 function doTransform( $file, $dstPath, $dstUrl, $params, $flags = 0 ) {
121123 global $wgFFmpegLocation, $wgEnabledDerivatives;
122124
@@ -128,11 +130,12 @@
129131 'offset' => $this->getOffset( $file ),
130132 'width' => $params['width'],
131133 'height' => $srcWidth == 0 ? $srcHeight : $params['width']* $srcHeight / $srcWidth,
132 - 'isVideo' => ( $srcHeight != 0 && $srcWidth != 0 ),
 134+ 'isVideo' => !$this->isAudio( $file ),
133135 'thumbtime' => ( isset( $params['thumbtime'] ) )? $params['thumbtime'] : false,
134136 'start' => ( isset( $params['start'] ) )? $params['start'] : false,
135137 'end' => ( isset( $params['end'] ) )? $params['end'] : false
136138 );
 139+
137140 // No thumbs for audio
138141 if( $baseConfig['isVideo'] === false ){
139142 return new TimedMediaTransformOutput( $baseConfig );
Index: trunk/extensions/TimedMediaHandler/TimedMediaHandler.i18n.php
@@ -32,21 +32,28 @@
3333 'timedmedia-oggThumb-version' => 'OggHandler requires oggThumb version $1 or later.',
3434 'timedmedia-oggThumb-failed' => 'oggThumb failed to create the thumbnail.',
3535
36 - // derivative
37 - 'timedmedia-derivative-200_200kbs_ogv' => 'Ogg 200',
38 - 'timedmedia-derivative-desc-200_200kbs_ogv' => 'Low bandwith Ogg video (200 kbs)',
 36+ // source
 37+ 'timedmedia-source-file' => 'Source',
 38+ 'timedmedia-source-file-desc' => 'Source $1, $2 x $3 ($4)',
 39+
 40+ // derivative timedmedia-derivative-desc-220_200kbs.ogv
 41+ 'timedmedia-derivative-220_200kbs.ogv' => 'Ogg 200',
 42+ 'timedmedia-derivative-desc-220_200kbs.ogv' => 'Low bandwith Ogg video (200 kbs)',
 43+
3944 'timedmedia-derivative-360_400kbs.ogv' => 'Ogg 360P',
4045 'timedmedia-derivative-desc-360_400kbs.ogv' => 'Web streamable Ogg video (360P)',
 46+
4147 'timedmedia-derivative-480_600kbs.ogv' => 'Ogg 480P',
4248 'timedmedia-derivative-desc-480_600kbs.ogv' => 'Web streamable Ogg video (480P)',
 49+
4350 'timedmedia-derivative-720_VBR.ogv' => 'Ogg HQ',
4451 'timedmedia-derivative-desc-720_VBR.ogv' => 'High quality downloadable Ogg video (720P)',
4552
4653 // WebM profiles:
4754 'timedmedia-derivative-480_600kbs.webm' => 'WebM 480P',
48 - 'timedmedia-derivative-480_600kbs.webm' => 'Web stremable WebM (480P)',
 55+ 'timedmedia-derivative-desc-480_600kbs.webm' => 'Web stremable WebM (480P)',
4956 'timedmedia-derivative-720_VBR.webm' => 'WebM HQ',
50 - 'timedmedia-derivative-480_600kbs.webm' => 'High quality downloadable WebM (720P)',
 57+ 'timedmedia-derivative-desc720_VBR.webm' => 'High quality downloadable WebM (720P)',
5158
5259 );
5360
@@ -64,6 +71,13 @@
6572 */
6673 $messages['qqq'] = array(
6774 'timedmedia-desc' => '{{desc}}',
 75+ 'timedmedia-source-file-desc' => 'Source file description
 76+Paramaters are:
 77+* $1 file type ie webm or ogg
 78+* $2 resolution width
 79+* $3 resolution height
 80+* $3 human readable bitrate',
 81+
6882 'timedmedia-ogg-short-general' => 'File details for generic (non-audio, non-video) Ogg files, short version.
6983 Parameters are:
7084 * $1 file type, e.g. Vorbis, Speex
@@ -272,7 +286,7 @@
273287 'timedmedia-desc-link' => 'Інфармацыя пра гэты файл',
274288 'timedmedia-oggThumb-version' => 'OggHandler патрабуе oggThumb вэрсіі $1 ці больш позьняй.',
275289 'timedmedia-oggThumb-failed' => 'oggThumb не атрымалася стварыць мініятуру.',
276 - 'timedmedia-derivative-desc-200_200kbs_ogv' => 'Нізкапаточнае Ogg-відэа (200 кб/с)',
 290+ 'timedmedia-derivative-desc-220_200kbs.ogv' => 'Нізкапаточнае Ogg-відэа (200 кб/с)',
277291 'timedmedia-derivative-desc-360_400kbs.ogv' => 'Паточнае Ogg-відэа (360 пкс)',
278292 'timedmedia-derivative-desc-480_600kbs.ogv' => 'Паточнае Ogg-відэа (480 пкс)',
279293 'timedmedia-derivative-desc-720_VBR.ogv' => 'Высакаякаснае Ogg-відэа для загрузкі (720 пкс)',
@@ -468,7 +482,7 @@
469483 'timedmedia-desc-link' => 'Über diese Datei',
470484 'timedmedia-oggThumb-version' => 'OggHandler erfordert oggThumb in der Version $1 oder höher.',
471485 'timedmedia-oggThumb-failed' => 'oggThumb konnte kein Miniaturbild erstellen.',
472 - 'timedmedia-derivative-desc-200_200kbs_ogv' => 'Ogg-Videodatei mit niedriger Datenübertragungsrate (200 kbit/s)',
 486+ 'timedmedia-derivative-desc-220_200kbs.ogv' => 'Ogg-Videodatei mit niedriger Datenübertragungsrate (200 kbit/s)',
473487 'timedmedia-derivative-desc-360_400kbs.ogv' => 'Webstreamingfähige Ogg-Videodatei (360p)',
474488 'timedmedia-derivative-desc-480_600kbs.ogv' => 'Webstreamingfähige Ogg-Videodatei (480p)',
475489 'timedmedia-derivative-desc-720_VBR.ogv' => 'Qualitativ hochwertige Ogg-Videodatei (720p)',
@@ -700,7 +714,7 @@
701715 'timedmedia-desc-link' => 'À propos de ce fichier',
702716 'timedmedia-oggThumb-version' => 'OggHandler nécessite oggThumb, version $1 ou supérieure.',
703717 'timedmedia-oggThumb-failed' => 'oggThumb n’a pas réussi à créer la miniature.',
704 - 'timedmedia-derivative-desc-200_200kbs_ogv' => 'Vidéo Ogg bas débit (200 kbps)',
 718+ 'timedmedia-derivative-desc-220_200kbs.ogv' => 'Vidéo Ogg bas débit (200 kbps)',
705719 'timedmedia-derivative-desc-360_400kbs.ogv' => 'Vidéo Ogg lisible en continu sur le Web (360p)',
706720 'timedmedia-derivative-desc-480_600kbs.ogv' => 'Vidéo Ogg lisible en continu sur le web (480p)',
707721 'timedmedia-derivative-desc-720_VBR.ogv' => 'Vidéo Ogg téléchargeable de grande qualité (720p)',
@@ -958,7 +972,7 @@
959973 'timedmedia-desc-link' => 'A proposito de iste file',
960974 'timedmedia-oggThumb-version' => 'OggHandler require oggThumb version $1 o plus recente.',
961975 'timedmedia-oggThumb-failed' => 'oggThumb ha fallite de crear le miniatura.',
962 - 'timedmedia-derivative-desc-200_200kbs_ogv' => 'Video Ogg a basse largor de banda (200 kbs)',
 976+ 'timedmedia-derivative-desc-220_200kbs.ogv' => 'Video Ogg a basse largor de banda (200 kbs)',
963977 'timedmedia-derivative-desc-360_400kbs.ogv' => 'Video Ogg fluibile per web (360P)',
964978 'timedmedia-derivative-desc-480_600kbs.ogv' => 'Video Ogg fluibile per web (480P)',
965979 'timedmedia-derivative-desc-720_VBR.ogv' => 'Video Ogg discargabile de alte qualitate (720P)',
@@ -1237,7 +1251,7 @@
12381252 'timedmedia-desc-link' => 'Övver di Datei',
12391253 'timedmedia-oggThumb-version' => 'Dä <code lang="en">OggHandler</code> bruch <code lang="en">oggThumb</code> in dä Version $1 udder hüüter.',
12401254 'timedmedia-oggThumb-failed' => '<code lang="en">oggThumb</code> kunnt kei MiniBelldsche maache.',
1241 - 'timedmedia-derivative-desc-200_200kbs_ogv' => 'En Viddejo-Dattei met winnesch Bandbreide (200 kbs) em <i lang="en">Ogg</i>-Fommaat',
 1255+ 'timedmedia-derivative-desc-220_200kbs.ogv' => 'En Viddejo-Dattei met winnesch Bandbreide (200 kbs) em <i lang="en">Ogg</i>-Fommaat',
12421256 'timedmedia-derivative-desc-360_400kbs.ogv' => 'En Viddejo-Dattei met huhe Qualiteit (met 720p) em <i lang="en">Ogg</i>-Fommaat zom eronger laade',
12431257 'timedmedia-derivative-desc-480_600kbs.ogv' => 'En Viddejo-Dattei (met 480p) em <i lang="en">Ogg</i>-Fommaat för övver et Web ze striime',
12441258 'timedmedia-derivative-desc-720_VBR.ogv' => 'En Viddejo-Dattei met huhe Qualiteit (met 720p) em <i lang="en">Ogg</i>-Fommaat zom eronger laade',
@@ -1353,7 +1367,7 @@
13541368 'timedmedia-desc-link' => 'Информации за оваа податотека',
13551369 'timedmedia-oggThumb-version' => 'OggHandler бара oggThumb верзија $1 или понова.',
13561370 'timedmedia-oggThumb-failed' => 'oggThumb не успеа да ја создаде минијатурата.',
1357 - 'timedmedia-derivative-desc-200_200kbs_ogv' => 'Нископропусно Ogg-видео (200 кб/с)',
 1371+ 'timedmedia-derivative-desc-220_200kbs.ogv' => 'Нископропусно Ogg-видео (200 кб/с)',
13581372 'timedmedia-derivative-360_400kbs.ogv' => 'Ogg 360п',
13591373 'timedmedia-derivative-desc-360_400kbs.ogv' => 'Ogg-видео за емитување (360 пиксели)',
13601374 'timedmedia-derivative-480_600kbs.ogv' => 'Ogg 480п',
@@ -1500,7 +1514,7 @@
15011515 'timedmedia-desc-link' => 'Over dit bestand',
15021516 'timedmedia-oggThumb-version' => 'OggHandler vereist oggThumb versie $1 of hoger.',
15031517 'timedmedia-oggThumb-failed' => 'oggThumb kon geen miniatuur aanmaken.',
1504 - 'timedmedia-derivative-desc-200_200kbs_ogv' => 'Lage bandbreedte Ogg video (200 kbps)',
 1518+ 'timedmedia-derivative-desc-220_200kbs.ogv' => 'Lage bandbreedte Ogg video (200 kbps)',
15051519 'timedmedia-derivative-desc-360_400kbs.ogv' => 'Te webstreamen Off video (360P)',
15061520 'timedmedia-derivative-desc-480_600kbs.ogv' => 'Te webstreamen Ogg video (480P)',
15071521 'timedmedia-derivative-desc-720_VBR.ogv' => 'Hoge kwaliteit downloadbare Ogg video (720P)',
@@ -1683,7 +1697,7 @@
16841698 'timedmedia-desc-link' => 'Sobre este ficheiro',
16851699 'timedmedia-oggThumb-version' => 'O oggHandler requer o oggThumb versão $1 ou posterior.',
16861700 'timedmedia-oggThumb-failed' => 'O oggThumb não conseguiu criar a miniatura.',
1687 - 'timedmedia-derivative-desc-200_200kbs_ogv' => 'Vídeo Ogg de baixa largura de banda (200 kbs)',
 1701+ 'timedmedia-derivative-desc-220_200kbs.ogv' => 'Vídeo Ogg de baixa largura de banda (200 kbs)',
16881702 'timedmedia-derivative-desc-360_400kbs.ogv' => 'Vídeo Ogg para web streaming (360P)',
16891703 'timedmedia-derivative-desc-480_600kbs.ogv' => 'Vídeo Ogg para web streaming (480P)',
16901704 'timedmedia-derivative-desc-720_VBR.ogv' => 'Vídeo Ogg de alta qualidade para download (720 P)',
@@ -1886,7 +1900,7 @@
18871901 'timedmedia-desc-link' => 'O datoteki',
18881902 'timedmedia-oggThumb-version' => 'OggHandler potrebuje oggThumb različice $1 ali višje.',
18891903 'timedmedia-oggThumb-failed' => 'oggThumb ni uspel ustvariti predogledne sličice.',
1890 - 'timedmedia-derivative-desc-200_200kbs_ogv' => 'Video Ogg za majhno pasovno širino (200 kb/s)',
 1904+ 'timedmedia-derivative-desc-220_200kbs.ogv' => 'Video Ogg za majhno pasovno širino (200 kb/s)',
18911905 'timedmedia-derivative-desc-360_400kbs.ogv' => 'Video Ogg za pretakanje preko spleta (360P)',
18921906 'timedmedia-derivative-desc-480_600kbs.ogv' => 'Video Ogg za pretakanje preko spleta (480P)',
18931907 'timedmedia-derivative-desc-720_VBR.ogv' => 'Visoko ločljivostni video Ogg za prenos (720P)',
Index: trunk/extensions/TimedMediaHandler/TimedMediaHandler.php
@@ -8,22 +8,14 @@
99 // Set up the timed media handler dir:
1010 $timedMediaDir = dirname(__FILE__);
1111
12 -if ( !in_array( 'ogg', $wgFileExtensions ) ) {
13 - $wgFileExtensions[] = 'ogg';
 12+$wgTimedMediaHandlerFileExtensions = array( 'ogg', 'ogv', 'oga', 'webm');
 13+
 14+foreach($wgTimedMediaHandlerFileExtensions as $ext ){
 15+ if ( !in_array( $ext, $wgFileExtensions ) ) {
 16+ $wgFileExtensions[] = $ext;
 17+ }
1418 }
15 -if ( !in_array( 'ogv', $wgFileExtensions ) ) {
16 - $wgFileExtensions[] = 'ogv';
17 -}
18 -if ( !in_array( 'oga', $wgFileExtensions ) ) {
19 - $wgFileExtensions[] = 'oga';
20 -}
21 -if ( !in_array( 'webm', $wgFileExtensions ) ) {
22 - $wgFileExtensions[] = 'webm';
23 -}
2419
25 -
26 -
27 -
2820 // Timed Media Handler AutoLoad Classes:
2921 $wgAutoloadClasses['TimedMediaHandler'] = "$timedMediaDir/TimedMediaHandler_body.php";
3022 $wgAutoloadClasses['TimedMediaHandlerHooks'] = "$timedMediaDir/TimedMediaHandler.hooks.php";
@@ -111,6 +103,7 @@
112104 * -Only derivatives with smaller width than the source asset size will be created
113105 * -Derivative jobs are added to the mediaWiki JobQueue the first time the asset is displayed
114106 * -Derivative keys encode settings are defined in WebVideoTranscode.php
 107+ * -List Derivative from min to max
115108 */
116109 $wgEnabledTranscodeSet = array(
117110 // Cover accessibility for low bandwidth / low resources clients:
Index: trunk/extensions/TimedMediaHandler/WebVideoTranscode/WebVideoTranscodeJob.php
@@ -21,7 +21,7 @@
2222 parent::__construct( 'webVideoTranscode', $title, $params, $id );
2323 }
2424
25 - // Local function to debug output ( jobs don't have access to the maintenance class )
 25+ // Local function to debug output ( jobs don't have access to the maintenance output class )
2626 private function output( $msg ){
2727 print $msg . "\n";
2828 }
@@ -30,11 +30,21 @@
3131 public function run() {
3232 // Get the file object
3333 $file = wfLocalFile( $this->title );
 34+
 35+ $source = $file->getFullPath();
 36+ if( !is_file($source ) ){
 37+ $this->output( 'File not found: ' . $this->title );
 38+ return false;
 39+ }
3440 $transcodeKey = $this->params['transcodeKey'];
3541
3642 // Build the destination target
3743 $destinationFile = WebVideoTranscode::getTargetEncodePath( $file, $transcodeKey );
38 -
 44+
 45+ if( ! isset( WebVideoTranscode::$derivativeSettings[ $transcodeKey ] )){
 46+ $this->output("Transcode key $transcodeKey not found, skipping");
 47+ return false;
 48+ }
3949 $options = WebVideoTranscode::$derivativeSettings[ $transcodeKey ];
4050
4151 $this->output( "Encoding to codec: " . $options['codec'] );
@@ -44,14 +54,17 @@
4555 } else if( $options['codec'] == 'vp8' ){
4656 // Check for twopass:
4757 if( isset( $options['twopass'] ) ){
 58+ // ffmpeg requires manual two pass
4859 $status = $this->ffmpegEncode( $file, $destinationFile, $options, 1 );
4960 if( $status ){
5061 $status = $this->ffmpegEncode( $file, $destinationFile, $options, 2 );
51 - }
 62+ }
 63+ // remove any log files
 64+ $this->removeFffmpgeLogFiles( dirname( $destinationFile) );
 65+
5266 } else {
53 - $this->ffmpegEncode( $file, $destinationFile, $options );
 67+ $status = $this->ffmpegEncode( $file, $destinationFile, $options );
5468 }
55 -
5669 } else {
5770 wfDebug( 'Error unknown codec:' . $options['codec'] );
5871 $status = false;
@@ -60,12 +73,27 @@
6174 // If status is oky move the file to its final destination. ( timedMediaHandler will look for it there )
6275 // XXX would be nice to clear the cache for the pages where the title in use
6376 if( $status ){
64 - $status = @rename($destinationFile, WebVideoTranscode::getDerivativeFilePath( $file, $transcodeKey) );
 77+ wfSuppressWarnings();
 78+ $status = rename($destinationFile, WebVideoTranscode::getDerivativeFilePath( $file, $transcodeKey) );
 79+ wfRestoreWarnings();
6580 }
66 -
6781 return $status;
6882 }
69 -
 83+ function removeFffmpgeLogFiles( $dir ){
 84+ if (is_dir($dir)) {
 85+ if ($dh = opendir($dir)) {
 86+ while (($file = readdir($dh)) !== false) {
 87+ $ext = strtolower( pathinfo("$dir/$file", PATHINFO_EXTENSION) );
 88+ if( $ext == '.log' ){
 89+ wfSuppressWarnings();
 90+ unlink( "$dir/$file");
 91+ wfRestoreWarnings();
 92+ }
 93+ }
 94+ closedir($dh);
 95+ }
 96+ }
 97+ }
7098 /** Utility helper for ffmpeg and ffmpeg2theora mapping **/
7199
72100 function ffmpegEncode( $file, $target, $options, $pass=0 ){
@@ -75,7 +103,7 @@
76104 $this->output( "Encode:\n source:$source\n target:$target\n" );
77105
78106 // Set up the base command
79 - $cmd = wfEscapeShellArg( $wgFFmpegLocation ) . ' ' . wfEscapeShellArg( $source );
 107+ $cmd = wfEscapeShellArg( $wgFFmpegLocation ) . ' -i ' . wfEscapeShellArg( $source );
80108
81109 if( isset($options['preset']) ){
82110 if ($options['preset'] == "360p") {
@@ -86,14 +114,11 @@
87115 $cmd.= " -vpre libvpx-1080p";
88116 }
89117 }
90 - $this->output( "novideo::$cmd" );
91118 if ( isset( $options['novideo'] ) ) {
92119 $cmd.= " -vn ";
93120 } else {
94121 $cmd.= $this->ffmpegAddVideoOptions( $file, $target, $options, $pass );
95 -
96122 }
97 - $this->output( "add starty optiosn$cmd" );
98123
99124 // Check for start time
100125 if( isset( $options['starttime'] ) ){
@@ -105,15 +130,14 @@
106131 if( isset( $options['endtime'] ) ){
107132 $cmd.= ' -t ' . intval( $options['endtime'] ) - intval($options['starttime'] ) ;
108133 }
109 - $this->output( "add audio optiosn$cmd" );
110134
111 - if ( $pass == 1 || $options['noaudio'] ) {
 135+ if ( $pass == 1 || isset( $options['noaudio'] ) ) {
112136 $cmd.= ' -an';
113137 } else {
114138 $cmd.= $this->ffmpegAddAudioOptions( $file, $target, $options, $pass );
115139 }
116 - $this->output( "add webmn$cmd" );
117 - // Output WebM
 140+
 141+ // Output WebM
118142 $cmd.=" -f webm";
119143
120144 if ( $pass != 0 ) {
@@ -124,11 +148,15 @@
125149 if ($pass==1) {
126150 $cmd.= ' /dev/null';
127151 } else{
128 - $cmd.= $target;
129 - }
 152+ $cmd.= " $target";
 153+ }
130154
 155+ // Don't display shell output
 156+ $cmd .= ' 2>&1';
 157+
131158 $this->output( "Running cmd: \n\n" .$cmd . "\n" );
132159
 160+ // Right before we output remove the old file
133161 wfProfileIn( 'ffmpeg_encode' );
134162 wfShellExec( $cmd, $retval );
135163 wfProfileOut( 'ffmpeg_encode' );
@@ -141,7 +169,7 @@
142170 function ffmpegAddVideoOptions( $file, $target, $options, $pass){
143171 $cmd ='';
144172 // Add the boiler plate vp8 ffmpeg command:
145 - $cmd.="-y -skip_threshold 0 -rc_buf_aggressivity 0 -bufsize 6000k -rc_init_occupancy 4000 -threads 4";
 173+ $cmd.=" -y -skip_threshold 0 -rc_buf_aggressivity 0 -bufsize 6000k -rc_init_occupancy 4000 -threads 4";
146174
147175 // Check for video quality:
148176 if ( isset( $options['videoQuality'] ) && $options['videoQuality'] >= 0 ) {
@@ -154,35 +182,35 @@
155183 // Check for video bitrate:
156184 if ( isset( $options['videoBitrate'] ) ) {
157185 $cmd.= " -qmin 1 -qmax 51";
158 - $cmd.= " -vp " . wfEscapeShellArg( $options['videoBitrate'] );
 186+ $cmd.= " -vb " . wfEscapeShellArg( $options['videoBitrate'] * 1000 );
159187 }
160188 // Set the codec:
161189 $cmd.= " -vcodec libvpx";
162190
163 - die( $file->getWidth() + ':' + $file->getHeight() );
164 -
165191 // Check for aspect ratio
166 - if ($options['aspect']) {
 192+ if ( isset( $options['aspect'] ) ) {
167193 $aspectRatio = $options['aspect'];
168194 } else {
169 - $aspectRatio = $file->getWidth() + ':' + $file->getHeight();
 195+ $aspectRatio = $file->getWidth() . ':' . $file->getHeight();
170196 }
 197+ $dar = explode(':', $aspectRatio);
 198+ $dar = intval( $dar[0] ) / intval( $dar[1] );
171199
172 - $dar = $aspectRatio.split(':');
173 - $dar = intval( $aspectRatio[0] ) / intval( $aspectRatio[1] );
174 -
175200 // Check maxSize
176201 if (isset( $options['maxSize'] ) && intval( $options['maxSize'] ) > 0) {
177 - $sourceWidth = $file->getWidth();
178 - $sourceHeight =$file->getHeight();
179 - if ($sourceWidth > $options['maxSize'] ) {
180 - $width = intval( $options['maxSize'] );
181 - $height = intval( $width / $dar);
182 - } else {
183 - $height = intval( $options['maxSize'] );
184 - $width = intval( $height * $dar);
185 - }
186 - $cmd.= ' -s ' . intval( $width ) . 'x' . intval( $height );
 202+ // Check if source is smaller than maxSize
 203+ if( !WebVideoTranscode::isTargetLargerThanFile( $options['maxSize'], $file ) ){
 204+ $sourceWidth = $file->getWidth();
 205+ $sourceHeight = $file->getHeight();
 206+ if ($sourceWidth > $options['maxSize'] ) {
 207+ $width = intval( $options['maxSize'] );
 208+ $height = intval( $width / $dar);
 209+ } else {
 210+ $height = intval( $options['maxSize'] );
 211+ $width = intval( $height * $dar);
 212+ }
 213+ $cmd.= ' -s ' . intval( $width ) . 'x' . intval( $height );
 214+ }
187215 } else if (
188216 (isset( $options['width'] ) && $options['width'] > 0 )
189217 &&
@@ -253,18 +281,23 @@
254282 if( isset( self::$foggMap[$key] ) ){
255283 if( is_array( self::$foggMap[$key] ) ){
256284 $cmd.= ' '. implode(' ', WebVideoTranscode::$foggMap[$key] );
257 - }else if($val == 'true' || $val === true){
 285+ } else if ($val == 'true' || $val === true){
258286 $cmd.= ' '. self::$foggMap[$key];
259 - }else if( $val === false){
 287+ } else if ( $val === false){
260288 //ignore "false" flags
261 - }else{
 289+ } else {
262290 //normal get/set value
263291 $cmd.= ' '. self::$foggMap[$key] . ' ' . wfEscapeShellArg( $val );
264292 }
265293 }
266294 }
 295+
267296 // Add the output target:
268297 $cmd.= ' -o ' . wfEscapeShellArg ( $target );
 298+
 299+ // Don't display shell output
 300+ $cmd.=' 2>&1';
 301+
269302 $this->output( "Running cmd: \n\n" .$cmd . "\n" );
270303
271304 wfProfileIn( 'ffmpeg2theora_encode' );
@@ -276,6 +309,7 @@
277310 }
278311 return true;
279312 }
 313+
280314 /**
281315 * Mapping between firefogg api and ffmpeg2theora command line
282316 *
Index: trunk/extensions/TimedMediaHandler/WebVideoTranscode/WebVideoTranscode.php
@@ -30,7 +30,7 @@
3131 */
3232
3333 // Ogg Profiles
34 - const ENC_OGV_2MBS = '200_200kbs.ogv';
 34+ const ENC_OGV_2MBS = '220_200kbs.ogv';
3535 const ENC_OGV_4MBS = '360_400kbs.ogv';
3636 const ENC_OGV_6MBS = '480_600kbs.ogv';
3737 const ENC_OGV_HQ_VBR = '720_VBR.ogv';
@@ -50,11 +50,11 @@
5151 public static $derivativeSettings = array(
5252 WebVideoTranscode::ENC_OGV_2MBS =>
5353 array(
54 - 'maxSize' => '200',
55 - 'videoBitrate' => '128',
 54+ 'maxSize' => '220',
 55+ 'videoBitrate' => '160',
5656 'audioBitrate' => '32',
5757 'samplerate' => '22050',
58 - 'framerate' => '15',
 58+ //'framerate' => '15',
5959 'channels' => '1',
6060 'noUpscaling' => 'true',
6161 'twopass' => 'true',
@@ -105,19 +105,25 @@
106106 'noUpscaling' => 'true',
107107 'codec' => 'vp8',
108108 )
109 - );
110 - static public function getDerivativeFilePath($file, $transcodeKey){
 109+ );
 110+
 111+ static public function getDerivativeFilePath( &$file, $transcodeKey){
111112 return dirname(
112 - $file->getThumbPath(
113 - $file->thumbName( array() )
114 - )
115 - ) . '/' .
116 - $file->getName() . '.' .
117 - $transcodeKey ;
 113+ $file->getThumbPath(
 114+ $file->thumbName( array() )
 115+ )
 116+ ) . '/' .
 117+ $file->getName() . '.' .
 118+ $transcodeKey ;
 119+}
 120+
 121+ static public function getTargetEncodePath( &$file, $transcodeKey ){
 122+ // TODO probably should use some other temporary non-web accessible location for
 123+ // in-progress encodes.
 124+ $filePath = self::getDerivativeFilePath( $file, $transcodeKey );
 125+ $ext = strtolower( pathinfo( "$filePath", PATHINFO_EXTENSION ) );
 126+ return "{$filePath}.queue.{$ext}";
118127 }
119 - static public function getTargetEncodePath( $file, $transcodeKey ){
120 - return self::getDerivativeFilePath( $file, $transcodeKey ) . '.tmp';
121 - }
122128
123129 /**
124130 * Static function to get the set of video assets
@@ -132,71 +138,109 @@
133139 * @param {Object} File object
134140 * @returns an associative array of sources suitable for <source> tag output
135141 */
136 - static public function getSources( $file ){
137 - global $wgEnabledTranscodeSet;
 142+ static public function getSources( &$file ){
 143+ global $wgEnabledTranscodeSet, $wgLang;
138144 $sources = array();
139145
 146+ // Add the original file:
 147+ $sources[] = array(
 148+ 'src' => $file->getUrl(),
 149+ 'title' => wfMsg('timedmedia-source-file-desc',
 150+ $file->getHandler()->getMetadataType(),
 151+ $wgLang->formatNum( $file->getWidth() ),
 152+ $wgLang->formatNum( $file->getHeight() ),
 153+ $wgLang->formatBitrate( $file->getHandler()->getBitrate( $file ) )
 154+ ),
 155+ 'data-shorttitle' => wfMsg('timedmedia-source-file')
 156+ // TODO add some title and data about the file
 157+ );
 158+
 159+ // Just directly return audio sources ( for now no transcoding for audio )
 160+ if( $file->getHandler()->isAudio( $file ) ){
 161+ return $sources;
 162+ }
 163+
140164 // Setup local variables
141165 $fileName = $file->getName();
142166
143 - // Add the source file:
144 - $sources[] = array(
145 - 'src' => $file->getUrl()
146 - );
 167+ $addOggFlag = false;
 168+ $addWebMFlag = false;
147169
148 - $thumbName = $file->thumbName( array() );
149 - $thumbUrl = $file->getThumbUrl( $thumbName );
150 - $thumbUrlDir = dirname( $thumbUrl );
151 -
152 - $hasOggFlag = false;
153 - $hasWebMFlag = false;
 170+ $ext = pathinfo("$fileName", PATHINFO_EXTENSION);
154171 // Check the source file for .webm extension
155 - if( preg_match( "/$.webm/i", $fileName ) ) {
156 - $hasWebMFlag = true;
 172+ if( strtolower( $ext )== 'webm' ) {
 173+ $addWebMFlag = true;
157174 } else {
158 - // we only support ogg and webm so assume oky if we have .webm
159 - $hasOggFlag = true;
 175+ // If not webm assume ogg as the source file
 176+ $addOggFlag = true;
160177 }
161178
162 - foreach($wgEnabledTranscodeSet as $transcodeKey){
 179+ foreach( $wgEnabledTranscodeSet as $transcodeKey ){
163180 $derivativeFile = self::getDerivativeFilePath( $file, $transcodeKey);
164181 $codec = self::$derivativeSettings[$transcodeKey]['codec'];
165 - if( is_file( $derivativeFile ) ){
166 - $messageKey = str_replace('.','_',$transcodeKey );
167 - $sources[] = array(
168 - 'src' => $thumbUrlDir . '/' .$fileName . '.' . $transcodeKey,
169 - 'title' => wfMsg('timedmedia-derivative-desc-' . $messageKey ),
170 - 'data-shorttitle' => wfMsg('timedmedia-derivative-' . $messageKey)
171 - );
172 - } else {
173 - // Check if we should derivative to job queue
174 - // Skip if we have both ogg and one WebM and target is too small:
175 - if( $hasOggFlag && $hasWebMFlag &&
176 - !self::isTranscodeSmallerThanSource( $file, $transcodeKey ) ){
177 - continue;
 182+ // Check if we should add derivative to job queue
 183+ // Skip if we have both an Ogg & WebM and if target encode larger than source
 184+ if( self::isTargetLargerThanFile( self::$derivativeSettings[$transcodeKey]['maxSize'], $file) ){
 185+ continue;
 186+ }
 187+ // if we are checking for this derivative, update codec flags:
 188+ if( $codec == 'theora' ){
 189+ $addOggFlag = true;
 190+ }
 191+ if( $codec == 'vp8' ){
 192+ $addWebMFlag = true;
 193+ }
 194+ // Try and add the source
 195+ self::tryAddSource( $file, $sources,$transcodeKey );
 196+ }
 197+ // Make sure we got at least one ogg and webm encode
 198+ if( !$addOggFlag || !$addWebMFlag){
 199+ foreach( $wgEnabledTranscodeSet as $transcodeKey ){
 200+ if( !$addOggFlag && self::$derivativeSettings[$transcodeKey]['codec'] == 'theora' ){
 201+ self::tryAddSource( $file, $sources,$transcodeKey );
 202+ $addOggFlag = true;
178203 }
179 - // Update Flags:
180 - if( $codec == 'theora' ){
181 - $hasOggFlag = true;
 204+ if( !$addWebMFlag && self::$derivativeSettings[$transcodeKey]['codec'] == 'vp8' ){
 205+ self::tryAddSource( $file, $sources, $transcodeKey );
 206+ $addWebMFlag = true;
182207 }
183 - if( $codec == 'vp8' ){
184 - $hasWebMFlag = true;
185 - }
186 - self::updateJobQueue($file, $transcodeKey);
187208 }
188209 }
189210 return $sources;
190211 }
 212+
191213 /**
 214+ * Try to add a source to the sources param
 215+ * if the source is not found update the job queue
 216+ */
 217+ public static function tryAddSource( &$file, &$sources, $transcodeKey){
 218+ $derivativeFile = self::getDerivativeFilePath( $file, $transcodeKey);
 219+
 220+ $thumbName = $file->thumbName( array() );
 221+ $thumbUrl = $file->getThumbUrl( $thumbName );
 222+ $thumbUrlDir = dirname( $thumbUrl );
 223+
 224+ if( is_file( $derivativeFile ) ){
 225+ $sources[] = array(
 226+ 'src' => $thumbUrlDir . '/' .$file->getName() . '.' . $transcodeKey,
 227+ 'title' => wfMsg('timedmedia-derivative-desc-' . $transcodeKey ),
 228+ 'data-shorttitle' => wfMsg('timedmedia-derivative-' . $transcodeKey)
 229+ );
 230+ } else {
 231+ self::updateJobQueue($file, $transcodeKey);
 232+ }
 233+ }
 234+
 235+ /**
192236 * Update the job queue if the file is not already in the job queue:
193237 */
194 - public static function updateJobQueue( $file, $transcodeKey ){
 238+ public static function updateJobQueue( &$file, $transcodeKey ){
195239 $target = self::getTargetEncodePath( $file, $transcodeKey );
196240 // TranscodeKey not found ( check if the file is in progress ) ( tmp transcode location )
197241 if( is_file( $target ) ) {
198242 // file in progress / in queue
199 - // XXX Note we could check date and flag as failure
200 - } else {
 243+ // TODO We could check date and flag as failure somewhere
 244+ } else {
201245 // no in-progress file add to job queue and touch the target
202246 $job = new WebVideoTranscodeJob( $file->getTitle(), array(
203247 'transcodeMode' => 'derivative',
@@ -204,23 +248,24 @@
205249 ) );
206250 $jobId = $job->insert();
207251 if( $jobId ){
208 - // Make the thumb target directory and touch the file ( so we don't add the job again )
209 - wfMkdirParents( dirname( $target ) );
210 - touch( $target );
 252+ // Make the thumb target directory
 253+ if( ! is_dir( dirname( $target ) )){
 254+ wfMkdirParents( dirname( $target ) );
 255+ }
 256+ // Touch the target file
 257+ touch( $target );
211258 }
212259 }
213260 }
214261 /**
215 - * Test if a given transcode target is smaller than the source file
 262+ * Test if a given transcode target is larger than the source file
216263 *
217264 * @param $transcodeKey The static transcode key
218265 * @param $file {Object} File object
219266 */
220 - public static function isTranscodeSmallerThanSource( $file, $transcodeKey){
221 - return ( self::$derivativeSettings[$transcodeKey]['maxSize'] < $file->getWidth()
222 - &&
223 - self::$derivativeSettings[$transcodeKey]['maxSize'] < $file->getHeight()
224 - );
 267+ public static function isTargetLargerThanFile( $targetMaxSize, &$file){
 268+ $largerSize = ( $file->getWidth() > $file->getHeight() )?$file->getWidth(): $file->getHeight();
 269+ return ( $targetMaxSize > $largerSize );
225270 }
226271 }
227272
Index: trunk/extensions/TimedMediaHandler/TimedMediaHandler.hooks.php
@@ -10,7 +10,8 @@
1111 class TimedMediaHandlerHooks {
1212 // Register TimedMediaHandler Hooks
1313 static function register(){
14 - global $wgParserOutputHooks, $wgHooks, $wgJobClasses, $wgJobExplitRequestTypes, $wgMediaHandlers;
 14+ global $wgParserOutputHooks, $wgHooks, $wgJobClasses, $wgJobExplitRequestTypes,
 15+ $wgMediaHandlers, $wgExcludeFromThumbnailPurge, $wgTimedMediaHandlerFileExtensions;
1516
1617 // Setup media Handlers:
1718 $wgMediaHandlers['application/ogg'] = 'OggHandler';
@@ -27,7 +28,12 @@
2829 $wgJobExplitRequestTypes+= array(
2930 'webVideoTranscode'
3031 );
31 -
 32+ // Exclude transcoded assets from normal thumbnail purging
 33+ // ( a mantaince script could handle transcode asset purging)
 34+ $wgExcludeFromThumbnailPurge += $wgTimedMediaHandlerFileExtensions;
 35+ // Also add the .log file ( used in two pass encoding )
 36+ // ( probably should move in-progress encodes out of web accessible directory )
 37+ $wgExcludeFromThumbnailPurge+= array( 'log');
3238 /**
3339 * Add support for the "TimedText" NameSpace
3440 */
Index: trunk/extensions/TimedMediaHandler/TimedMediaThumbnail.php
@@ -7,16 +7,19 @@
88
99 // Set up lodal pointer to file
1010 $file = $options['file'];
11 -
12 - wfMkdirParents( dirname( $options['dstPath'] ) );
 11+ if( !is_dir( dirname( $options['dstPath'] ) ) ){
 12+ wfMkdirParents( dirname( $options['dstPath'] ) );
 13+ }
1314
1415 wfDebug( "Creating video thumbnail at" . $options['dstPath'] . "\n" );
1516
16 - // If ogg try OggThumb:
17 - if( self::tryOggThumb( $options) ){
18 - return true;
 17+ // If ogg try OggThumb:
 18+ if( $options['file']->getHandler()->getMetadataType() == 'ogg' ){
 19+ if( self::tryOggThumb( $options) ){
 20+ return true;
 21+ }
1922 }
20 - // Else try and return the ffmpeg thumbnail attempt:
 23+ // Else try ffmpeg and return result:
2124 return self::tryFfmpegThumb( $options );
2225 }
2326 /**
@@ -30,8 +33,7 @@
3134 global $wgOggThumbLocation;
3235
3336 // Check for ogg format file and $wgOggThumbLocation
34 - if( !$options['file']->getHandler()->getMetadataType() == 'ogg'
35 - || !$wgOggThumbLocation
 37+ if( !$wgOggThumbLocation
3638 || !is_file( $wgOggThumbLocation )
3739 ){
3840 return false;
@@ -57,8 +59,8 @@
5860 }
5961
6062 $cmd = wfEscapeShellArg( $wgFFmpegLocation ) .
61 - ' -ss ' . intval( $options['thumbtime'] ) . ' ' .
6263 ' -i ' . wfEscapeShellArg( $options['file']->getPath() ) .
 64+ ' -ss ' . intval( $options['thumbtime'] ) .
6365 # MJPEG, that's the same as JPEG except it's supported by the windows build of ffmpeg
6466 # No audio, one frame
6567 ' -f mjpeg -an -vframes 1 ' .
@@ -66,7 +68,6 @@
6769
6870 $retval = 0;
6971 $returnText = wfShellExec( $cmd, $retval );
70 -
7172 // Check if it was successful
7273 if ( !$options['file']->getHandler()->removeBadFile( $options['dstPath'], $retval ) ) {
7374 return true;

Follow-up revisions

RevisionCommit summaryAuthorDate
r82348Consistenxy fix for r82345...raymond21:16, 17 February 2011

Status & tagging log