Merge pull request #253 from Romain/waveform

Implementation of the Waveform filter
This commit is contained in:
Romain Neutron 2016-12-15 15:45:12 +01:00 committed by GitHub
commit 85ab770aa9
14 changed files with 1152 additions and 6 deletions

View file

@ -136,7 +136,7 @@ below for more informations.
You can extract a frame at any timecode using the `FFMpeg\Media\Video::frame`
method.
This code return a `FFMpeg\Media\Frame` instance corresponding to the second 42.
This code returns a `FFMpeg\Media\Frame` instance corresponding to the second 42.
You can pass any `FFMpeg\Coordinate\TimeCode` as argument, see dedicated
documentation below for more information.
@ -145,6 +145,42 @@ $frame = $video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(42));
$frame->save('image.jpg');
```
##### Generate a waveform
You can generate a waveform of an audio file using the `FFMpeg\Media\Audio::waveform`
method.
This code returns a `FFMpeg\Media\Waveform` instance.
You can optionally pass dimensions as arguments, see dedicated
documentation below for more information.
The ouput file MUST use the PNG extension.
```php
$waveform = $audio->waveform(640, 120);
$waveform->save('waveform.png');
```
If you want to get a waveform from a video, convert it in an audio file first.
```php
// Open your video file
$video = $ffmpeg->open( 'video.mp4' );
// Set an audio format
$audio_format = new FFMpeg\Format\Audio\Mp3();
// Extract the audio into a new file
$video->save('audio.mp3');
// Set the audio file
$audio = $ffmpeg->open( 'audio.mp3' );
// Create the waveform
$waveform = $audio->waveform();
$waveform->save( 'waveform.png' );
```
##### Filters
You can apply filters on `FFMpeg\Media\Video` with the `FFMpeg\Media\Video::addFilter`

View file

@ -119,7 +119,17 @@
</tr>
<tr>
<td class="type">
string
integer
</td>
<td class="last">
<a href="#method_setPasses">setPasses</a>(integer $passes)
<p>Sets the number of passes.</p>
</td>
<td></td>
</tr>
<tr>
<td class="type">
integer
</td>
<td class="last">
<a href="#method_getPasses">getPasses</a>()
@ -499,12 +509,37 @@
</div>
</div>
<h3 id="method_setPasses">
<div class="location">in <a href="../../../FFMpeg/Format/Video/X264.html#method_setPasses"><abbr title="FFMpeg\Format\Video\X264">X264</abbr></a> at line 68</div>
<code> public integer
<strong>setPasses</strong>(integer $passes)</code>
</h3>
<div class="details">
<p>Sets the number of passes.</p>
<p>
</p>
<div class="tags">
<h4>Parameters</h4>
<table>
<tr>
<td>integer</td>
<td>$passes</td>
</tr>
</table>
</div>
</div>
<h3 id="method_getPasses">
<div class="location">at line 68</div>
<code> public string
<div class="location">in <a href="../../../FFMpeg/Format/Video/X264.html#method_getPasses"><abbr title="FFMpeg\Format\Video\X264">X264</abbr></a> at line 79</div>
<code> public integer
<strong>getPasses</strong>()</code>
</h3>
<div class="details">
@ -517,7 +552,7 @@
<table>
<tr>
<td>string</td>
<td>integer</td>
<td>
</td>
</tr>

View file

@ -171,6 +171,16 @@
<p>Exports the audio in the desired format, applies registered filters.</p>
</td>
<td></td>
</tr>
<tr>
<td class="type">
<a href="../../FFMpeg/Media/Waveform.html"><abbr title="FFMpeg\Media\Audio">Audio</abbr></a>
</td>
<td class="last">
<a href="#method_waveform">waveform</a>(integer $width, integer $height)
<p>Generates an image file representing the waveform of the audio file.</p>
</td>
<td></td>
</tr>
</table>
@ -609,6 +619,59 @@
</div>
</div>
<h3 id="method_waveform">
<div class="location">at line 113</div>
<code> public <a href="../../FFMpeg/Media/Waveform.html"><abbr title="FFMpeg\Media\Audio">Audio</abbr></a>
<strong>save</strong>(<a href="../../FFMpeg/Format/FormatInterface.html"><abbr title="FFMpeg\Format\FormatInterface">FormatInterface</abbr></a> $format, string $outputPathfile)</code>
</h3>
<div class="details">
<p>Exports the audio in the desired format, applies registered filters.</p>
<p>
</p>
<div class="tags">
<h4>Parameters</h4>
<table>
<tr>
<td><a href="../../FFMpeg/Format/FormatInterface.html"><abbr title="FFMpeg\Format\FormatInterface">FormatInterface</abbr></a></td>
<td>$format</td>
<td>
</td>
</tr>
<tr>
<td>string</td>
<td>$outputPathfile</td>
<td>
</td>
</tr>
</table>
<h4>Return Value</h4>
<table>
<tr>
<td><a href="../../FFMpeg/Media/Audio.html"><abbr title="FFMpeg\Media\Audio">Audio</abbr></a></td>
<td>
</td>
</tr>
</table>
<h4>Exceptions</h4>
<table>
<tr>
<td><a href="http://php.net/RuntimeException"><abbr title="RuntimeException">RuntimeException</abbr></a></td>
<td>
</td>
</tr>
</table>
</div>
</div>
</div>
<div id="footer">

View file

@ -0,0 +1,621 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="robots" content="index, follow, all" />
<title>FFMpeg\Media\Frame | PHP-FFMpeg API</title>
<link rel="stylesheet" type="text/css" href="../../stylesheet.css">
</head>
<body id="class">
<div class="header">
<ul>
<li><a href="../../classes.html">Classes</a></li>
<li><a href="../../namespaces.html">Namespaces</a></li>
<li><a href="../../interfaces.html">Interfaces</a></li>
<li><a href="../../traits.html">Traits</a></li>
<li><a href="../../doc-index.html">Index</a></li>
</ul>
<div id="title">PHP-FFMpeg API</div>
<div class="type">Class</div>
<h1><a href="../../FFMpeg/Media.html">FFMpeg\Media</a>\Frame</h1>
</div>
<div class="content">
<p> class
<strong>Frame</strong> extends <a href="../../FFMpeg/Media/AbstractMediaType.html"><abbr title="FFMpeg\Media\AbstractMediaType">AbstractMediaType</abbr></a></p>
<h2>Methods</h2>
<table>
<tr>
<td class="type">
</td>
<td class="last">
<a href="#method___construct">__construct</a>(<a href="../../FFMpeg/Media/Video.html"><abbr title="FFMpeg\Media\Video">Video</abbr></a> $video, <a href="../../FFMpeg/Driver/FFMpegDriver.html"><abbr title="FFMpeg\Driver\FFMpegDriver">FFMpegDriver</abbr></a> $driver, <a href="../../FFMpeg/FFProbe.html"><abbr title="FFMpeg\FFProbe">FFProbe</abbr></a> $ffprobe, <a href="../../FFMpeg/Coordinate/TimeCode.html"><abbr title="FFMpeg\Coordinate\TimeCode">TimeCode</abbr></a> $timecode)
<p>
</p>
</td>
<td></td>
</tr>
<tr>
<td class="type">
<a href="../../FFMpeg/Driver/FFMpegDriver.html"><abbr title="FFMpeg\Driver\FFMpegDriver">FFMpegDriver</abbr></a>
</td>
<td class="last">
<a href="#method_getFFMpegDriver">getFFMpegDriver</a>()
<p>
</p>
</td>
<td><small>from&nbsp;<a href="../../FFMpeg/Media/AbstractMediaType.html#method_getFFMpegDriver"><abbr title="FFMpeg\Media\AbstractMediaType">AbstractMediaType</abbr></a></small></td>
</tr>
<tr>
<td class="type">
<a href="../../FFMpeg/Media/MediaTypeInterface.html"><abbr title="FFMpeg\Media\MediaTypeInterface">MediaTypeInterface</abbr></a>
</td>
<td class="last">
<a href="#method_setFFMpegDriver">setFFMpegDriver</a>(<a href="../../FFMpeg/Driver/FFMpegDriver.html"><abbr title="FFMpeg\Driver\FFMpegDriver">FFMpegDriver</abbr></a> $driver)
<p>
</p>
</td>
<td><small>from&nbsp;<a href="../../FFMpeg/Media/AbstractMediaType.html#method_setFFMpegDriver"><abbr title="FFMpeg\Media\AbstractMediaType">AbstractMediaType</abbr></a></small></td>
</tr>
<tr>
<td class="type">
<a href="../../FFMpeg/FFProbe.html"><abbr title="FFMpeg\FFProbe">FFProbe</abbr></a>
</td>
<td class="last">
<a href="#method_getFFProbe">getFFProbe</a>()
<p>
</p>
</td>
<td><small>from&nbsp;<a href="../../FFMpeg/Media/AbstractMediaType.html#method_getFFProbe"><abbr title="FFMpeg\Media\AbstractMediaType">AbstractMediaType</abbr></a></small></td>
</tr>
<tr>
<td class="type">
<a href="../../FFMpeg/Media/MediaTypeInterface.html"><abbr title="FFMpeg\Media\MediaTypeInterface">MediaTypeInterface</abbr></a>
</td>
<td class="last">
<a href="#method_setFFProbe">setFFProbe</a>(<a href="../../FFMpeg/FFProbe.html"><abbr title="FFMpeg\FFProbe">FFProbe</abbr></a> $ffprobe)
<p>
</p>
</td>
<td><small>from&nbsp;<a href="../../FFMpeg/Media/AbstractMediaType.html#method_setFFProbe"><abbr title="FFMpeg\Media\AbstractMediaType">AbstractMediaType</abbr></a></small></td>
</tr>
<tr>
<td class="type">
string
</td>
<td class="last">
<a href="#method_getPathfile">getPathfile</a>()
<p>
</p>
</td>
<td><small>from&nbsp;<a href="../../FFMpeg/Media/AbstractMediaType.html#method_getPathfile"><abbr title="FFMpeg\Media\AbstractMediaType">AbstractMediaType</abbr></a></small></td>
</tr>
<tr>
<td class="type">
<a href="../../FFMpeg/Media/MediaTypeInterface.html"><abbr title="FFMpeg\Media\MediaTypeInterface">MediaTypeInterface</abbr></a>
</td>
<td class="last">
<a href="#method_setFiltersCollection">setFiltersCollection</a>(<a href="../../FFMpeg/Filters/FiltersCollection.html"><abbr title="FFMpeg\Filters\FiltersCollection">FiltersCollection</abbr></a> $filters)
<p>
</p>
</td>
<td><small>from&nbsp;<a href="../../FFMpeg/Media/AbstractMediaType.html#method_setFiltersCollection"><abbr title="FFMpeg\Media\AbstractMediaType">AbstractMediaType</abbr></a></small></td>
</tr>
<tr>
<td class="type">
<a href="../../FFMpeg/Media/MediaTypeInterface.html"><abbr title="FFMpeg\Media\MediaTypeInterface">MediaTypeInterface</abbr></a>
</td>
<td class="last">
<a href="#method_getFiltersCollection">getFiltersCollection</a>()
<p>
</p>
</td>
<td><small>from&nbsp;<a href="../../FFMpeg/Media/AbstractMediaType.html#method_getFiltersCollection"><abbr title="FFMpeg\Media\AbstractMediaType">AbstractMediaType</abbr></a></small></td>
</tr>
<tr>
<td class="type">
<a href="../../FFMpeg/Media/Video.html"><abbr title="FFMpeg\Media\Video">Video</abbr></a>
</td>
<td class="last">
<a href="#method_getVideo">getVideo</a>()
<p>Returns the video related to the frame.</p>
</td>
<td></td>
</tr>
<tr>
<td class="type">
<a href="../../FFMpeg/Filters/Frame/FrameFilters.html"><abbr title="FFMpeg\Filters\Frame\FrameFilters">FrameFilters</abbr></a>
</td>
<td class="last">
<a href="#method_filters">filters</a>()
<p>Returns the available filters.</p>
</td>
<td></td>
</tr>
<tr>
<td class="type">
<a href="../../FFMpeg/Media/Frame.html"><abbr title="FFMpeg\Media\Frame">Frame</abbr></a>
</td>
<td class="last">
<a href="#method_addFilter">addFilter</a>(<a href="../../FFMpeg/Filters/Frame/FrameFilterInterface.html"><abbr title="FFMpeg\Filters\Frame\FrameFilterInterface">FrameFilterInterface</abbr></a> $filter)
<p>{@inheritdoc}</p>
</td>
<td></td>
</tr>
<tr>
<td class="type">
<a href="../../FFMpeg/Coordinate/TimeCode.html"><abbr title="FFMpeg\Coordinate\TimeCode">TimeCode</abbr></a>
</td>
<td class="last">
<a href="#method_getTimeCode">getTimeCode</a>()
<p>
</p>
</td>
<td></td>
</tr>
<tr>
<td class="type">
<a href="../../FFMpeg/Media/Frame.html"><abbr title="FFMpeg\Media\Frame">Frame</abbr></a>
</td>
<td class="last">
<a href="#method_save">save</a>(string $pathfile, Boolean $accurate = false)
<p>Saves the frame in the given filename.</p>
</td>
<td></td>
</tr>
</table>
<h2>Details</h2>
<h3 id="method___construct">
<div class="location">at line 29</div>
<code> public
<strong>__construct</strong>(<a href="../../FFMpeg/Media/Video.html"><abbr title="FFMpeg\Media\Video">Video</abbr></a> $video, <a href="../../FFMpeg/Driver/FFMpegDriver.html"><abbr title="FFMpeg\Driver\FFMpegDriver">FFMpegDriver</abbr></a> $driver, <a href="../../FFMpeg/FFProbe.html"><abbr title="FFMpeg\FFProbe">FFProbe</abbr></a> $ffprobe, <a href="../../FFMpeg/Coordinate/TimeCode.html"><abbr title="FFMpeg\Coordinate\TimeCode">TimeCode</abbr></a> $timecode)</code>
</h3>
<div class="details">
<p>
</p>
<p>
</p>
<div class="tags">
<h4>Parameters</h4>
<table>
<tr>
<td><a href="../../FFMpeg/Media/Video.html"><abbr title="FFMpeg\Media\Video">Video</abbr></a></td>
<td>$video</td>
<td>
</td>
</tr>
<tr>
<td><a href="../../FFMpeg/Driver/FFMpegDriver.html"><abbr title="FFMpeg\Driver\FFMpegDriver">FFMpegDriver</abbr></a></td>
<td>$driver</td>
<td>
</td>
</tr>
<tr>
<td><a href="../../FFMpeg/FFProbe.html"><abbr title="FFMpeg\FFProbe">FFProbe</abbr></a></td>
<td>$ffprobe</td>
<td>
</td>
</tr>
<tr>
<td><a href="../../FFMpeg/Coordinate/TimeCode.html"><abbr title="FFMpeg\Coordinate\TimeCode">TimeCode</abbr></a></td>
<td>$timecode</td>
<td>
</td>
</tr>
</table>
</div>
</div>
<h3 id="method_getFFMpegDriver">
<div class="location">in <a href="../../FFMpeg/Media/AbstractMediaType.html#method_getFFMpegDriver"><abbr title="FFMpeg\Media\AbstractMediaType">AbstractMediaType</abbr></a> at line 40</div>
<code> public <a href="../../FFMpeg/Driver/FFMpegDriver.html"><abbr title="FFMpeg\Driver\FFMpegDriver">FFMpegDriver</abbr></a>
<strong>getFFMpegDriver</strong>()</code>
</h3>
<div class="details">
<p>
</p>
<p>
</p>
<div class="tags">
<h4>Return Value</h4>
<table>
<tr>
<td><a href="../../FFMpeg/Driver/FFMpegDriver.html"><abbr title="FFMpeg\Driver\FFMpegDriver">FFMpegDriver</abbr></a></td>
<td>
</td>
</tr>
</table>
</div>
</div>
<h3 id="method_setFFMpegDriver">
<div class="location">in <a href="../../FFMpeg/Media/AbstractMediaType.html#method_setFFMpegDriver"><abbr title="FFMpeg\Media\AbstractMediaType">AbstractMediaType</abbr></a> at line 50</div>
<code> public <a href="../../FFMpeg/Media/MediaTypeInterface.html"><abbr title="FFMpeg\Media\MediaTypeInterface">MediaTypeInterface</abbr></a>
<strong>setFFMpegDriver</strong>(<a href="../../FFMpeg/Driver/FFMpegDriver.html"><abbr title="FFMpeg\Driver\FFMpegDriver">FFMpegDriver</abbr></a> $driver)</code>
</h3>
<div class="details">
<p>
</p>
<p>
</p>
<div class="tags">
<h4>Parameters</h4>
<table>
<tr>
<td><a href="../../FFMpeg/Driver/FFMpegDriver.html"><abbr title="FFMpeg\Driver\FFMpegDriver">FFMpegDriver</abbr></a></td>
<td>$driver</td>
<td>
</td>
</tr>
</table>
<h4>Return Value</h4>
<table>
<tr>
<td><a href="../../FFMpeg/Media/MediaTypeInterface.html"><abbr title="FFMpeg\Media\MediaTypeInterface">MediaTypeInterface</abbr></a></td>
<td>
</td>
</tr>
</table>
</div>
</div>
<h3 id="method_getFFProbe">
<div class="location">in <a href="../../FFMpeg/Media/AbstractMediaType.html#method_getFFProbe"><abbr title="FFMpeg\Media\AbstractMediaType">AbstractMediaType</abbr></a> at line 60</div>
<code> public <a href="../../FFMpeg/FFProbe.html"><abbr title="FFMpeg\FFProbe">FFProbe</abbr></a>
<strong>getFFProbe</strong>()</code>
</h3>
<div class="details">
<p>
</p>
<p>
</p>
<div class="tags">
<h4>Return Value</h4>
<table>
<tr>
<td><a href="../../FFMpeg/FFProbe.html"><abbr title="FFMpeg\FFProbe">FFProbe</abbr></a></td>
<td>
</td>
</tr>
</table>
</div>
</div>
<h3 id="method_setFFProbe">
<div class="location">in <a href="../../FFMpeg/Media/AbstractMediaType.html#method_setFFProbe"><abbr title="FFMpeg\Media\AbstractMediaType">AbstractMediaType</abbr></a> at line 70</div>
<code> public <a href="../../FFMpeg/Media/MediaTypeInterface.html"><abbr title="FFMpeg\Media\MediaTypeInterface">MediaTypeInterface</abbr></a>
<strong>setFFProbe</strong>(<a href="../../FFMpeg/FFProbe.html"><abbr title="FFMpeg\FFProbe">FFProbe</abbr></a> $ffprobe)</code>
</h3>
<div class="details">
<p>
</p>
<p>
</p>
<div class="tags">
<h4>Parameters</h4>
<table>
<tr>
<td><a href="../../FFMpeg/FFProbe.html"><abbr title="FFMpeg\FFProbe">FFProbe</abbr></a></td>
<td>$ffprobe</td>
<td>
</td>
</tr>
</table>
<h4>Return Value</h4>
<table>
<tr>
<td><a href="../../FFMpeg/Media/MediaTypeInterface.html"><abbr title="FFMpeg\Media\MediaTypeInterface">MediaTypeInterface</abbr></a></td>
<td>
</td>
</tr>
</table>
</div>
</div>
<h3 id="method_getPathfile">
<div class="location">in <a href="../../FFMpeg/Media/AbstractMediaType.html#method_getPathfile"><abbr title="FFMpeg\Media\AbstractMediaType">AbstractMediaType</abbr></a> at line 80</div>
<code> public string
<strong>getPathfile</strong>()</code>
</h3>
<div class="details">
<p>
</p>
<p>
</p>
<div class="tags">
<h4>Return Value</h4>
<table>
<tr>
<td>string</td>
<td>
</td>
</tr>
</table>
</div>
</div>
<h3 id="method_setFiltersCollection">
<div class="location">in <a href="../../FFMpeg/Media/AbstractMediaType.html#method_setFiltersCollection"><abbr title="FFMpeg\Media\AbstractMediaType">AbstractMediaType</abbr></a> at line 90</div>
<code> public <a href="../../FFMpeg/Media/MediaTypeInterface.html"><abbr title="FFMpeg\Media\MediaTypeInterface">MediaTypeInterface</abbr></a>
<strong>setFiltersCollection</strong>(<a href="../../FFMpeg/Filters/FiltersCollection.html"><abbr title="FFMpeg\Filters\FiltersCollection">FiltersCollection</abbr></a> $filters)</code>
</h3>
<div class="details">
<p>
</p>
<p>
</p>
<div class="tags">
<h4>Parameters</h4>
<table>
<tr>
<td><a href="../../FFMpeg/Filters/FiltersCollection.html"><abbr title="FFMpeg\Filters\FiltersCollection">FiltersCollection</abbr></a></td>
<td>$filters</td>
<td>
</td>
</tr>
</table>
<h4>Return Value</h4>
<table>
<tr>
<td><a href="../../FFMpeg/Media/MediaTypeInterface.html"><abbr title="FFMpeg\Media\MediaTypeInterface">MediaTypeInterface</abbr></a></td>
<td>
</td>
</tr>
</table>
</div>
</div>
<h3 id="method_getFiltersCollection">
<div class="location">in <a href="../../FFMpeg/Media/AbstractMediaType.html#method_getFiltersCollection"><abbr title="FFMpeg\Media\AbstractMediaType">AbstractMediaType</abbr></a> at line 100</div>
<code> public <a href="../../FFMpeg/Media/MediaTypeInterface.html"><abbr title="FFMpeg\Media\MediaTypeInterface">MediaTypeInterface</abbr></a>
<strong>getFiltersCollection</strong>()</code>
</h3>
<div class="details">
<p>
</p>
<p>
</p>
<div class="tags">
<h4>Return Value</h4>
<table>
<tr>
<td><a href="../../FFMpeg/Media/MediaTypeInterface.html"><abbr title="FFMpeg\Media\MediaTypeInterface">MediaTypeInterface</abbr></a></td>
<td>
</td>
</tr>
</table>
</div>
</div>
<h3 id="method_getVideo">
<div class="location">at line 41</div>
<code> public <a href="../../FFMpeg/Media/Video.html"><abbr title="FFMpeg\Media\Video">Video</abbr></a>
<strong>getVideo</strong>()</code>
</h3>
<div class="details">
<p>Returns the video related to the frame.</p>
<p>
</p>
<div class="tags">
<h4>Return Value</h4>
<table>
<tr>
<td><a href="../../FFMpeg/Media/Video.html"><abbr title="FFMpeg\Media\Video">Video</abbr></a></td>
<td>
</td>
</tr>
</table>
</div>
</div>
<h3 id="method_filters">
<div class="location">at line 51</div>
<code> public <a href="../../FFMpeg/Filters/Frame/FrameFilters.html"><abbr title="FFMpeg\Filters\Frame\FrameFilters">FrameFilters</abbr></a>
<strong>filters</strong>()</code>
</h3>
<div class="details">
<p>Returns the available filters.</p>
<p>
</p>
<div class="tags">
<h4>Return Value</h4>
<table>
<tr>
<td><a href="../../FFMpeg/Filters/Frame/FrameFilters.html"><abbr title="FFMpeg\Filters\Frame\FrameFilters">FrameFilters</abbr></a></td>
<td>
</td>
</tr>
</table>
</div>
</div>
<h3 id="method_addFilter">
<div class="location">at line 61</div>
<code> public <a href="../../FFMpeg/Media/Frame.html"><abbr title="FFMpeg\Media\Frame">Frame</abbr></a>
<strong>addFilter</strong>(<a href="../../FFMpeg/Filters/Frame/FrameFilterInterface.html"><abbr title="FFMpeg\Filters\Frame\FrameFilterInterface">FrameFilterInterface</abbr></a> $filter)</code>
</h3>
<div class="details">
<p>{@inheritdoc}</p>
<p>
</p>
<div class="tags">
<h4>Parameters</h4>
<table>
<tr>
<td><a href="../../FFMpeg/Filters/Frame/FrameFilterInterface.html"><abbr title="FFMpeg\Filters\Frame\FrameFilterInterface">FrameFilterInterface</abbr></a></td>
<td>$filter</td>
<td>
</td>
</tr>
</table>
<h4>Return Value</h4>
<table>
<tr>
<td><a href="../../FFMpeg/Media/Frame.html"><abbr title="FFMpeg\Media\Frame">Frame</abbr></a></td>
<td>
</td>
</tr>
</table>
</div>
</div>
<h3 id="method_getTimeCode">
<div class="location">at line 71</div>
<code> public <a href="../../FFMpeg/Coordinate/TimeCode.html"><abbr title="FFMpeg\Coordinate\TimeCode">TimeCode</abbr></a>
<strong>getTimeCode</strong>()</code>
</h3>
<div class="details">
<p>
</p>
<p>
</p>
<div class="tags">
<h4>Return Value</h4>
<table>
<tr>
<td><a href="../../FFMpeg/Coordinate/TimeCode.html"><abbr title="FFMpeg\Coordinate\TimeCode">TimeCode</abbr></a></td>
<td>
</td>
</tr>
</table>
</div>
</div>
<h3 id="method_save">
<div class="location">at line 88</div>
<code> public <a href="../../FFMpeg/Media/Frame.html"><abbr title="FFMpeg\Media\Frame">Frame</abbr></a>
<strong>save</strong>(string $pathfile, Boolean $accurate = false)</code>
</h3>
<div class="details">
<p>Saves the frame in the given filename.</p>
<p>Uses the <code>unaccurate method by default.</code></p>
<div class="tags">
<h4>Parameters</h4>
<table>
<tr>
<td>string</td>
<td>$pathfile</td>
<td>
</td>
</tr>
<tr>
<td>Boolean</td>
<td>$accurate</td>
<td>
</td>
</tr>
</table>
<h4>Return Value</h4>
<table>
<tr>
<td><a href="../../FFMpeg/Media/Frame.html"><abbr title="FFMpeg\Media\Frame">Frame</abbr></a></td>
<td>
</td>
</tr>
</table>
<h4>Exceptions</h4>
<table>
<tr>
<td><a href="http://php.net/RuntimeException"><abbr title="RuntimeException">RuntimeException</abbr></a></td>
<td>
</td>
</tr>
</table>
</div>
</div>
</div>
<div id="footer">
Generated by <a href="http://sami.sensiolabs.org/" target="_top">Sami, the API Documentation Generator</a>.
</div>
</body>
</html>

View file

@ -0,0 +1,75 @@
<?php
/*
* This file is part of PHP-FFmpeg.
*
* (c) Strime <contact@strime.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FFMpeg\Filters\Waveform;
use FFMpeg\Exception\RuntimeException;
use FFMpeg\Media\Waveform;
class WaveformDownmixFilter implements WaveformFilterInterface
{
/** @var boolean */
private $downmix;
/** @var integer */
private $priority;
// By default, the downmix value is set to FALSE.
public function __construct($downmix = FALSE, $priority = 0)
{
$this->downmix = $downmix;
$this->priority = $priority;
}
/**
* {@inheritdoc}
*/
public function getDownmix()
{
return $this->downmix;
}
/**
* {@inheritdoc}
*/
public function getPriority()
{
return $this->priority;
}
/**
* {@inheritdoc}
*/
public function apply(Waveform $waveform)
{
$dimensions = null;
$commands = array();
foreach ($waveform->getAudio()->getStreams() as $stream) {
if ($stream->isAudio()) {
try {
// If the downmix parameter is set to TRUE, we add an option to the FFMPEG command
if($this->downmix == TRUE) {
$commands[] = '"aformat=channel_layouts=mono"';
}
break;
} catch (RuntimeException $e) {
}
}
}
return $commands;
}
}

View file

@ -0,0 +1,20 @@
<?php
/*
* This file is part of PHP-FFmpeg.
*
* (c) Strime <contact@strime.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FFMpeg\Filters\Waveform;
use FFMpeg\Filters\FilterInterface;
use FFMpeg\Media\Waveform;
interface WaveformFilterInterface extends FilterInterface
{
public function apply(Waveform $waveform);
}

View file

@ -0,0 +1,38 @@
<?php
/*
* This file is part of PHP-FFmpeg.
*
* (c) Strime <contact@strime.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace FFMpeg\Filters\Waveform;
use FFMpeg\Media\Waveform;
class WaveformFilters
{
private $waveform;
public function __construct(Waveform $waveform)
{
$this->waveform = $waveform;
}
/**
* Sets the downmix of the output waveform.
*
* If you want a simpler waveform, sets the downmix to TRUE.
*
* @return WaveformFilters
*/
public function setDownmix()
{
$this->waveform->addFilter(new WaveformDownmixFilter());
return $this;
}
}

View file

@ -19,6 +19,9 @@ class X264 extends DefaultVideo
/** @var boolean */
private $bframesSupport = true;
/** @var integer */
private $passes = 2;
public function __construct($audioCodec = 'libfaac', $videoCodec = 'libx264')
{
$this
@ -62,12 +65,23 @@ class X264 extends DefaultVideo
return array('libx264');
}
/**
* @param $passes
*
* @return X264
*/
public function setPasses($passes)
{
$this->passes = $passes;
return $this;
}
/**
* {@inheritDoc}
*/
public function getPasses()
{
return 2;
return $this->passes;
}
/**

View file

@ -102,4 +102,16 @@ class Audio extends AbstractStreamableMedia
return $this;
}
/**
* Gets the waveform of the video.
*
* @param integer $width
* @param integer $height
* @return Waveform
*/
public function waveform($width = 640, $height = 120)
{
return new Waveform($this, $this->driver, $this->ffprobe, $width, $height);
}
}

View file

@ -0,0 +1,105 @@
<?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\Filters\Waveform\WaveformFilterInterface;
use FFMpeg\Filters\Waveform\WaveformFilters;
use FFMpeg\Driver\FFMpegDriver;
use FFMpeg\FFProbe;
use FFMpeg\Exception\RuntimeException;
use FFMpeg\Coordinate\TimeCode;
class Waveform extends AbstractMediaType
{
/** @var Video */
private $audio;
private $width;
private $height;
public function __construct(Audio $audio, FFMpegDriver $driver, FFProbe $ffprobe, $width, $height)
{
parent::__construct($audio->getPathfile(), $driver, $ffprobe);
$this->audio = $audio;
$this->width = $width;
$this->height = $height;
}
/**
* Returns the audio related to the waveform.
*
* @return Audio
*/
public function getAudio()
{
return $this->audio;
}
/**
* {@inheritdoc}
*
* @return WaveformFilters
*/
public function filters()
{
return new WaveformFilters($this);
}
/**
* {@inheritdoc}
*
* @return Waveform
*/
public function addFilter(WaveformFilterInterface $filter)
{
$this->filters->add($filter);
return $this;
}
/**
* Saves the waveform in the given filename.
*
* @param string $pathfile
*
* @return Waveform
*
* @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(
'-i', $this->pathfile, '-filter_complex',
'showwavespic=s='.$this->width.'x'.$this->height,
'-frames:v', '1'
);
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 waveform', $e->getCode(), $e);
}
return $this;
}
}

View file

@ -0,0 +1,28 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Waveform;
use Tests\FFMpeg\Unit\TestCase;
use FFMpeg\Filters\Waveform\WaveformDownmixFilter;
use FFMpeg\Media\Waveform;
use FFMpeg\Coordinate\TimeCode;
use FFMpeg\FFProbe\DataMapping\StreamCollection;
use FFMpeg\FFProbe\DataMapping\Stream;
class WaveformDownmixFilterTest extends TestCase
{
public function testApply()
{
$stream = new Stream(array('codec_type' => 'audio', 'width' => 960, 'height' => 720));
$streams = new StreamCollection(array($stream));
$audio = $this->getAudioMock(__FILE__);
$audio->expects($this->once())
->method('getStreams')
->will($this->returnValue($streams));
$waveform = new Waveform($audio, $this->getFFMpegDriverMock(), $this->getFFProbeMock(), 640, 120);
$filter = new WaveformDownmixFilter(TRUE);
$this->assertEquals(array('"aformat=channel_layouts=mono"'), $filter->apply($waveform));
}
}

View file

@ -0,0 +1,21 @@
<?php
namespace Tests\FFMpeg\Unit\Filters\Waveform;
use Tests\FFMpeg\Unit\TestCase;
use FFMpeg\Filters\Waveform\WaveformFilters;
class WaveformFiltersTest extends TestCase
{
public function testResize()
{
$Waveform = $this->getWaveformMock();
$filters = new WaveformFilters($Waveform);
$Waveform->expects($this->once())
->method('addFilter')
->with($this->isInstanceOf('FFMpeg\Filters\Waveform\WaveformDownmixFilter'));
$filters->setDownmix();
}
}

View file

@ -0,0 +1,71 @@
<?php
namespace Tests\FFMpeg\Unit\Media;
use FFMpeg\Media\Waveform;
class WaveformTest extends AbstractMediaTestCase
{
public function testFiltersReturnFilters()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$waveform = new Waveform($this->getAudioMock(__FILE__), $driver, $ffprobe, 640, 120);
$this->assertInstanceOf('FFMpeg\Filters\Waveform\WaveformFilters', $waveform->filters());
}
public function testAddFiltersAddsAFilter()
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$filters = $this->getMockBuilder('FFMpeg\Filters\FiltersCollection')
->disableOriginalConstructor()
->getMock();
$filter = $this->getMock('FFMpeg\Filters\Waveform\WaveformFilterInterface');
$filters->expects($this->once())
->method('add')
->with($filter);
$waveform = new Waveform($this->getAudioMock(__FILE__), $driver, $ffprobe, 640, 120);
$waveform->setFiltersCollection($filters);
$waveform->addFilter($filter);
}
/**
* @dataProvider provideSaveOptions
*/
public function testSave($commands)
{
$driver = $this->getFFMpegDriverMock();
$ffprobe = $this->getFFProbeMock();
$pathfile = '/tests/files/Audio.mp3';
array_push($commands, $pathfile);
$driver->expects($this->once())
->method('command')
->with($commands);
$waveform = new Waveform($this->getAudioMock(__FILE__), $driver, $ffprobe, 640, 120);
$this->assertSame($waveform, $waveform->save($pathfile));
}
public function provideSaveOptions()
{
return array(
array(
array(
'-i', NULL, '-filter_complex',
'showwavespic=s=640x120',
'-frames:v', '1',
),
),
);
}
}

View file

@ -47,6 +47,13 @@ class TestCase extends \PHPUnit_Framework_TestCase
->getMock();
}
public function getWaveformMock()
{
return $this->getMockBuilder('FFMpeg\Media\Waveform')
->disableOriginalConstructor()
->getMock();
}
public function getFFMpegDriverMock()
{
return $this->getMockBuilder('FFMpeg\Driver\FFMpegDriver')