public function register(Application $app)
 {
     $app['ffmpeg.configuration'] = array();
     $app['ffmpeg.default.configuration'] = array('ffmpeg.threads' => 4, 'ffmpeg.timeout' => 300, 'ffmpeg.binaries' => array('avconv', 'ffmpeg'), 'ffprobe.timeout' => 30, 'ffprobe.binaries' => array('avprobe', 'ffprobe'));
     $app['ffmpeg.logger'] = null;
     $app['ffmpeg.configuration.build'] = $app->share(function (Application $app) {
         return array_replace($app['ffmpeg.default.configuration'], $app['ffmpeg.configuration']);
     });
     $app['ffmpeg'] = $app['ffmpeg.ffmpeg'] = $app->share(function (Application $app) {
         $configuration = $app['ffmpeg.configuration.build'];
         if (isset($configuration['ffmpeg.timeout'])) {
             $configuration['timeout'] = $configuration['ffmpeg.timeout'];
         }
         return FFMpeg::create($configuration, $app['ffmpeg.logger'], $app['ffmpeg.ffprobe']);
     });
     $app['ffprobe.cache'] = $app->share(function () {
         return new ArrayCache();
     });
     $app['ffmpeg.ffprobe'] = $app->share(function (Application $app) {
         $configuration = $app['ffmpeg.configuration.build'];
         if (isset($configuration['ffmpeg.timeout'])) {
             $configuration['timeout'] = $configuration['ffprobe.timeout'];
         }
         return FFProbe::create($configuration, $app['ffmpeg.logger'], $app['ffprobe.cache']);
     });
 }
 /**
  * @covers MediaVorus\MediaCollection::match
  */
 public function testMatch()
 {
     $logger = new Logger('test');
     $logger->pushHandler(new NullHandler());
     $mediavorus = new MediaVorus(Reader::create($logger), Writer::create($logger), FFProbe::create());
     $collection = $mediavorus->inspectDirectory(__DIR__ . '/../../files/');
     $audio = $collection->match(new MediaType(MediaInterface::TYPE_AUDIO));
     $this->assertInstanceOf('\\Doctrine\\Common\\Collections\\ArrayCollection', $audio);
     $this->assertGreaterThan(0, $audio->count());
     foreach ($audio as $audio) {
         $this->assertEquals(MediaInterface::TYPE_AUDIO, $audio->getType());
     }
     $notAudio = $collection->match(new MediaType(MediaInterface::TYPE_AUDIO), true);
     $this->assertGreaterThan(0, $notAudio->count());
     $this->assertInstanceOf('\\Doctrine\\Common\\Collections\\ArrayCollection', $notAudio);
     foreach ($notAudio as $audio) {
         $this->assertFalse(MediaInterface::TYPE_AUDIO === $audio->getType());
     }
 }
Esempio n. 3
0
 public function __construct($file, $screenshotDirectory = '/tmp')
 {
     $this->file = $file;
     $this->screenshotDirectory = $screenshotDirectory;
     $this->ffmpeg = FFMpeg::create();
     $this->ffprobe = FFProbe::create();
     $this->movie = $this->ffmpeg->open($file);
     $this->info = $this->ffprobe->format($file);
 }
Esempio n. 4
0
 /**
  * Instantiate mediavorus to register the mime types
  */
 public function setUp()
 {
     parent::setUp();
     $logger = new Logger('test');
     $logger->pushHandler(new NullHandler());
     $mediavorus = new MediaVorus(Reader::create($logger), Writer::create($logger), FFProbe::create());
 }
 public function getProbe()
 {
     try {
         return FFProbe::create();
     } catch (FFMpegExecutableNotFound $e) {
     }
     return null;
 }
 private function initialize()
 {
     $format = $this->ffprobe->format($this->pathfile);
     if (false === $format->has('size') || false === $format->has('duration')) {
         throw new RuntimeException(sprintf('Unable to probe format for %s', $this->pathfile));
     }
     $this->totalSize = $format->get('size') / 1024;
     $this->duration = $format->get('duration');
     $this->initialized = true;
 }
Esempio n. 7
0
 /**
  * @covers FFMpeg\FFMpeg::encode
  * @covers FFMpeg\FFMpeg::encodeVideo
  */
 public function testEncodeX264()
 {
     $dest = __DIR__ . '/../../files/encode_test.mp4';
     $format = new Format\Video\WebM();
     $format->setDimensions(32, 32);
     $this->object->open(__DIR__ . '/../../files/Test.ogv');
     $this->object->encode($format, $dest);
     $this->probe->probeFormat($dest);
     unlink($dest);
 }
