![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/rentpix.corals.io/vendor/php-ffmpeg/php-ffmpeg/src/FFMpeg/Media/ |
<?php /* * This file is part of PHP-FFmpeg. * * (c) Strime <[email protected]> * * 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 Alchemy\BinaryDriver\Exception\InvalidArgumentException; use FFMpeg\Driver\FFMpegDriver; use FFMpeg\Exception\RuntimeException; use FFMpeg\FFProbe; use FFMpeg\Filters\Audio\SimpleFilter; use FFMpeg\Filters\Concat\ConcatFilterInterface; use FFMpeg\Filters\Concat\ConcatFilters; use FFMpeg\Format\AudioInterface; use FFMpeg\Format\FormatInterface; use FFMpeg\Format\VideoInterface; use Spatie\TemporaryDirectory\TemporaryDirectory; class Concat extends AbstractMediaType { /** @var array */ private $sources; public function __construct($sources, FFMpegDriver $driver, FFProbe $ffprobe) { parent::__construct($sources, $driver, $ffprobe); $this->sources = $sources; } /** * Returns the path to the sources. * * @return string */ public function getSources() { return $this->sources; } /** * {@inheritdoc} * * @return ConcatFilters */ public function filters() { return new ConcatFilters($this); } /** * {@inheritdoc} * * @return Concat */ public function addFilter(ConcatFilterInterface $filter) { $this->filters->add($filter); return $this; } /** * Saves the concatenated video in the given array, considering that the sources videos are all encoded with the same codec. * * @param string $outputPathfile * @param bool $streamCopy * * @return Concat * * @throws RuntimeException */ public function saveFromSameCodecs($outputPathfile, $streamCopy = true) { /** * @see https://ffmpeg.org/ffmpeg-formats.html#concat * @see https://trac.ffmpeg.org/wiki/Concatenate */ // Create the file which will contain the list of videos $fs = $this->getTemporaryDirectory()->create(); $sourcesFile = $fs->path('ffmpeg.concat'); // Set the content of this file $fileStream = @fopen($sourcesFile, 'w'); if (false === $fileStream) { throw new RuntimeException('Cannot open the temporary file.'); } $count_videos = 0; if (is_array($this->sources) && (count($this->sources) > 0)) { foreach ($this->sources as $videoPath) { $line = ''; if (0 != $count_videos) { $line .= "\n"; } $line .= 'file '.addcslashes($videoPath, '\'"\\\0 '); fwrite($fileStream, $line); ++$count_videos; } } else { throw new InvalidArgumentException('The list of videos is not a valid array.'); } fclose($fileStream); $commands = [ '-f', 'concat', '-safe', '0', '-i', $sourcesFile, ]; // Check if stream copy is activated if (true === $streamCopy) { $commands[] = '-c'; $commands[] = 'copy'; } // If not, we can apply filters else { foreach ($this->filters as $filter) { $commands = array_merge($commands, $filter->apply($this)); } } // Set the output file in the command $commands = array_merge($commands, [$outputPathfile]); // Execute the command try { $this->driver->command($commands); } catch (ExecutionFailureException $e) { $this->cleanupTemporaryFile($outputPathfile); // TODO@v1: paste this line into an `finally` block. $this->cleanupTemporaryFile($sourcesFile); throw new RuntimeException('Unable to save concatenated video', $e->getCode(), $e); } $this->cleanupTemporaryFile($sourcesFile); return $this; } /** * Saves the concatenated video in the given filename, considering that the sources videos are all encoded with the same codec. * * @param string $outputPathfile * * @return Concat */ public function saveFromDifferentCodecs(FormatInterface $format, $outputPathfile) { /* * @see https://ffmpeg.org/ffmpeg-formats.html#concat * @see https://trac.ffmpeg.org/wiki/Concatenate */ // Check the validity of the parameter if (!is_array($this->sources) || (0 == count($this->sources))) { throw new InvalidArgumentException('The list of videos is not a valid array.'); } // Create the commands variable $commands = []; // Prepare the parameters $nbSources = 0; $files = []; // For each source, check if this is a legit file // and prepare the parameters foreach ($this->sources as $videoPath) { $files[] = '-i'; $files[] = $videoPath; ++$nbSources; } $commands = array_merge($commands, $files); // Set the parameters of the request $commands[] = '-filter_complex'; $complex_filter = ''; for ($i = 0; $i < $nbSources; ++$i) { $complex_filter .= '['.$i.':v:0] ['.$i.':a:0] '; } $complex_filter .= 'concat=n='.$nbSources.':v=1:a=1 [v] [a]'; $commands[] = $complex_filter; $commands[] = '-map'; $commands[] = '[v]'; $commands[] = '-map'; $commands[] = '[a]'; // Prepare the filters $filters = clone $this->filters; $filters->add(new SimpleFilter($format->getExtraParams(), 10)); if ($this->driver->getConfiguration()->has('ffmpeg.threads')) { $filters->add(new SimpleFilter(['-threads', $this->driver->getConfiguration()->get('ffmpeg.threads')])); } if ($format instanceof VideoInterface) { if (null !== $format->getVideoCodec()) { $filters->add(new SimpleFilter(['-vcodec', $format->getVideoCodec()])); } } if ($format instanceof AudioInterface) { if (null !== $format->getAudioCodec()) { $filters->add(new SimpleFilter(['-acodec', $format->getAudioCodec()])); } } // Add the filters foreach ($this->filters as $filter) { $commands = array_merge($commands, $filter->apply($this)); } if ($format instanceof AudioInterface) { if (null !== $format->getAudioKiloBitrate()) { $commands[] = '-b:a'; $commands[] = $format->getAudioKiloBitrate().'k'; } if (null !== $format->getAudioChannels()) { $commands[] = '-ac'; $commands[] = $format->getAudioChannels(); } } // If the user passed some additional parameters if ($format instanceof VideoInterface) { if (null !== $format->getAdditionalParameters()) { foreach ($format->getAdditionalParameters() as $additionalParameter) { $commands[] = $additionalParameter; } } } // Set the output file in the command $commands[] = $outputPathfile; $failure = null; try { $this->driver->command($commands); } catch (ExecutionFailureException $e) { throw new RuntimeException('Encoding failed', $e->getCode(), $e); } return $this; } }