![]() 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) Alchemy <[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 FFMpeg\Driver\FFMpegDriver; use FFMpeg\Exception\InvalidArgumentException; use FFMpeg\Exception\RuntimeException; use FFMpeg\FFProbe; use FFMpeg\Filters\Waveform\WaveformFilterInterface; use FFMpeg\Filters\Waveform\WaveformFilters; /** * Class Spectrum * Generates an audio spectrum image using FFMPeg's `showspectrumpic` command * @see https://ffmpeg.org/ffmpeg-filters.html#showspectrumpic * @author Marcus Bointon <[email protected]> * @package FFMpeg\Media */ class Spectrum extends Waveform { const DEFAULT_MODE = 'combined'; const DEFAULT_COLOR = 'intensity'; const DEFAULT_SCALE = 'log'; const DEFAULT_FSCALE = 'lin'; const DEFAULT_SATURATION = 1.0; const DEFAULT_WIN_FUNC = 'hann'; const DEFAULT_ORIENTATION = 'vertical'; const DEFAULT_GAIN = 1.0; const DEFAULT_LEGEND = true; const DEFAULT_ROTATION = 0.0; const DEFAULT_START = 0; const DEFAULT_STOP = 0; /** * Whether to generate a `combined` spectrogram for all channels, or a `separate` one for each * @var string */ protected $mode = self::DEFAULT_MODE; /** * The color palette to use, see setColor() for options * @var string */ protected $color = self::DEFAULT_COLOR; /** * The scale to use for color intensity * @var string */ protected $scale = self::DEFAULT_SCALE; /** * The scale to use for the frequency axis * @var string */ protected $fscale = self::DEFAULT_FSCALE; /** * A saturation scaling factor, between -10.0 and 10.0. Negative values invert the color palette * @var float */ protected $saturation = self::DEFAULT_SATURATION; /** * The windowing function to use when calculating the spectrum. See setWinFunc() for options * @var string */ protected $win_func = self::DEFAULT_WIN_FUNC; /** * Frequency axis orientation, `horizontal` or `vertical` * @var string */ protected $orientation = self::DEFAULT_ORIENTATION; /** * Gain for calculating color values * @var float */ protected $gain = self::DEFAULT_GAIN; /** * Whether to display axes and labels * @var bool */ protected $legend = self::DEFAULT_LEGEND; /** * Rotation of colors within the palette, between -1.0 and 1.0 * @var float */ protected $rotation = self::DEFAULT_ROTATION; /** * Starting frequency for the spectrum in Hz. Must be positive and not greater than stop frequency * @var int */ protected $start = self::DEFAULT_START; /** * Ending frequency for the spectrum in Hz. Must be positive and not less than start frequency * @var int */ protected $stop = self::DEFAULT_STOP; /** * Spectrum constructor. * * @param Audio $audio * @param FFMpegDriver $driver * @param FFProbe $ffprobe * @param int $width * @param int $height * @param array $colors Note that this is not used, just here for compatibility with the Waveform parent */ public function __construct( Audio $audio, FFMpegDriver $driver, FFProbe $ffprobe, $width, $height, $colors = array(self::DEFAULT_COLOR) ) { parent::__construct($audio, $driver, $ffprobe, $width, $height); $this->audio = $audio; } /** * Set the rendering mode. * * @param string $mode `combined` to create a single spectrogram for all channels, or `separate` for each channel separately, all within the same image * * @return $this */ public function setMode($mode = 'combined') { static $modes = array( 'combined', 'separate', ); if (! in_array($mode, $modes, true)) { throw new InvalidArgumentException('Unknown mode. Valid values are: ' . implode(', ', $modes)); } $this->mode = $mode; return $this; } /** * Get the current rendering mode. * @return string */ public function getMode() { return $this->mode; } /** * Set the color palette to use. * * @param string $color One of the available preset palette names: `channel`, `intensity`, `moreland`, `nebulae`, `fire`, `fiery`, `fruit`, `cool`, `magma`, `green`, `viridis`, `plasma`, `cividis`, `terrain`, or `random` to have it pick a random one * * @return $this */ public function setColor($color = 'intensity') { static $modes = array( 'channel', 'intensity', 'moreland', 'nebulae', 'fire', 'fiery', 'fruit', 'cool', 'magma', 'green', 'viridis', 'plasma', 'cividis', 'terrain', ); if ($color === 'random') { $this->color = array_rand($modes); return $this; } if (!in_array($color, $modes, true)) { throw new InvalidArgumentException('Unknown color mode. Valid values are: ' . implode(', ', $modes)); } $this->color = $color; return $this; } /** * Get the current color palette. * * @return string */ public function getColor() { return $this->color; } /** * Set the scale to use for color intensity * * @param string $scale One of `lin`, `sqrt`, `log`, `4thrt`, or `5thrt`. * * @return $this */ public function setScale($scale = 'log') { static $scales = array( 'lin', 'sqrt', 'log', '4thrt', '5thrt', ); if (! in_array($scale, $scales, true)) { throw new InvalidArgumentException('Unknown scale. Valid values are: ' . implode(', ', $scales)); } $this->scale = $scale; return $this; } /** * Get the current color intensity scale. * * @return string */ public function getScale() { return $this->scale; } /** * Set the frequency axis scale. * * @param string $fscale One of `lin` or `log`. * * @return $this */ public function setFscale($fscale = 'lin') { static $fscales = array( 'lin', 'log', ); if (! in_array($fscale, $fscales, true)) { throw new InvalidArgumentException('Unknown fscale. Valid values are: ' . implode(', ', $fscales)); } $this->fscale = $fscale; return $this; } /** * Get the current frequency axis scale. * * @return string */ public function getFscale() { return $this->fscale; } /** * Set the color saturation scaling factor. * * @param float $saturation A value between -10.0 and 10.0 to multiply saturation values by. Negative values invert the saturation. * * @return $this */ public function setSaturation($saturation = 1.0) { $saturation = (float)$saturation; if ($saturation < -10.0 || $saturation > 10.0) { throw new InvalidArgumentException('Saturation must be between -10.0 and 10.0.'); } $this->saturation = $saturation; return $this; } /** * Get the current saturation scaling value. * * @return float */ public function getSaturation() { return $this->saturation; } /** * Set the windowing function to use when calculating the spectrum. * * @param string $win_func One of `rect`, `bartlett`, `hann`, `hanning`, `hamming`, `blackman`, `welch`, `flattop`, `bharris`, `bnuttall`, `bhann`, `sine`, `nuttall`, `lanczos`, `gauss`, `tukey`, `dolph`, `cauchy`, `parzen`, `poisson`, or `bohman`. * * @return $this */ public function setWinFunc($win_func = 'hann') { static $win_funcs = array( 'rect', 'bartlett', 'hann', 'hanning', 'hamming', 'blackman', 'welch', 'flattop', 'bharris', 'bnuttall', 'bhann', 'sine', 'nuttall', 'lanczos', 'gauss', 'tukey', 'dolph', 'cauchy', 'parzen', 'poisson', 'bohman', ); if (! in_array($win_func, $win_funcs, true)) { throw new InvalidArgumentException('Unknown win_func. Valid values are: ' . implode(', ', $win_funcs)); } $this->win_func = $win_func; return $this; } /** * Get the current windowing function. * * @return string */ public function getWinFunc() { return $this->win_func; } /** * Set the orientation of the generated spectrum. * * @param string $orientation `vertical` or `horizontal` * * @return $this */ public function setOrientation($orientation = 'vertical') { static $orientations = array( 'vertical', 'horizontal', ); if (! in_array($orientation, $orientations, true)) { throw new InvalidArgumentException( 'Unknown orientation. Valid values are: ' . implode(', ', $orientations) ); } $this->orientation = $orientation; return $this; } /** * Get the current orientation. * * @return string */ public function getOrientation() { return $this->orientation; } /** * Set the gain used for calculating colour values. * * @param float $gain A multiplying factor: Use larger values for files with quieter audio. * * @return $this */ public function setGain($gain = 1.0) { $this->gain = (float)$gain; return $this; } /** * Get the current colour gain factor. * * @return float */ public function getGain() { return $this->gain; } /** * Turn the graph legends (axes and scales) on and off. * * @param bool $legend * * @return $this */ public function setLegend($legend = true) { $this->legend = (bool)$legend; return $this; } /** * Get the current legend state. * * @return bool */ public function getLegend() { return $this->legend; } /** * Set the color rotation value. This rotates the colour palette, not the resulting image. * * @param float $rotation * * @return $this */ public function setRotation($rotation = 0.0) { $rotation = (float)$rotation; if ($rotation < -1.0 || $rotation > 1.0) { throw new InvalidArgumentException('Color rotation must be between -1.0 and 1.0.'); } $this->rotation = $rotation; return $this; } /** * Get the color palette rotation value. * * @return float */ public function getRotation() { return $this->rotation; } /** * Set the starting frequency for the spectrum. * * @param int $start The starting frequency, in Hz. Must be positive and not greater than the stop frequency. * * @return $this */ public function setStart($start = 0) { $start = (int)abs($start); if ($start > $this->stop) { throw new InvalidArgumentException('Start frequency must be lower than stop frequency.'); } $this->start = $start; return $this; } /** * Get the current starting frequency. * * @return int */ public function getStart() { return $this->start; } /** * Set the ending frequency for the spectrum. * * @param int $stop The ending frequency, in Hz. Must be positive and not less than the start frequency. * * @return $this */ public function setStop($stop = 0) { $stop = (int)abs($stop); if ($stop < $this->start) { throw new InvalidArgumentException('Stop frequency must be higher than start frequency.'); } $this->stop = $stop; return $this; } /** * Get the current ending frequency. * * @return int */ public function getStop() { return $this->stop; } /** * Compile options into a parameter string * * @return string */ protected function compileOptions() { $params = array(); $params[] = 's=' . $this->width . 'x' . $this->height; if ($this->mode !== self::DEFAULT_MODE) { $params[] = 'mode=' . $this->mode; } if ($this->color !== self::DEFAULT_COLOR) { $params[] = 'color=' . $this->color; } if ($this->scale !== self::DEFAULT_SCALE) { $params[] = 'scale=' . $this->scale; } if ($this->fscale !== self::DEFAULT_FSCALE) { $params[] = 'fscale=' . $this->fscale; } if ($this->saturation !== self::DEFAULT_SATURATION) { $params[] = 'saturation=' . $this->saturation; } if ($this->win_func !== self::DEFAULT_WIN_FUNC) { $params[] = 'win_func=' . $this->win_func; } if ($this->orientation !== self::DEFAULT_ORIENTATION) { $params[] = 'orientation=' . $this->orientation; } if ($this->gain !== self::DEFAULT_GAIN) { $params[] = 'gain=' . $this->gain; } if ($this->legend !== self::DEFAULT_LEGEND) { $params[] = 'legend=' . ($this->legend ? '1' : '0'); } if ($this->rotation !== self::DEFAULT_ROTATION) { $params[] = 'rotation=' . $this->rotation; } if ($this->start !== self::DEFAULT_START) { $params[] = 'start=' . $this->start; } if ($this->stop !== self::DEFAULT_STOP) { $params[] = 'stop=' . $this->stop; } return implode(':', $params); } /** * Generates and saves the spectrum in the given filename. * * @param string $pathfile * * @return Spectrum * * @throws RuntimeException */ public function save($pathfile) { /** * might be optimized with http://ffmpeg.org/trac/ffmpeg/wiki/Seeking%20with%20FFmpeg * @see http://ffmpeg.org/ffmpeg.html#Main-options */ $commands = array( '-y', //Overwrite output files '-i', //Specify input file $this->pathfile, '-filter_complex', //Say we want a complex filter 'showspectrumpic=' . $this->compileOptions(), //Specify the filter and its params '-frames:v', //Stop writing output... 1 // after 1 "frame" ); foreach ($this->filters as $filter) { $commands = array_merge($commands, $filter->apply($this)); } $commands = array_merge($commands, array($pathfile)); try { $this->driver->command($commands); } catch (ExecutionFailureException $e) { $this->cleanupTemporaryFile($pathfile); throw new RuntimeException('Unable to save spectrum', $e->getCode(), $e); } return $this; } }