Esempio n. 8
0
 public function setUp()
 {
     if (!class_exists('FFMpeg\\FFProbe')) {
         $this->markTestSkipped('FFMpeg\\FFProbe not available.');
     }
     try {
         $this->reader = new FfprobeReader(FFProbe::create());
     } catch (\Exception $e) {
         $this->markTestSkipped('FfprobeReader not available.');
     }
 }
Esempio n. 9
0
 /**
  * Create screenshot from uploaded video
  * @param  \App\Models\Video $video The object we created
  * @return boolean	Always true
  */
 private function capture(\App\Models\Video $video)
 {
     //that's easier
     $video_path = public_path('/videos/' . $video->video);
     //find duration
     $ffprobe = \FFMpeg\FFProbe::create();
     $duration = $ffprobe->format($video_path)->get('duration');
     //take the shot
     $ffmpeg = \FFMpeg\FFMpeg::create();
     $capture = $ffmpeg->open($video_path);
     $capture->frame(\FFMpeg\Coordinate\TimeCode::fromSeconds($duration > 5 ? 5 : (int) ($duration / 2)))->save(public_path('/previews/' . $video->getKey() . '.jpg'));
     return true;
 }
 private function initialize()
 {
     try {
         $format = $this->ffprobe->format($this->pathfile);
     } catch (RuntimeException $e) {
         return;
     }
     if (false === $format->has('size') || false === $format->has('duration')) {
         return;
     }
     $this->totalSize = $format->get('size') / 1024;
     $this->duration = $format->get('duration');
     $this->initialized = true;
 }
Esempio n. 11
0
 protected function __construct()
 {
     $basedir = dirname(dirname(dirname(__DIR__)));
     StitchLib::$log_dir = $basedir . DIRECTORY_SEPARATOR . 'logs';
     StitchLib::$tmp_dir = sys_get_temp_dir();
     if (!is_dir(StitchLib::$log_dir)) {
         mkdir(StitchLib::$log_dir);
     }
     if (!is_dir(StitchLib::$tmp_dir)) {
         mkdir(StitchLib::$tmp_dir, 0777, true);
     }
     $this->logger = new Logger(StitchLib::$log_dir);
     $this->ffprobe = \FFMpeg\FFProbe::create([], $this->logger);
 }
Esempio n. 12
0
 public function setUp()
 {
     parent::setUp();
     $logger = new Logger('Tests');
     $logger->pushHandler(new NullHandler());
     $this->reader = Reader::create($logger);
     $this->writer = Writer::create($logger);
     $file = __DIR__ . '/../../../files/ExifTool.jpg';
     $this->object = new Image(new File($file), $this->reader->reset()->files($file)->first(), $this->writer);
     $logger = new Logger('test');
     $logger->pushHandler(new NullHandler());
     $this->ffprobe = FFProbe::create();
     $this->mediavorus = new MediaVorus($this->reader, $this->writer, $this->ffprobe);
 }
Esempio n. 13
0
 /**
  * Create.
  *
  * This method creates the thumbnail from the video.
  *
  * @param string   $videoFile     Video file to process
  * @param string   $thumbnailFile Output gif
  * @param int|null $count         Number of frames to use
  * @param int|null $interval      The interval beetween the frames of the gif
  * @param int|null $width         Width of the gif
  * @param int|null $height        Height of the gif
  * @param int|null $start         The start of the video part
  * @param int|null $end           The end of the video part
  *
  * @throws VideoException If error during procession or writing.
  */
 public function create($videoFile, $thumbnailFile, $count = null, $interval = null, $width = null, $height = null, $start = null, $end = null)
 {
     $count = $count ?: $this->defaults['count'];
     $interval = $interval ?: $this->defaults['interval'];
     $width = $width ?: $this->defaults['width'];
     $height = $height ?: $this->defaults['height'];
     try {
         $ffmpeg = FFMpeg::create();
         $ffprobe = FFProbe::create();
     } catch (\Exception $e) {
         throw new VideoException('Cannot start FFMpeg or FFProbe', 0, $e);
     }
     try {
         // Determine the duration of the video
         $duration = $ffprobe->format($videoFile)->get('duration');
     } catch (\Exception $e) {
         throw new VideoException(sprintf('Cannot determine the duration of %s', $videoFile), 0, $e);
     }
     // If invalid start or end time, assume it is the start and the end
     // of the video.
     $start = max(0, $start ?: 0);
     $end = min($duration, $end ?: $duration);
     $delay = (double) ($end - $start) / ($count + 1);
     $video = $ffmpeg->open($videoFile);
     $hashDir = $this->tmpDir . '/video-gif/' . md5($videoFile . time());
     if (!file_exists($hashDir)) {
         mkdir($hashDir, 0777, true);
     }
     $pos = $start;
     $frames = array();
     $durations = array();
     // Grab frames
     for ($i = 0; $i < $count; ++$i) {
         $pos += $delay;
         $video->frame(TimeCode::fromSeconds($pos))->save(sprintf($hashDir . '/tmp-frame%03d.jpg', $i));
         Image::open(sprintf($hashDir . '/tmp-frame%03d.jpg', $i))->cropResize($width, $height)->save(sprintf($hashDir . '/frame%03d.jpg', $i));
         $frames[] = sprintf($hashDir . '/frame%03d.jpg', $i);
         $durations[] = $interval;
     }
     $gc = new GifCreator();
     $gc->create($frames, $durations, 0);
     $this->removeDirectory($hashDir);
     if (false === @file_put_contents($thumbnailFile, $gc->getGif())) {
         throw new VideoException(sprintf('Cannot write %s', $thumbnailFile));
     }
 }
