- 01
 - 02
 - 03
 - 04
 - 05
 - 06
 - 07
 - 08
 - 09
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 - 25
 - 26
 - 27
 - 28
 - 29
 - 30
 - 31
 - 32
 - 33
 - 34
 - 35
 - 36
 - 37
 - 38
 - 39
 - 40
 - 41
 - 42
 - 43
 - 44
 - 45
 - 46
 - 47
 - 48
 - 49
 - 50
 - 51
 - 52
 - 53
 - 54
 - 55
 - 56
 - 57
 - 58
 - 59
 - 60
 - 61
 - 62
 - 63
 - 64
 - 65
 - 66
 - 67
 - 68
 - 69
 - 70
 - 71
 - 72
 - 73
 - 74
 - 75
 - 76
 - 77
 - 78
 - 79
 - 80
 - 81
 - 82
 - 83
 - 84
 - 85
 - 86
 - 87
 - 88
 - 89
 - 90
 - 91
 - 92
 - 93
 - 94
 - 95
 - 96
 - 97
 - 98
 - 99
 
                        class EncoderCommand extends CConsoleCommand {
	public function actionStart()
	{
		if (file_exists($this->getLockFile())) { throw new RuntimeException('Encoder already started!'); return false; }
		if (!touch($this->getLockFile())) { throw new RuntimeException('Can not create lock file '.$this->getLockFile()); return false; }
		Yii::setPathOfAlias('webroot', dirname(dirname(dirname(__FILE__))));
		if (file_exists($this->getLogFile()))
			unlink($this->getLogFile());
		foreach (EncodingQueue::model()->findAll('phase != :lastPhase', array(':lastPhase' => EncodingQueue::ENCODED)) as $task) {
			// exec('php '.Yii::getPathOfAlias('application').'/yiic.php encoder process '.$task->id, $output);
			// echo implode(PHP_EOL, $output);
			$this->process($task);
		}
		unlink($this->getLockFile());
	}
	public function process(EncodingQueue $task) {
		
		// ещё не скачано
		if ($task->phase < EncodingQueue::DOWNLOADED) {
			$task->phase = EncodingQueue::DOWNLOADING;
			$task->save();
			if (!empty($task->remote_source_file) && !file_exists(Yii::getPathOfAlias('webroot').$task->source_file)) {
				echo 'Downloading to '.$task->source_file.' ...'.PHP_EOL;
				file_put_contents($this->getLogFile(), null);
				
				$cmd = 'curl -o '.escapeshellarg(Yii::getPathOfAlias('webroot').$task->source_file).' '.escapeshellarg($task->remote_source_file).' 1>'.$this->getLogFile().' 2>&1  &';
				exec($cmd, $output);
				echo implode(PHP_EOL, $output);
				$i = 0;
				while (true) {
					$c = file_get_contents($this->getLogFile());
					$f = explode("\r", $c);
					if (count($f) > 0) {
						$s = trim($f[count($f) - 1]);
						if (substr($c, -1) == "\n")
							break;
						sscanf($s, '%3d', $progress);
						$task->progress = $progress;
						$task->save();
						echo '...'.$progress.'%'.PHP_EOL;
					}
					sleep(1);
				}
			}
			$task->progress = -1;
			$task->phase = EncodingQueue::DOWNLOADED;
			$task->save();
		}
		// ещё не перекодировано
		if ($task->phase < EncodingQueue::ENCODED) {
			$task->phase = EncodingQueue::ENCODING;
			$task->save();
			if (!empty($task->ffmpeg_options)) {
				echo 'Encoding to '.$task->target_file.' ...'.PHP_EOL;
				file_put_contents($this->getLogFile(), null);
				$cmd = 'ffmpeg -y -i '.escapeshellarg(Yii::getPathOfAlias('webroot').$task->source_file).' '.$task->ffmpeg_options.' '.escapeshellarg(Yii::getPathOfAlias('webroot').$task->target_file).' 1>'.$this->getLogFile().' 2>&1 &';
				exec($cmd, $output);
				echo implode(PHP_EOL, $output);
				$i = 0;
				while (true) {
					$c = file_get_contents($this->getLogFile());
					if (!empty($c)) {
						preg_match('~Duration: (.*?), start:~', $c, $matches);
						$duration = $this->timeToSeconds($matches[1]);
						preg_match_all('~time=(.*?) bitrate~', $c, $matches); 
						$last = array_pop($matches);
						if (is_array($last)) $last = array_pop($last);
						$curTime = $this->timeToSeconds($last);
						$progress = 100*$curTime/$duration;
						$task->progress = $progress;
						$task->save();
						echo '...'.$progress.'%'.PHP_EOL;
						if (preg_match('~video:[0-9]+kB audio:[0-9]+kB~u', $c))
							break;
					}
					sleep(1);
				}
			} else {
				echo 'Copying '.Yii::getPathOfAlias('webroot').$task->source_file.' to '.Yii::getPathOfAlias('webroot').$task->target_file.' ...'.PHP_EOL;
				copy(Yii::getPathOfAlias('webroot').$task->source_file, Yii::getPathOfAlias('webroot').$task->target_file);
			}
			$task->progress = -1;
			$task->phase = EncodingQueue::ENCODED;
			$task->save();
		}
	}
	public function getLockFile($postfix = null) { return Yii::getPathOfAlias('application').'/runtime/encoder'.($postfix != null ? '.'.$postfix : null).'.lock'; }
	public function getLogFile($postfix = null) { return Yii::getPathOfAlias('application').'/runtime/encoder'.($postfix != null ? '.'.$postfix : null).'.log'; }
	/**
	 * Translates string like "00:04:12.17" into "252.17"
	 */
	protected function timeToSeconds($rawDuration) {
		$ar = array_reverse(explode(':', $rawDuration));
		$duration = floatval($ar[0]);
		if (!empty($ar[1])) $duration += intval($ar[1]) * 60;
		if (!empty($ar[2])) $duration += intval($ar[2]) * 60 * 60;
		return $duration;
	}
}
                                 
        
            Еще один "огрызок" из прошлого. Перекодировщик видео с ютуба, работал в несколько потоков и вполне стабильно держал небольшую нагрузку.
        
        
Комментарии (1) RSS
Добавить комментарий