| 
									
										
										
										
											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; | 
					
						
							| 
									
										
										
										
											2017-01-24 15:03:51 -03:00
										 |  |  | use FFMpeg\Coordinate\Dimension; | 
					
						
							| 
									
										
										
										
											2013-06-26 00:21:12 +02:00
										 |  |  | use FFMpeg\Filters\Audio\SimpleFilter; | 
					
						
							| 
									
										
										
										
											2013-10-10 13:27:06 +02:00
										 |  |  | use FFMpeg\Exception\InvalidArgumentException; | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							| 
									
										
										
										
											2013-10-10 15:09:10 +02:00
										 |  |  | use FFMpeg\Format\AudioInterface; | 
					
						
							|  |  |  | use FFMpeg\Format\VideoInterface; | 
					
						
							| 
									
										
										
										
											2013-10-10 13:27:06 +02:00
										 |  |  | use Neutron\TemporaryFilesystem\Manager as FsManager; | 
					
						
							| 
									
										
										
										
											2018-02-18 13:57:06 +01:00
										 |  |  | use FFMpeg\Filters\Video\ClipFilter; | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 21:43:01 +02:00
										 |  |  | class Video extends Audio | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2017-11-05 18:26:04 +01:00
										 |  |  |      * FileSystem Manager instance | 
					
						
							|  |  |  |      * @var Manager | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected $fs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * FileSystem Manager ID | 
					
						
							|  |  |  |      * @var int | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected $fsId; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @inheritDoc | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  |      * @return VideoFilters | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function filters() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return new VideoFilters($this); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2017-11-05 18:26:04 +01:00
										 |  |  |      * @inheritDoc | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  |      * @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
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2017-11-05 18:26:04 +01:00
										 |  |  |      * @param FormatInterface   $format | 
					
						
							|  |  |  |      * @param string            $outputPathfile | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  |      * @return Video | 
					
						
							|  |  |  |      * @throws RuntimeException | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2017-11-05 18:45:35 +01:00
										 |  |  |     public function save(FormatInterface $format, $outputPathfile) | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-11-05 18:26:04 +01:00
										 |  |  |         $passes = $this->buildCommand($format, $outputPathfile); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $failure = null; | 
					
						
							|  |  |  |         $totalPasses = $format->getPasses(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($passes as $pass => $passCommands) { | 
					
						
							|  |  |  |             try { | 
					
						
							|  |  |  |                 /** add listeners here */ | 
					
						
							|  |  |  |                 $listeners = null; | 
					
						
							| 
									
										
										
										
											2018-02-18 13:57:06 +01:00
										 |  |  |          | 
					
						
							| 
									
										
										
										
											2017-11-05 18:26:04 +01:00
										 |  |  |                 if ($format instanceof ProgressableInterface) { | 
					
						
							| 
									
										
										
										
											2018-02-18 13:57:06 +01:00
										 |  |  |                     $filters = clone $this->filters; | 
					
						
							|  |  |  |                     $duration = 0; | 
					
						
							| 
									
										
										
										
											2018-02-19 10:59:58 +01:00
										 |  |  |                      | 
					
						
							|  |  |  |                     // check the filters of the video, and if the video has the ClipFilter then
 | 
					
						
							|  |  |  |                     // take the new video duration and send to the
 | 
					
						
							|  |  |  |                     // FFMpeg\Format\ProgressListener\AbstractProgressListener class
 | 
					
						
							| 
									
										
										
										
											2018-02-18 13:57:06 +01:00
										 |  |  |                     foreach ($filters as $filter) { | 
					
						
							|  |  |  |                         if($filter instanceof ClipFilter){ | 
					
						
							|  |  |  |                             $duration = $filter->getDuration()->toSeconds(); | 
					
						
							|  |  |  |                             break; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     $listeners = $format->createProgressListener($this, $this->ffprobe, $pass + 1, $totalPasses, $duration); | 
					
						
							| 
									
										
										
										
											2017-11-05 18:26:04 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 $this->driver->command($passCommands, false, $listeners); | 
					
						
							|  |  |  |             } catch (ExecutionFailureException $e) { | 
					
						
							|  |  |  |                 $failure = $e; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->fs->clean($this->fsId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (null !== $failure) { | 
					
						
							|  |  |  |             throw new RuntimeException('Encoding failed', $failure->getCode(), $failure); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $this; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * NOTE: This method is different to the Audio's one, because Video is using passes. | 
					
						
							|  |  |  |      * @inheritDoc | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2017-11-05 18:45:35 +01:00
										 |  |  |     public function getFinalCommand(FormatInterface $format, $outputPathfile) { | 
					
						
							| 
									
										
										
										
											2017-11-05 18:26:04 +01:00
										 |  |  |         $finalCommands = array(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach($this->buildCommand($format, $outputPathfile) as $pass => $passCommands) { | 
					
						
							|  |  |  |             $finalCommands[] = implode(' ', $passCommands); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->fs->clean($this->fsId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $finalCommands; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * **NOTE:** This creates passes instead of a single command! | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @inheritDoc | 
					
						
							|  |  |  |      * @return string[][] | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2017-11-05 18:45:35 +01:00
										 |  |  |     protected function buildCommand(FormatInterface $format, $outputPathfile) { | 
					
						
							| 
									
										
										
										
											2013-06-26 00:21:12 +02:00
										 |  |  |         $commands = array('-y', '-i', $this->pathfile); | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-05 14:19:12 +02:00
										 |  |  |         $filters = clone $this->filters; | 
					
						
							|  |  |  |         $filters->add(new SimpleFilter($format->getExtraParams(), 10)); | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if ($this->driver->getConfiguration()->has('ffmpeg.threads')) { | 
					
						
							| 
									
										
										
										
											2013-08-05 14:19:12 +02:00
										 |  |  |             $filters->add(new SimpleFilter(array('-threads', $this->driver->getConfiguration()->get('ffmpeg.threads')))); | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2014-08-08 23:50:33 +02:00
										 |  |  |         if ($format instanceof VideoInterface) { | 
					
						
							| 
									
										
										
										
											2013-10-10 15:09:10 +02:00
										 |  |  |             if (null !== $format->getVideoCodec()) { | 
					
						
							|  |  |  |                 $filters->add(new SimpleFilter(array('-vcodec', $format->getVideoCodec()))); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2014-08-08 23:50:33 +02:00
										 |  |  |         if ($format instanceof AudioInterface) { | 
					
						
							| 
									
										
										
										
											2013-10-10 15:09:10 +02:00
										 |  |  |             if (null !== $format->getAudioCodec()) { | 
					
						
							|  |  |  |                 $filters->add(new SimpleFilter(array('-acodec', $format->getAudioCodec()))); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2013-06-26 00:21:12 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-05 14:19:12 +02:00
										 |  |  |         foreach ($filters as $filter) { | 
					
						
							| 
									
										
										
										
											2013-06-26 00:21:12 +02:00
										 |  |  |             $commands = array_merge($commands, $filter->apply($this, $format)); | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-08 23:50:33 +02:00
										 |  |  |         if ($format instanceof VideoInterface) { | 
					
						
							| 
									
										
										
										
											2013-10-10 15:09:10 +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'; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-08 23:50:33 +02:00
										 |  |  |         if ($format instanceof AudioInterface) { | 
					
						
							| 
									
										
										
										
											2013-10-10 15:09:10 +02:00
										 |  |  |             if (null !== $format->getAudioKiloBitrate()) { | 
					
						
							|  |  |  |                 $commands[] = '-b:a'; | 
					
						
							|  |  |  |                 $commands[] = $format->getAudioKiloBitrate() . 'k'; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2014-08-08 23:50:33 +02:00
										 |  |  |             if (null !== $format->getAudioChannels()) { | 
					
						
							|  |  |  |                 $commands[] = '-ac'; | 
					
						
							|  |  |  |                 $commands[] = $format->getAudioChannels(); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2013-08-05 14:19:12 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 15:19:32 -03:00
										 |  |  |         // If the user passed some additional parameters
 | 
					
						
							| 
									
										
										
										
											2017-06-30 21:27:10 +02:00
										 |  |  |         if ($format instanceof VideoInterface) { | 
					
						
							|  |  |  |             if (null !== $format->getAdditionalParameters()) { | 
					
						
							|  |  |  |                 foreach ($format->getAdditionalParameters() as $additionalParameter) { | 
					
						
							|  |  |  |                     $commands[] = $additionalParameter; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2017-01-24 15:19:32 -03:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-28 05:18:22 +08:00
										 |  |  |         // Merge Filters into one command
 | 
					
						
							| 
									
										
										
										
											2017-10-11 16:45:20 -07:00
										 |  |  |         $videoFilterVars = $videoFilterProcesses = array(); | 
					
						
							| 
									
										
										
										
											2017-06-28 05:18:22 +08:00
										 |  |  |         for($i=0;$i<count($commands);$i++) { | 
					
						
							|  |  |  |             $command = $commands[$i]; | 
					
						
							|  |  |  |             if ( $command == '-vf' ) { | 
					
						
							|  |  |  |                 $commandSplits = explode(";", $commands[$i + 1]); | 
					
						
							|  |  |  |                 if ( count($commandSplits) == 1 ) { | 
					
						
							|  |  |  |                     $commandSplit = $commandSplits[0]; | 
					
						
							|  |  |  |                     $command = trim($commandSplit); | 
					
						
							|  |  |  |                     if ( preg_match("/^\[in\](.*?)\[out\]$/is", $command, $match) ) { | 
					
						
							|  |  |  |                         $videoFilterProcesses[] = $match[1]; | 
					
						
							|  |  |  |                     } else { | 
					
						
							| 
									
										
										
										
											2017-11-05 18:26:04 +01:00
										 |  |  |                         $videoFilterProcesses[] = $command; | 
					
						
							| 
									
										
										
										
											2017-06-28 05:18:22 +08:00
										 |  |  |                     } | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     foreach($commandSplits as $commandSplit) { | 
					
						
							|  |  |  |                         $command = trim($commandSplit); | 
					
						
							|  |  |  |                         if ( preg_match("/^\[[^\]]+\](.*?)\[[^\]]+\]$/is", $command, $match) ) { | 
					
						
							|  |  |  |                             $videoFilterProcesses[] = $match[1]; | 
					
						
							|  |  |  |                         } else { | 
					
						
							|  |  |  |                             $videoFilterVars[] = $command; | 
					
						
							| 
									
										
										
										
											2017-11-05 18:26:04 +01:00
										 |  |  |                         } | 
					
						
							| 
									
										
										
										
											2017-06-28 05:18:22 +08:00
										 |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 unset($commands[$i]); | 
					
						
							|  |  |  |                 unset($commands[$i + 1]); | 
					
						
							|  |  |  |                 $i++; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $videoFilterCommands = $videoFilterVars; | 
					
						
							|  |  |  |         $lastInput = 'in'; | 
					
						
							|  |  |  |         foreach($videoFilterProcesses as $i => $process) { | 
					
						
							|  |  |  |             $command = '[' . $lastInput .']'; | 
					
						
							|  |  |  |             $command .= $process; | 
					
						
							|  |  |  |             $lastInput = 'p' . $i; | 
					
						
							| 
									
										
										
										
											2017-11-05 18:26:04 +01:00
										 |  |  |             if($i === (count($videoFilterProcesses) - 1)) { | 
					
						
							| 
									
										
										
										
											2017-06-28 05:18:22 +08:00
										 |  |  |                 $command .= '[out]'; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 $command .= '[' . $lastInput . ']'; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-11-05 18:26:04 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-28 05:18:22 +08:00
										 |  |  |             $videoFilterCommands[] = $command; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-11-05 18:26:04 +01:00
										 |  |  |         $videoFilterCommand = implode(';', $videoFilterCommands); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if($videoFilterCommand) { | 
					
						
							| 
									
										
										
										
											2017-06-28 05:18:22 +08:00
										 |  |  |             $commands[] = '-vf'; | 
					
						
							|  |  |  |             $commands[] = $videoFilterCommand; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-11-05 18:26:04 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $this->fs = FsManager::create(); | 
					
						
							|  |  |  |         $this->fsId = uniqid('ffmpeg-passes'); | 
					
						
							|  |  |  |         $passPrefix = $this->fs->createTemporaryDirectory(0777, 50, $this->fsId) . '/' . uniqid('pass-'); | 
					
						
							| 
									
										
										
										
											2013-10-10 13:27:06 +02:00
										 |  |  |         $passes = array(); | 
					
						
							|  |  |  |         $totalPasses = $format->getPasses(); | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-05 18:26:04 +01:00
										 |  |  |         if(!$totalPasses) { | 
					
						
							| 
									
										
										
										
											2013-10-10 13:27:06 +02:00
										 |  |  |             throw new InvalidArgumentException('Pass number should be a positive value.'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-05 18:26:04 +01:00
										 |  |  |         for($i = 1; $i <= $totalPasses; $i++) { | 
					
						
							| 
									
										
										
										
											2013-10-10 13:27:06 +02:00
										 |  |  |             $pass = $commands; | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-10 13:27:06 +02:00
										 |  |  |             if ($totalPasses > 1) { | 
					
						
							|  |  |  |                 $pass[] = '-pass'; | 
					
						
							|  |  |  |                 $pass[] = $i; | 
					
						
							|  |  |  |                 $pass[] = '-passlogfile'; | 
					
						
							|  |  |  |                 $pass[] = $passPrefix; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-10 14:59:38 +02:00
										 |  |  |             $pass[] = $outputPathfile; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-10 13:27:06 +02:00
										 |  |  |             $passes[] = $pass; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-05 18:26:04 +01:00
										 |  |  |         return $passes; | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2013-06-25 10:40:20 +02:00
										 |  |  |      * Gets the frame at timecode. | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2013-06-26 15:17:16 +02:00
										 |  |  |      * @param  TimeCode $at | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  |      * @return Frame | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2013-06-26 15:17:16 +02:00
										 |  |  |     public function frame(TimeCode $at) | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2013-09-04 19:50:38 +02:00
										 |  |  |         return new Frame($this, $this->driver, $this->ffprobe, $at); | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-01-24 15:03:51 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Extracts a gif from a sequence of the video. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param  TimeCode $at | 
					
						
							|  |  |  |      * @param  Dimension $dimension | 
					
						
							|  |  |  |      * @param  integer $duration | 
					
						
							|  |  |  |      * @return Gif | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function gif(TimeCode $at, Dimension $dimension, $duration = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return new Gif($this, $this->driver, $this->ffprobe, $at, $dimension, $duration); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-02-14 13:55:07 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Concatenates a list of videos into one unique video. | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2017-06-28 00:18:05 +02:00
										 |  |  |      * @param  array $sources | 
					
						
							| 
									
										
										
										
											2017-02-14 13:55:07 -03:00
										 |  |  |      * @return Concat | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function concat($sources) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return new Concat($sources, $this->driver, $this->ffprobe); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-06-25 10:03:20 +02:00
										 |  |  | } |