/** * Test time parsing to seconds */ function testParseTimeString() { // Some time conversions: $this->assertEquals( TimedMediaHandler::parseTimeString( 100 ), 100 ); $this->assertEquals( TimedMediaHandler::parseTimeString( '1:0:0' ), 3600 ); $this->assertEquals( TimedMediaHandler::parseTimeString( -1 ), 0 ); // Test longer than duration check ( should return time -1 ) $this->assertEquals( TimedMediaHandler::parseTimeString( 10, 9 ), 8 ); // Test failures: $this->assertEquals( TimedMediaHandler::parseTimeString( '1:1:1:1' ), false ); $this->assertEquals( TimedMediaHandler::parseTimeString( 'abc' ), false ); }
public function execute() { global $wgUser, $wgEnabledTranscodeSet, $wgEnableTranscode, $wgWaitTimeForTranscodeReset; // Check if transcoding is enabled on this wiki at all: if( !$wgEnableTranscode ){ $this->dieUsage( 'Transcode is disabled on this wiki', 'disabledtranscode' ); } // Confirm the user has the transcode-reset right if( !$wgUser->isAllowed( 'transcode-reset' ) ){ $this->dieUsage( 'You don\'t have permission to reset transcodes', 'missingpermission' ); } $params = $this->extractRequestParams(); // Make sure we have a valid Title $titleObj = Title::newFromText( $params['title'] ); if ( !$titleObj || $titleObj->isExternal() ) { $this->dieUsageMsg( array( 'invalidtitle', $params['title'] ) ); } // Make sure the title can be transcoded if( !TimedMediaHandlerHooks::isTranscodableTitle( $titleObj ) ){ $this->dieUsage( array( 'invalidtranscodetitle', $params['title'] ) ); } $transcodeKey = false; // Make sure its a enabled transcode key we are trying to remove: // ( if you update your transcode keys the api is not how you purge the database of expired keys ) if( isset( $params['transcodekey'] ) ){ global $wgEnabledTranscodeSet; if( !in_array( $params['transcodekey'], $wgEnabledTranscodeSet ) ){ $this->dieUsage( 'Invalid or disabled transcode key: ' . htmlspecialchars( $params['transcodekey'] ) , 'badtranscodekey' ); } else { $transcodeKey = $params['transcodekey']; } } // Don't reset if less than 1 hour has passed and we have no error ) $timeSinceLastReset = self::checkTimeSinceLastRest( $titleObj->getDBKey(), $transcodeKey ); if( $timeSinceLastReset < $wgWaitTimeForTranscodeReset){ $this->dieUsage( 'Not enough time has passed since the last reset of this transcode. ' . TimedMediaHandler::getTimePassedMsg( $wgWaitTimeForTranscodeReset - $timeSinceLastReset ) . ' until this transcode can be reset', 'notenoughtimereset'); } // All good do the transcode removal: WebVideoTranscode::removeTranscodes( $titleObj, $transcodeKey ); $this->getResult()->addValue(null, 'success', 'removed transcode'); }
static function getThumbTime( $options ){ $length = $options['file']->getLength(); $thumbtime = false; // If start time param isset use that for the thumb: if( isset( $options['start'] ) ) { $thumbtime = TimedMediaHandler::parseTimeString( $options['start'], $length ); if( $thumbtime ) return $thumbtime; } // else use thumbtime if ( isset( $options['thumbtime'] ) ) { $thumbtime = TimedMediaHandler::parseTimeString( $options['thumbtime'], $length ); if( $thumbtime ) return $thumbtime; } // Seek to midpoint by default, it tends to be more interesting than the start return $length / 2; }
function runCheckJobThreadsLoop() { global $IP, $wgTranscodeBackgroundTimeLimit; // Check if we have $threads number of webTranscode jobs running else sleep $runingJobsCount = 0; foreach ($this->getProcessList() as $pid => $proc) { // Check that the process is a "runJobs.php" action with type webVideoTranscode argument if (strpos($proc['args'], 'runJobs.php') !== false && strpos($proc['args'], '--type webVideoTranscode') !== false) { if (TimedMediaHandler::parseTimeString($proc['time']) > $wgTranscodeBackgroundTimeLimit) { // should probably "kill" the process $killSuccess = posix_kill($pid); $this->output("Trying to expire transcode job: " . $pid . " result:" . $killSuccess); } else { // Job is oky add to count: $runingJobsCount++; } } } if ($runingJobsCount < $this->threads) { // Add one process: $parameters = array(); if ($this->wiki) { $parameters[] = '--wiki'; $parameters[] = $this->wiki; } $parameters[] = '--type'; $parameters[] = 'webVideoTranscode'; $parameters[] = '--maxjobs'; $parameters[] = '1'; $parameters[] = '--maxtime'; $parameters[] = $wgTranscodeBackgroundTimeLimit; $cmd = wfShellMaintenanceCmd("{$IP}/maintenance/runJobs.php", $parameters); $status = $this->runBackgroundProc($cmd); $this->output("{$runingJobsCount} existing job runners, Check for new transcode jobs: "); } else { // Just output a "tick" $this->output("{$runingJobsCount} transcode jobs active:\n"); } }
public static function getStatusMsg( $file, $state ){ // Check for success: if( !is_null( $state['time_success'] ) ) { return wfMsgHtml('timedmedia-completed-on', $state['time_success'] ); } // Check for error: if( !is_null( $state['time_error'] ) ){ if( !is_null( $state['error'] ) ){ $showErrorLink = self::$linker->link( $file->getTitle(), wfMsg('timedmedia-show-error'), array( 'title' => wfMsgHtml('timedmedia-error-on', $state['time_error'] ), 'class' => 'errorlink', 'data-error' => $state['error'] )); } return wfMsgHtml('timedmedia-error-on', $state['time_error'] ) . $showErrorLink; } $db = wfGetDB( DB_SLAVE ); // Check for started encoding if( !is_null( $state['time_startwork'] ) ){ $timePassed = wfTimestampNow() - $db->timestamp( $state['time_startwork'] ); // Get the rough estimate of time done: ( this is not very costly considering everything else // that happens in an action=purge video page request ) /*$filePath = WebVideoTranscode::getTargetEncodePath( $file, $state['key'] ); if( is_file( $filePath ) ){ $targetSize = WebVideoTranscode::getProjectedFileSize( $file, $state['key'] ); if( $targetSize === false ){ $doneMsg = wfMsgHtml('timedmedia-unknown-target-size', $wgLang->formatSize( filesize( $filePath ) ) ); } else { $doneMsg = wfMsgHtml('timedmedia-percent-done', round( filesize( $filePath ) / $targetSize, 2 ) ); } } */ // Predicting percent done is not working well right now ( disabled for now ) $doneMsg = ''; return wfMsgHtml('timedmedia-started-transcode', TimedMediaHandler::getTimePassedMsg( $timePassed ), $doneMsg ); } // Check for job added ( but not started encoding ) if( !is_null( $state['time_addjob'] ) ){ $timePassed = wfTimestampNow() - $db->timestamp( $state['time_addjob'] ) ; return wfMsgHtml('timedmedia-in-job-queue', TimedMediaHandler::getTimePassedMsg( $timePassed ) ); } // Return unknown status error: return wfMsgHtml('timedmedia-status-unknown'); }
function getShortDesc( $file ) { global $wgLang, $wgMediaAudioTypes, $wgMediaVideoTypes; $streamTypes = $this->getStreamTypes( $file ); if ( !$streamTypes ) { return parent::getShortDesc( $file ); } return wfMsg( 'timedmedia-webm-short-video', implode( '/', $streamTypes ), $wgLang->formatTimePeriod( $this->getLength( $file ) ) ); }
function getShortDesc( $file ) { global $wgLang, $wgMediaAudioTypes, $wgMediaVideoTypes; $streamTypes = $this->getStreamTypes( $file ); if ( !$streamTypes ) { return parent::getShortDesc( $file ); } if ( array_intersect( $streamTypes, $wgMediaVideoTypes ) ) { // Count multiplexed audio/video as video for short descriptions $msg = 'timedmedia-ogg-short-video'; } elseif ( array_intersect( $streamTypes, $wgMediaAudioTypes ) ) { $msg = 'timedmedia-ogg-short-audio'; } else { $msg = 'timedmedia-ogg-short-general'; } return wfMsg( $msg, implode( '/', $streamTypes ), $wgLang->formatTimePeriod( $this->getLength( $file ) ) ); }
public function monitorTranscode( $pid, &$retval, $encodingLog, $retvalLog ){ global $wgTranscodeBackgroundTimeLimit, $wgLang; $errorMsg = ''; $loopCount = 0; $oldFileSize = 0; $startTime = time(); $fileIsNotGrowing = false; $this->output( "Encoding with pid: $pid \npcntl_waitpid: " . pcntl_waitpid( $pid, $status, WNOHANG OR WUNTRACED) . "\nisProcessRunning: " . self::isProcessRunningKillZombie( $pid ) . "\n" ); // Check that the child process is still running ( note this does not work well with pcntl_waitpid // for some reason :( while( self::isProcessRunningKillZombie( $pid ) ) { //$this->output( "$pid is running" ); // Check that the target file is growing ( every 5 seconds ) if( $loopCount == 5 ){ // only run check if we are outputing to target file // ( two pass encoding does not output to target on first pass ) clearstatcache(); $newFileSize = is_file( $this->getTargetEncodePath() ) ? filesize( $this->getTargetEncodePath() ) : 0; // Don't start checking for file growth until we have an initial positive file size: if( $newFileSize > 0 ){ $this->output( $wgLang->formatSize( $newFileSize ). ' Total size, encoding ' . $wgLang->formatSize( ( $newFileSize - $oldFileSize ) / 5 ) . ' per second' ); if( $newFileSize == $oldFileSize ){ if( $fileIsNotGrowing ){ $errorMsg = "Target File is not increasing in size, kill process."; $this->output( $errorMsg ); // file is not growing in size, kill proccess $retval = 1; //posix_kill( $pid, 9); self::killProcess( $pid ); break; } // Wait an additional 5 seconds of the file not growing to confirm // the transcode is frozen. $fileIsNotGrowing = true; } else { $fileIsNotGrowing = false; } $oldFileSize = $newFileSize; } // reset the loop counter $loopCount = 0; } // Check if we have global job run-time has been exceeded: if ( $wgTranscodeBackgroundTimeLimit && time() - $startTime > $wgTranscodeBackgroundTimeLimit ){ $errorMsg = "Encoding exceeded max job run time ( " . TimedMediaHandler::seconds2npt( $maxTime ) . " ), kill process."; $this->output( $errorMsg ); // File is not growing in size, kill proccess $retval = 1; //posix_kill( $pid, 9); self::killProcess( $pid ); break; } // Sleep for one second before repeating loop $loopCount++; sleep( 1 ); } $returnPcntl = pcntl_wexitstatus( $status ); // check status wfSuppressWarnings(); $returnCodeFile = file_get_contents( $retvalLog ); wfRestoreWarnings(); //$this->output( "TranscodeJob:: Child pcntl return:". $returnPcntl . ' Log file exit code:' . $returnCodeFile . "\n" ); // File based exit code seems more reliable than pcntl_wexitstatus $retval = $returnCodeFile; // return the encoding log contents ( will be inserted into error table if an error ) // ( will be ignored and removed if success ) if( $errorMsg!= '' ){ $errorMsg.="\n\n"; } return $errorMsg . file_get_contents( $encodingLog ); }
function getTemporalUrlHash(){ if( $this->hashTime ){ return $this->hashTime; } $hash =''; if( $this->start ){ $startSec = TimedMediaHandler::parseTimeString( $this->start ); if( $startSec !== false ){ $hash.= '#t=' . TimedMediaHandler::seconds2npt( $startSec ); } } if( $this->end ){ if( $hash == '' ){ $hash .= '#t=0'; } $endSec = TimedMediaHandler::parseTimeString( $this->end ); if( $endSec !== false ){ $hash.= ',' . TimedMediaHandler::seconds2npt( $endSec ); } } $this->hashTime = $hash; return $this->hashTime; }