Esempio n. 14
0
 /**
  * Get video properties
  *
  * @param $path
  * @return array|null
  * @throws ErrorException
  */
 public static function getProperties($path)
 {
     if (is_file($path)) {
         // init
         $ffprobe = FFProbe::create();
         $streams = $ffprobe->streams($path);
         // extracts streams informations
         // get video data
         $video = $streams->videos()->first();
         // filters video first streams
         $dimensions = $video->getDimensions();
         // get audio data
         $audio = $streams->audios()->first();
         // filters audio first streams
         return ['screen_width' => $dimensions->getWidth(), 'screen_height' => $dimensions->getHeight(), 'video_bitrate' => $video->get('bit_rate'), 'audio_bitrate' => $audio->get('bit_rate')];
     }
     throw new ErrorException('Not found file: ' . $path);
 }
Esempio n. 15
0
 /**
  * Encode to video
  *
  * @param  Video            $format         The output format
  * @param  string           $outputPathfile The pathfile where to write
  * @param  integer          $threads        The number of threads to use
  * @return \FFMpeg\FFMpeg
  * @throws RuntimeException
  */
 protected function encodeVideo(Video $format, $outputPathfile, $threads)
 {
     $cmd_part1 = $this->binary . ' -y -i ' . escapeshellarg($this->pathfile) . ' ' . $format->getExtraParams() . ' ';
     $cmd_part2 = '';
     if ($format instanceof Video\Resizable) {
         if (!$this->prober) {
             throw new LogicException('You must set a valid prober if you use RESIZEMODE_INSET');
         }
         $result = json_decode($this->prober->probeStreams($this->pathfile), true);
         $originalWidth = $originalHeight = null;
         foreach ($result as $stream) {
             foreach ($stream as $name => $value) {
                 if ($name == 'width') {
                     $originalWidth = $value;
                     continue;
                 }
                 if ($name == 'value') {
                     $originalHeight = $value;
                     continue;
                 }
             }
         }
         if ($originalHeight !== null && $originalWidth !== null) {
             $dimensions = $format->getComputedDimensions($originalWidth, $originalHeight);
             $width = $this->getMultiple($dimensions->getWidth(), 16);
             $height = $this->getMultiple($dimensions->getHeight(), 16);
             $cmd_part2 .= ' -s ' . $width . 'x' . $height;
         }
     }
     if ($format instanceof Video\Resamplable) {
         $cmd_part2 .= ' -r ' . $format->getFrameRate();
     }
     if ($format instanceof Video\Transcodable) {
         $cmd_part2 .= ' -vcodec ' . $format->getVideoCodec();
     }
     $cmd_part2 .= ' -b ' . $format->getKiloBitrate() . 'k -g 25 -bf 3' . ' -threads ' . $threads . ' -refs 6 -b_strategy 1 -coder 1 -qmin 10 -qmax 51 ' . ' -sc_threshold 40 -flags +loop -cmp +chroma' . ' -me_range 16 -subq 7 -i_qfactor 0.71 -qcomp 0.6 -qdiff 4 ' . ' -trellis 1 -qscale 1 ' . ' -ab 92k ';
     if ($format instanceof Audio\Transcodable) {
         $cmd_part2 .= '-acodec ' . $format->getAudioCodec();
     }
     $tmpFile = new \SplFileInfo(tempnam(sys_get_temp_dir(), 'temp') . '.' . pathinfo($outputPathfile, PATHINFO_EXTENSION));
     $passes = array();
     $passes[] = $cmd_part1 . ' -pass 1 ' . $cmd_part2 . ' -an ' . escapeshellarg($tmpFile->getPathname());
     $passes[] = $cmd_part1 . ' -pass 2 ' . $cmd_part2 . ' -ac 2 -ar 44100 ' . escapeshellarg($outputPathfile);
     $process = null;
     foreach ($passes as $pass) {
         $this->logger->addInfo(sprintf('FFmpeg executes command %s', $pass));
         $process = new Process($pass);
         try {
             $process->run();
         } catch (\RuntimeException $e) {
             break;
         }
     }
     $this->cleanupTemporaryFile($tmpFile->getPathname());
     $this->cleanupTemporaryFile(getcwd() . '/ffmpeg2pass-0.log');
     $this->cleanupTemporaryFile(getcwd() . '/av2pass-0.log');
     $this->cleanupTemporaryFile(getcwd() . '/ffmpeg2pass-0.log.mbtree');
     if (!$process->isSuccessful()) {
         $this->logger->addInfo(sprintf('FFmpeg command failed'));
         throw new RuntimeException(sprintf('Encoding failed : %s', $process->getErrorOutput()));
     }
     $this->logger->addInfo(sprintf('FFmpeg command successful'));
     return $this;
 }
 private function ingestImageAsset($filepath, $type, $ffprobe_config)
 {
     $msg = "Creating probe, for file: {$filepath}";
     $this->report[] = $msg;
     static::$logger->info($msg);
     try {
         $probe = FFProbe::create($ffprobe_config, static::$logger);
         if (!$probe) {
             throw new \Exception('FFProbe failed to create.');
         } else {
             $msg = "Probe created";
             $this->report[] = $msg;
             static::$logger->info($msg);
         }
     } catch (Exception $e) {
         $msg = "Probe creation failed: " . $e->getMessage();
         $this->report[] = $msg;
         static::$logger->info($msg);
     }
     $assignedProperties = [];
     $msg = "Probing file properties: {$filepath}";
     $this->report[] = $msg;
     static::$logger->info($msg);
     try {
         $props = $probe->format($filepath)->all();
         if ($props) {
             $assignedProperties[] = $this->formatToJsonArray($props);
         }
     } catch (ExecutionFailureException $e) {
         $msg = $e->getMessage();
         static::$logger->addWarning($msg);
         return false;
         // triggers rejection in ingest
     }
     $msg = "Probing exif properties";
     $this->report[] = $msg;
     static::$logger->info($msg);
     $exif = new Exif($filepath);
     $msg = "Encoding derived metadata";
     $this->report[] = $msg;
     static::$logger->info($msg);
     $exif_json = json_encode($exif->toArray(), JSON_UNESCAPED_SLASHES);
     $exif_obj = Util::decode_json($exif_json);
     $msg = "Encoding assignedProperties";
     $this->report[] = $msg;
     static::$logger->info($msg);
     $json_props = implode(",\n", $assignedProperties);
     $data = Util::decode_json($json_props);
     if ($exif_obj) {
         $msg = "Attaching derived exif props";
         $this->report[] = $msg;
         static::$logger->info($msg);
         $data->{'exif'} = $exif_obj;
     }
     $msg = "Returning derived data object";
     $this->report[] = $msg;
     static::$logger->info($msg);
     return $data;
 }
Esempio n. 17
0
 /**
  * Creates a new FFMpeg instance.
  *
  * @param array|ConfigurationInterface $configuration
  * @param LoggerInterface              $logger
  * @param FFProbe                      $probe
  *
  * @return FFMpeg
  */
 public static function create($configuration = array(), LoggerInterface $logger = null, FFProbe $probe = null)
 {
     if (null === $probe) {
         $probe = FFProbe::create($configuration, $logger, null);
     }
     return new static(FFMpegDriver::create($logger, $configuration), $probe);
 }
 /**
  *  Get FFProbe
  */
 private function getFFProbe()
 {
     return $ffmpeg = \FFMpeg\FFProbe::create($this->getFFMpegConfig());
 }
Esempio n. 19
0
 public function getVideoLength($videoPath)
 {
     $ffprobe = \FFMpeg\FFProbe::create();
     return $ffprobe->streams($videoPath)->videos()->first()->get('duration');
 }
Esempio n. 20
0
 /**
  * {@inheritdoc}
  */
 public function read($filename)
 {
     $meta = new ValueBag();
     try {
         $format = $this->ffprobe->format($filename);
         if ($format->has('format_name')) {
             $meta->set('media.format_name', new MetaValue($format->get('format_name')));
         }
         if ($format->has('format_long_name')) {
             $meta->set('media.format_long_name', new MetaValue($format->get('format_long_name')));
         }
         if ($format->has('duration')) {
             $meta->set('media.duration', new MetaValue($format->get('duration')));
         }
         if ($format->has('bit_rate')) {
             $meta->set('media.bit_rate', new MetaValue($format->get('bit_rate')));
         }
         if ($format->has('width')) {
             $meta->set('media.width', new MetaValue($format->get('width')));
         }
         if ($format->has('height')) {
             $meta->set('media.height', new MetaValue($format->get('height')));
         }
         if ($format->has('nb_streams')) {
             $meta->set('media.number_of_streams', new MetaValue($format->get('nb_streams')));
         }
         $streams = $this->ffprobe->streams($filename);
         foreach ($streams as $stream) {
             $index = $stream->get('index');
             $prefix = 'stream_' . $index;
             $type = 'media';
             if ($stream->isVideo()) {
                 $type = 'video';
             } elseif ($stream->isAudio()) {
                 $type = 'audio';
             }
             if ($stream->has('codec_type')) {
                 $meta->set("{$type}.{$prefix}.codec_type", new MetaValue($stream->get('codec_type')));
             }
             if ($stream->has('codec_name')) {
                 $meta->set("{$type}.{$prefix}.codec_name", new MetaValue($stream->get('codec_name')));
             }
             if ($stream->has('codec_long_name')) {
                 $meta->set("{$type}.{$prefix}.codec_long_name", new MetaValue($stream->get('codec_long_name')));
             }
             if ($stream->has('codec_time_base')) {
                 $meta->set("{$type}.{$prefix}.codec_time_base", new MetaValue($stream->get('codec_time_base')));
             }
             if ($stream->has('codec_tag_string')) {
                 $meta->set("{$type}.{$prefix}.codec_tag", new MetaValue($stream->get('codec_tag_string')));
             }
             if ($stream->has('bit_rate')) {
                 $meta->set("{$type}.{$prefix}.bit_rate", new MetaValue($stream->get('bit_rate')));
             }
             if ($stream->has('display_aspect_ration')) {
                 $meta->set("{$type}.{$prefix}.aspect_ratio", new MetaValue($stream->get('display_aspect_ratio')));
             }
             if ($stream->has('avg_frame_rate')) {
                 $meta->set("{$type}.{$prefix}.frame_rate", new MetaValue($stream->get('avg_frame_rate')));
             }
             if ($stream->has('bits_per_sample')) {
                 $meta->set("{$type}.{$prefix}.bits_per_sample", new MetaValue($stream->get('bits_per_sample')));
             }
             if ($stream->has('channels')) {
                 $meta->set("{$type}.{$prefix}.channels", new MetaValue($stream->get('channels')));
             }
         }
     } catch (\Exception $e) {
     }
     return $meta;
 }
Esempio n. 21
0
 /**
  * @param UploadedFile $uploadedFile
  *
  * @return array
  */
 private function getProperties(UploadedFile $uploadedFile)
 {
     $mimeType = $uploadedFile->getMimeType();
     $properties = [];
     try {
         // if the file is a video we add the duration
         if (fnmatch('video/*', $mimeType)) {
             $properties['duration'] = $this->ffprobe->format($uploadedFile->getPathname())->get('duration');
         }
     } catch (ExecutableNotFoundException $e) {
         // Exception is thrown if ffmpeg is not installed -> duration is not set
     }
     return $properties;
 }
Esempio n. 22
0
 public function testProbeOnRemoteFile()
 {
     $ffprobe = FFProbe::create();
     $this->assertGreaterThan(0, count($ffprobe->streams('http://video-js.zencoder.com/oceans-clip.mp4')));
 }
Esempio n. 23
0
 /**
  * @param UploadedFile $uploadedFile
  *
  * @return array
  */
 private function getProperties(UploadedFile $uploadedFile)
 {
     $mimeType = $uploadedFile->getMimeType();
     $properties = [];
     // if the file is a video we add the duration
     if (fnmatch('video/*', $mimeType)) {
         $properties['duration'] = $this->ffprobe->format($uploadedFile->getPathname())->get('duration');
     }
     return $properties;
 }
Esempio n. 24
0
 public function setUp()
 {
     parent::setUp();
     $this->mediaRepository = $this->prophesize(MediaRepositoryInterface::class);
     $this->collectionRepository = $this->prophesize(CollectionRepositoryInterface::class);
     $this->userRepository = $this->prophesize(UserRepositoryInterface::class);
     $this->em = $this->prophesize(EntityManager::class);
     $this->storage = $this->prophesize(StorageInterface::class);
     $this->validator = $this->prophesize(FileValidatorInterface::class);
     $this->formatManager = $this->prophesize(FormatManagerInterface::class);
     $this->tagManager = $this->prophesize(TagManagerInterface::class);
     $this->typeManager = $this->prophesize(TypeManagerInterface::class);
     $this->pathCleaner = $this->prophesize(PathCleanupInterface::class);
     $this->tokenStorage = $this->prophesize(TokenStorageInterface::class);
     $this->securityChecker = $this->prophesize(SecurityCheckerInterface::class);
     $this->ffprobe = $this->prophesize(FFProbe::class);
     $this->mediaManager = new MediaManager($this->mediaRepository->reveal(), $this->collectionRepository->reveal(), $this->userRepository->reveal(), $this->em->reveal(), $this->storage->reveal(), $this->validator->reveal(), $this->formatManager->reveal(), $this->tagManager->reveal(), $this->typeManager->reveal(), $this->pathCleaner->reveal(), $this->tokenStorage->reveal(), $this->securityChecker->reveal(), $this->ffprobe->reveal(), ['view' => 64], '/', 0);
 }
Esempio n. 25
0
 public function __construct($file)
 {
     parent::__construct($file);
     $this->ffprobe = FFProbe::create(['ffmpeg.binaries' => env('FFMPEG'), 'ffprobe.binaries' => env('FFPROBE')]);
     $this->ffmpeg = FFMpeg::create(['ffmpeg.binaries' => env('FFMPEG'), 'ffprobe.binaries' => env('FFPROBE')]);
 }
Esempio n. 26
0
 /**
  * @dataProvider provideCreateOptions
  */
 public function testCreate($logger, $conf, $cache)
 {
     $finder = new ExecutableFinder();
     $found = false;
     foreach (array('avprobe', 'ffprobe') as $name) {
         if (null !== $finder->find($name)) {
             $found = true;
         }
     }
     if (!$found) {
         $this->markTestSkipped("Unable to find avprobe or ffprobe on system");
     }
     $ffprobe = FFProbe::create();
     $this->assertInstanceOf('FFMpeg\\FFprobe', $ffprobe);
     $ffprobe = FFProbe::create($conf, $logger, $cache);
     $this->assertInstanceOf('FFMpeg\\FFprobe', $ffprobe);
     if (null !== $cache) {
         $this->assertSame($cache, $ffprobe->getCache());
     }
     if (null !== $logger) {
         $this->assertSame($logger, $ffprobe->getFFProbeDriver()->getProcessRunner()->getLogger());
     }
     if ($conf instanceof ConfigurationInterface) {
         $this->assertSame($conf, $ffprobe->getFFProbeDriver()->getConfiguration());
     }
 }
Esempio n. 27
0
 public function testProbeOnRemoteFile()
 {
     $ffprobe = FFProbe::create();
     $this->assertGreaterThan(0, count($ffprobe->streams('http://vjs.zencdn.net/v/oceans.mp4')));
 }
 /**
  * Generates sprite and WebVTT for selected video
  *
  * @throws \Exception
  */
 public function generate()
 {
     // create temporay directory
     $tempDir = new Tempdir('sprite');
     $tempDir->addPlugin(new ListFiles());
     // get basic info about video
     $ffprobe = FFProbe::create()->format($this->getSource());
     $duration = floatval($ffprobe->get('duration'));
     // check if sample rate is high enough to reach desired minimum amount of thumbnails
     if ($duration <= $this->getMinThumbs()) {
         // we only have a 1 second resolution, so we can't get lower than 1 obviously
         $this->setRate(1);
     } else {
         if ($duration / $this->getRate() < $this->getMinThumbs()) {
             // sample rate too high, let's adjust rate a little
             $this->setRate(floor($duration / $this->getMinThumbs()));
         }
     }
     // capture images to tempdir
     for ($i = 0; $i <= $duration; $i += $this->getRate()) {
         $cmd = sprintf('ffmpeg -y -ss %d -i %s -frames:v 1 -filter:v scale=%d:-1 %s/%04d.jpg', $i, $this->getSource(), $this->getWidth(), $tempDir->getPath(), floor($i / $this->getRate()));
         $proc = new Process($cmd);
         $proc->setTimeout(null);
         $proc->run();
         if (!$proc->isSuccessful()) {
             throw new \RuntimeException($cmd . ":" . $proc->getErrorOutput());
         }
     }
     // combine all images to one sprite with quadratic tiling
     $gridSize = ceil(sqrt(count($tempDir->listFiles())));
     $firstImage = Image::make(sprintf('%s/0001.jpg', $tempDir->getPath()));
     $spriteFile = sprintf('%s/%s.jpg', $this->getOutputDirectory(), $this->getPrefix());
     $spriteUrl = empty($this->getUrlPrefix()) ? basename($spriteFile) : sprintf('%s/%s', $this->getUrlPrefix(), basename($spriteFile));
     $cmd = sprintf('montage %1$s/*.jpg -tile %2$dx -geometry %3$dx%4$d+0+0 %5$s', $tempDir->getPath(), $gridSize, $firstImage->width(), $firstImage->height(), $spriteFile);
     $proc = new Process($cmd);
     $proc->run();
     if (!$proc->isSuccessful()) {
         throw new RuntimeException($proc->getErrorOutput());
     }
     // create WebVTT output
     $vttFile = sprintf('%s/%s.vtt', $this->getOutputDirectory(), $this->getPrefix());
     $vtt = new WebvttFile();
     for ($i = 0; $i < count($tempDir->listFiles()); $i++) {
         $start = $i * $this->getRate();
         $end = ($i + 1) * $this->getRate();
         $x = $i % $gridSize * $firstImage->width();
         $y = floor($i / $gridSize) * $firstImage->height();
         $vtt->addCue(new WebvttCue($this->secondsToCue($start), $this->secondsToCue($end), sprintf('%s#xywh=%d,%d,%d,%d', $spriteUrl, $x, $y, $firstImage->width(), $firstImage->height())));
     }
     $vtt->build();
     $vtt->save($vttFile);
 }
Esempio n. 29
0
 /**
  * Create MediaVorus
  *
  * @return MediaVorus
  */
 public static function create()
 {
     $logger = new Logger('MediaVorus');
     $logger->pushHandler(new NullHandler());
     return new static(Reader::create($logger), Writer::create($logger), FFProbe::create(array(), $logger));
 }
 public function __construct()
 {
     $this['logger.name'] = 'Media-Alchemyst drivers logger';
     $this['logger.level'] = function (Pimple $container) {
         return Logger::DEBUG;
     };
     $this['logger.handler'] = $this->share(function (Pimple $container) {
         return new NullHandler($container['logger.level']);
     });
     $bridge = class_exists('Symfony\\Bridge\\Monolog\\Logger');
     $this['logger.class'] = $bridge ? 'Symfony\\Bridge\\Monolog\\Logger' : 'Monolog\\Logger';
     $this['logger'] = $this->share(function (Pimple $container) {
         $logger = new $container['logger.class']($container['logger.name']);
         $logger->pushHandler($container['logger.handler']);
         return $logger;
     });
     $this['default.configuration'] = array('ffmpeg.threads' => 4, 'ffmpeg.ffmpeg.timeout' => 3600, 'ffmpeg.ffprobe.timeout' => 60, 'ffmpeg.ffmpeg.binaries' => null, 'ffmpeg.ffprobe.binaries' => null, 'imagine.driver' => null, 'gs.timeout' => 60, 'gs.binaries' => null, 'mp4box.timeout' => 60, 'mp4box.binaries' => null, 'swftools.timeout' => 60, 'swftools.pdf2swf.binaries' => null, 'swftools.swfrender.binaries' => null, 'swftools.swfextract.binaries' => null, 'unoconv.binaries' => null, 'unoconv.timeout' => 60);
     $this['configuration'] = array();
     $this['configuration.merged'] = $this->share(function (Pimple $container) {
         return array_replace($container['default.configuration'], $container['configuration']);
     });
     $this['ffmpeg.ffmpeg'] = $this->share(function (Pimple $container) {
         try {
             return FFMpeg::create(array_filter(array('ffmpeg.threads' => $container['configuration.merged']['ffmpeg.threads'], 'timeout' => $container['configuration.merged']['ffmpeg.ffmpeg.timeout'], 'ffmpeg.binaries' => $container['configuration.merged']['ffmpeg.ffmpeg.binaries'])), $container['logger'], $container['ffmpeg.ffprobe']);
         } catch (FFMpegExecutableNotFound $e) {
             throw new RuntimeException('Unable to create FFMpeg driver', $e->getCode(), $e);
         }
     });
     $this['ffmpeg.ffprobe.cache'] = $this->share(function (Pimple $container) {
         return new ArrayCache();
     });
     $this['ffmpeg.ffprobe'] = $this->share(function (Pimple $container) {
         try {
             return FFProbe::create(array_filter(array('timeout' => $container['configuration.merged']['ffmpeg.ffprobe.timeout'], 'ffprobe.binaries' => $container['configuration.merged']['ffmpeg.ffprobe.binaries'])), $container['logger'], $container['ffmpeg.ffprobe.cache']);
         } catch (FFMpegExecutableNotFound $e) {
             throw new RuntimeException('Unable to create FFProbe driver', $e->getCode(), $e);
         }
     });
     $this['imagine'] = $this->share(function (Pimple $container) {
         $driver = $container['configuration.merged']['imagine.driver'];
         switch (true) {
             case 'imagick' === strtolower($driver):
             case null === $driver && class_exists('Imagick'):
                 $driver = 'Imagine\\Imagick\\Imagine';
                 break;
             case 'gmagick' === strtolower($driver):
             case null === $driver && class_exists('Gmagick'):
                 $driver = 'Imagine\\Gmagick\\Imagine';
                 break;
             case 'gd' === strtolower($driver):
             case null === $driver && extension_loaded('gd'):
                 $driver = 'Imagine\\Gd\\Imagine';
                 break;
         }
         if (false === class_exists($driver) || false === in_array('Imagine\\Image\\ImagineInterface', class_implements($driver))) {
             throw new InvalidArgumentException(sprintf('Invalid Imagine driver %s', $driver));
         }
         return new $driver();
     });
     $this['swftools.driver-container'] = $this->share(function (Pimple $container) {
         return DriverContainer::create(array_filter(array('pdf2swf.binaries' => $container['configuration.merged']['swftools.pdf2swf.binaries'], 'swfrender.binaries' => $container['configuration.merged']['swftools.swfrender.binaries'], 'swfextract.binaries' => $container['configuration.merged']['swftools.swfextract.binaries'], 'timeout' => $container['configuration.merged']['swftools.timeout'])), $container['logger']);
     });
     $this['swftools.flash-file'] = $this->share(function (Pimple $container) {
         return new FlashFile($container['swftools.driver-container']);
     });
     $this['swftools.pdf-file'] = $this->share(function (Pimple $container) {
         return new PDFFile($container['swftools.driver-container']);
     });
     $this['unoconv'] = $this->share(function (Pimple $container) {
         try {
             return Unoconv::create(array_filter(array('unoconv.binaries' => $container['configuration.merged']['unoconv.binaries'], 'timeout' => $container['configuration.merged']['unoconv.timeout'])), $container['logger']);
         } catch (ExecutableNotFoundException $e) {
             throw new RuntimeException('Unable to create Unoconv driver', $e->getCode(), $e);
         }
     });
     $this['exiftool.exiftool'] = $this->share(function (Pimple $container) {
         return new Exiftool($container['logger']);
     });
     $this['exiftool.rdf-parser'] = $this->share(function (Pimple $container) {
         return new RDFParser();
     });
     $this['exiftool.reader'] = $this->share(function (Pimple $container) {
         return new Reader($container['exiftool.exiftool'], $container['exiftool.rdf-parser']);
     });
     $this['exiftool.writer'] = $this->share(function (Pimple $container) {
         return new Writer($container['exiftool.exiftool']);
     });
     $this['exiftool.preview-extractor'] = $this->share(function (Pimple $container) {
         return new PreviewExtractor($container['exiftool.exiftool']);
     });
     $this['ghostscript.transcoder'] = $this->share(function (Pimple $container) {
         try {
             return Transcoder::create(array_filter(array('gs.binaries' => $container['configuration.merged']['gs.binaries'], 'timeout' => $container['configuration.merged']['gs.timeout'])), $container['logger']);
         } catch (ExecutableNotFoundException $e) {
             throw new RuntimeException('Unable to create Unoconv driver', $e->getCode(), $e);
         }
     });
     $this['mp4box'] = $this->share(function (Pimple $container) {
         try {
             return MP4Box::create(array_filter(array('mp4box.binaries' => $container['configuration.merged']['mp4box.binaries'], 'timeout' => $container['configuration.merged']['mp4box.timeout'])));
         } catch (ExecutableNotFoundException $e) {
             throw new RuntimeException('Unable to create Unoconv driver', $e->getCode(), $e);
         }
     });
     $this['mediavorus'] = $this->share(function (Pimple $container) {
         $ffprobe = null;
         try {
             $ffprobe = $container['ffmpeg.ffprobe'];
         } catch (RuntimeException $e) {
         }
         return new MediaVorus($container['exiftool.reader'], $container['exiftool.writer'], $ffprobe);
     });
 }