| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * This file is part of PHP-FFmpeg. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * (c) Alchemy <info@alchemy.fr> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * For the full copyright and license information, please view the LICENSE | 
					
						
							|  |  |  |  * file that was distributed with this source code. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace FFMpeg\Media; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | use Alchemy\BinaryDriver\Exception\ExecutionFailureException; | 
					
						
							|  |  |  | use FFMpeg\Coordinate\TimeCode; | 
					
						
							| 
									
										
										
										
											2013-06-26 00:21:12 +02:00
										 |  |  | use FFMpeg\Filters\Audio\SimpleFilter; | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  | use FFMpeg\Exception\RuntimeException; | 
					
						
							|  |  |  | use FFMpeg\Filters\Video\VideoFilters; | 
					
						
							| 
									
										
										
										
											2013-06-25 21:43:01 +02:00
										 |  |  | use FFMpeg\Filters\FilterInterface; | 
					
						
							|  |  |  | use FFMpeg\Format\FormatInterface; | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  | use FFMpeg\Format\ProgressableInterface; | 
					
						
							|  |  |  | use FFMpeg\Media\Frame; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 21:43:01 +02:00
										 |  |  | class Video extends Audio | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * {@inheritdoc} | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return VideoFilters | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function filters() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return new VideoFilters($this); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * {@inheritdoc} | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return Video | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2013-06-25 21:43:01 +02:00
										 |  |  |     public function addFilter(FilterInterface $filter) | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         $this->filters->add($filter); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $this; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2013-06-25 10:40:20 +02:00
										 |  |  |      * Exports the video in the desired format, applies registered filters. | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @param FormatInterface $format | 
					
						
							|  |  |  |      * @param string          $outputPathfile | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return Video | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @throws RuntimeException | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2013-06-25 21:43:01 +02:00
										 |  |  |     public function save(FormatInterface $format, $outputPathfile) | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2013-06-26 00:21:12 +02:00
										 |  |  |         $commands = array('-y', '-i', $this->pathfile); | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-26 00:21:12 +02:00
										 |  |  |         $this->addFilter(new SimpleFilter($format->getExtraParams(), 10)); | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if ($this->driver->getConfiguration()->has('ffmpeg.threads')) { | 
					
						
							| 
									
										
										
										
											2013-06-26 00:21:12 +02:00
										 |  |  |             $this->addFilter(new SimpleFilter(array('-threads', $this->driver->getConfiguration()->get('ffmpeg.threads')))); | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (null !== $format->getVideoCodec()) { | 
					
						
							| 
									
										
										
										
											2013-06-26 00:21:12 +02:00
										 |  |  |             $this->addFilter(new SimpleFilter(array('-vcodec', $format->getVideoCodec()))); | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (null !== $format->getAudioCodec()) { | 
					
						
							| 
									
										
										
										
											2013-06-26 00:21:12 +02:00
										 |  |  |             $this->addFilter(new SimpleFilter(array('-acodec', $format->getAudioCodec()))); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($this->filters as $filter) { | 
					
						
							|  |  |  |             $commands = array_merge($commands, $filter->apply($this, $format)); | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $commands[] = '-b:v'; | 
					
						
							|  |  |  |         $commands[] = $format->getKiloBitrate() . 'k'; | 
					
						
							|  |  |  |         $commands[] = '-refs'; | 
					
						
							|  |  |  |         $commands[] = '6'; | 
					
						
							|  |  |  |         $commands[] = '-coder'; | 
					
						
							|  |  |  |         $commands[] = '1'; | 
					
						
							|  |  |  |         $commands[] = '-sc_threshold'; | 
					
						
							|  |  |  |         $commands[] = '40'; | 
					
						
							|  |  |  |         $commands[] = '-flags'; | 
					
						
							|  |  |  |         $commands[] = '+loop'; | 
					
						
							|  |  |  |         $commands[] = '-me_range'; | 
					
						
							|  |  |  |         $commands[] = '16'; | 
					
						
							|  |  |  |         $commands[] = '-subq'; | 
					
						
							|  |  |  |         $commands[] = '7'; | 
					
						
							|  |  |  |         $commands[] = '-i_qfactor'; | 
					
						
							|  |  |  |         $commands[] = '0.71'; | 
					
						
							|  |  |  |         $commands[] = '-qcomp'; | 
					
						
							|  |  |  |         $commands[] = '0.6'; | 
					
						
							|  |  |  |         $commands[] = '-qdiff'; | 
					
						
							|  |  |  |         $commands[] = '4'; | 
					
						
							|  |  |  |         $commands[] = '-trellis'; | 
					
						
							|  |  |  |         $commands[] = '1'; | 
					
						
							|  |  |  |         $commands[] = '-b:a'; | 
					
						
							|  |  |  |         $commands[] = $format->getAudioKiloBitrate() . 'k'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $passPrefix = uniqid('pass-'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $pass1 = $commands; | 
					
						
							|  |  |  |         $pass2 = $commands; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $pass1[] = '-pass'; | 
					
						
							|  |  |  |         $pass1[] = '1'; | 
					
						
							|  |  |  |         $pass1[] = '-passlogfile'; | 
					
						
							|  |  |  |         $pass1[] = $passPrefix; | 
					
						
							|  |  |  |         $pass1[] = $outputPathfile; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $pass2[] = '-pass'; | 
					
						
							|  |  |  |         $pass2[] = '2'; | 
					
						
							|  |  |  |         $pass2[] = '-passlogfile'; | 
					
						
							|  |  |  |         $pass2[] = $passPrefix; | 
					
						
							|  |  |  |         $pass2[] = $outputPathfile; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $failure = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach (array($pass1, $pass2) as $pass => $passCommands) { | 
					
						
							|  |  |  |             try { | 
					
						
							|  |  |  |                 /** add listeners here */ | 
					
						
							|  |  |  |                 $listeners = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if ($format instanceof ProgressableInterface) { | 
					
						
							|  |  |  |                     $listeners = $format->createProgressListener($this, $this->ffprobe, $pass + 1, 2); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 $this->driver->command($passCommands, false, $listeners); | 
					
						
							|  |  |  |             } catch (ExecutionFailureException $e) { | 
					
						
							|  |  |  |                 $failure = $e; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this | 
					
						
							|  |  |  |             ->cleanupTemporaryFile(getcwd() . '/' . $passPrefix . '-0.log') | 
					
						
							|  |  |  |             ->cleanupTemporaryFile(getcwd() . '/' . $passPrefix . '-0.log') | 
					
						
							|  |  |  |             ->cleanupTemporaryFile(getcwd() . '/' . $passPrefix . '-0.log.mbtree'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (null !== $failure) { | 
					
						
							|  |  |  |             throw new RuntimeException('Encoding failed', $failure->getCode(), $failure); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $this; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2013-06-25 10:40:20 +02:00
										 |  |  |      * Gets the frame at timecode. | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @param  Timecode $at | 
					
						
							|  |  |  |      * @return Frame | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function frame(Timecode $at) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return new Frame($this->pathfile, $this->driver, $this->ffprobe, $at); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |