Merge branch 'master' into patch-1
This commit is contained in:
		
				commit
				
					
						b60a6c9922
					
				
			
		
					 112 changed files with 3790 additions and 421 deletions
				
			
		
							
								
								
									
										25
									
								
								.github/ISSUE_TEMPLATE.md
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								.github/ISSUE_TEMPLATE.md
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | ||||||
|  | | Q              | A | ||||||
|  | | -------------- | --- | ||||||
|  | | Bug?           | no | ||||||
|  | | New Feature?   | no | ||||||
|  | | Version Used   | Specific tag or commit sha | ||||||
|  | | FFmpeg Version | FFmpeg or AVConv and version | ||||||
|  | | OS             | Your OS and version | ||||||
|  | 
 | ||||||
|  | #### Actual Behavior | ||||||
|  | 
 | ||||||
|  | How does PHP-FFMpeg behave at the moment? | ||||||
|  | 
 | ||||||
|  | #### Expected Behavior | ||||||
|  | 
 | ||||||
|  | What is the behavior you expect? | ||||||
|  | 
 | ||||||
|  | #### Steps to Reproduce | ||||||
|  | 
 | ||||||
|  | What are the steps to reproduce this bug? Please add code examples, | ||||||
|  | screenshots or links to GitHub repositories that reproduce the problem. | ||||||
|  | 
 | ||||||
|  | #### Possible Solutions | ||||||
|  | 
 | ||||||
|  | If you have already ideas how to solve the issue, add them here. | ||||||
|  | Otherwise remove this section. | ||||||
							
								
								
									
										36
									
								
								.github/PULL_REQUEST_TEMPLATE.md
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								.github/PULL_REQUEST_TEMPLATE.md
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | ||||||
|  | | Q                  | A | ||||||
|  | | ------------------ | --- | ||||||
|  | | Bug fix?           | no | ||||||
|  | | New feature?       | no | ||||||
|  | | BC breaks?         | no | ||||||
|  | | Deprecations?      | no | ||||||
|  | | Fixed tickets      | fixes #issuenum | ||||||
|  | | Related issues/PRs | #issuenum | ||||||
|  | | License            | MIT | ||||||
|  | 
 | ||||||
|  | #### What's in this PR? | ||||||
|  | 
 | ||||||
|  | Explain the contents of the PR. | ||||||
|  | 
 | ||||||
|  | #### Why? | ||||||
|  | 
 | ||||||
|  | Which problem does the PR fix? | ||||||
|  | 
 | ||||||
|  | #### Example Usage | ||||||
|  | 
 | ||||||
|  | ```php | ||||||
|  | $foo = new Foo(); | ||||||
|  | 
 | ||||||
|  | // Now we can do | ||||||
|  | $foo->doSomething(); | ||||||
|  | 
 | ||||||
|  | // Remove this section if not needed | ||||||
|  | ~~~ | ||||||
|  | 
 | ||||||
|  | #### BC Breaks/Deprecations | ||||||
|  | 
 | ||||||
|  | Describe BC breaks/deprecations here (Remove this section if not needed). | ||||||
|  | 
 | ||||||
|  | #### To Do | ||||||
|  | 
 | ||||||
|  | - [ ] Create tests | ||||||
							
								
								
									
										6
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -1,6 +1,8 @@ | ||||||
| /nbproject/ | #/nbproject/ | ||||||
| /vendor/ | /vendor/ | ||||||
| /docs/build | /docs/build | ||||||
| composer.phar | composer.phar | ||||||
|  | composer.lock | ||||||
| phpunit.xml | phpunit.xml | ||||||
| 
 | sami.phar | ||||||
|  | .idea/ | ||||||
							
								
								
									
										37
									
								
								.travis.yml
									
										
									
									
									
								
							
							
						
						
									
										37
									
								
								.travis.yml
									
										
									
									
									
								
							|  | @ -1,18 +1,39 @@ | ||||||
| language: php | language: php | ||||||
| 
 | 
 | ||||||
| before_script: | dist: trusty | ||||||
|   - sudo apt-get update | 
 | ||||||
|   - sudo apt-get install -y ffmpeg libavcodec-extra-53 | branches: | ||||||
|   - composer self-update |   only: | ||||||
|   - composer install --no-interaction --prefer-source --dev |     - master | ||||||
|  |     - v1.x | ||||||
|  | 
 | ||||||
|  | cache: | ||||||
|  |   directories: | ||||||
|  |     - $HOME/.composer/cache | ||||||
|  |     - $HOME/.cache | ||||||
| 
 | 
 | ||||||
| php: | php: | ||||||
|   - 5.3.3 |  | ||||||
|   - 5.3 |  | ||||||
|   - 5.4 |   - 5.4 | ||||||
|   - 5.5 |   - 5.5 | ||||||
|   - 5.6 |   - 5.6 | ||||||
|  |   - 7.0 | ||||||
|  |   - 7.1 | ||||||
|  |   - 7.2 | ||||||
|  | 
 | ||||||
|  | matrix: | ||||||
|  |   include: | ||||||
|  |     - php: 5.4 | ||||||
|  |       env: COMPOSER_FLAGS="--prefer-lowest" | ||||||
|  | 
 | ||||||
|  | before_install: | ||||||
|  |   - sudo add-apt-repository ppa:mc3man/trusty-media -y | ||||||
|  |   - sudo apt-get update -q | ||||||
|  |   - composer self-update | ||||||
|  |   - if [ "$COMPOSER_FLAGS" == "--prefer-lowest" ]; then composer require "roave/security-advisories" dev-master --no-update; fi; | ||||||
|  | 
 | ||||||
|  | install: | ||||||
|  |   - sudo apt-get install -y ffmpeg | ||||||
|  |   - composer update --prefer-dist $COMPOSER_FLAGS | ||||||
| 
 | 
 | ||||||
| script: | script: | ||||||
|   - vendor/bin/phpunit --verbose |   - vendor/bin/phpunit --verbose | ||||||
|   - vendor/bin/phpunit --verbose -c phpunit-functional.xml.dist |  | ||||||
|  |  | ||||||
							
								
								
									
										192
									
								
								CHANGELOG.md
									
										
									
									
									
								
							
							
						
						
									
										192
									
								
								CHANGELOG.md
									
										
									
									
									
								
							|  | @ -1,101 +1,173 @@ | ||||||
| CHANGELOG | CHANGELOG | ||||||
| --------- | ========= | ||||||
| 
 | 
 | ||||||
| * 0.6.0 (xx-xx-2015) | All notable changes to this project will be documented in this file. | ||||||
|  | This project adheres to [Semantic Versioning](http://semver.org/). | ||||||
| 
 | 
 | ||||||
|  * AbstractData::get no longer throws exceptions (@sujayjaju). | [Unreleased] | ||||||
|  * Add crop filter (@cangelis). | ------------ | ||||||
|  * Fix watermark (@sujayjaju). |  | ||||||
| 
 | 
 | ||||||
| * 0.5.1 (08-26-2014) | ### Added | ||||||
| 
 | 
 | ||||||
|   * Fix video aspect ratio calculation (@nlegoff). | - Add pull request and issue templates. | ||||||
|  | - Usage of new codec "aac" of ffmpeg 3 | ||||||
| 
 | 
 | ||||||
| * 0.5.0 (08-12-2014) | ### Changed | ||||||
| 
 | 
 | ||||||
|   * Add support for Wav and AAC audio formats (@MrHash). | - Updated changelog to follow [keepachangelog.com](http://keepachangelog.com/) | ||||||
|   * Add watermark filter (@sylvainv). |   style you see now here. | ||||||
|   * Add configuration for audio channels (@SimonSimCity). |  | ||||||
| 
 | 
 | ||||||
| * 0.4.4 (12-17-2013) | [0.7.0] - 2016-12-15 | ||||||
|  | -------------------- | ||||||
| 
 | 
 | ||||||
|   * Fix width / height dimensions extraction. | - Add support for FFMpeg 3 aac codec (@Nek-) | ||||||
|  | - Add a waveform filter to extract audio waveform images (@Romain) | ||||||
| 
 | 
 | ||||||
| * 0.4.3 (12-02-2013) | [0.6.1] - 2016-03-08 | ||||||
|  | -------------------- | ||||||
| 
 | 
 | ||||||
|   * Fix using rotate and resize filters at the same time (#78) | - Support PHP 7 and test against | ||||||
|  | - Unused code cleanup (@haphan) | ||||||
|  | - Composer and tests cleanup (PSR-4 autoloading) | ||||||
|  | - Allow usage of evenement v2.0 | ||||||
| 
 | 
 | ||||||
| * 0.4.2 (11-29-2013) | [0.6.0] - 2016-01-30 | ||||||
|  | -------------------- | ||||||
| 
 | 
 | ||||||
|   * Add Rotate filter. | - AbstractData::get no longer throws exceptions (@sujayjaju). | ||||||
|   * Remove time_start metadata when using synchronize filter | - Add crop filter (@cangelis). | ||||||
|   * Remove restriction on filesystem resources. | - Fix watermark (@sujayjaju). | ||||||
| 
 | 
 | ||||||
| * 0.4.1 (11-26-2013) | [0.5.1] - 2016-08-26 | ||||||
|  | -------------------- | ||||||
| 
 | 
 | ||||||
|   * Add Clip filter (@guimeira) | - Fix video aspect ratio calculation (@nlegoff). | ||||||
| 
 | 
 | ||||||
| * 0.4.0 (10-21-2013) | [0.5.0] - 2014-08-12 | ||||||
|  | -------------------- | ||||||
| 
 | 
 | ||||||
|   * Add support for video to audio transcoding | - Add support for Wav and AAC audio formats (@MrHash). | ||||||
|   * BC Break : Add FormatInterface::getPasses and FormatInterface::getExtraParams | - Add watermark filter (@sylvainv). | ||||||
|  | - Add configuration for audio channels (@SimonSimCity). | ||||||
| 
 | 
 | ||||||
| * 0.3.5 (10-21-2013) | [0.4.4] - 2016-12-17 | ||||||
|  | -------------------- | ||||||
| 
 | 
 | ||||||
|   * Add vorbis audio format (@jacobbudin). | - Fix width / height dimensions extraction. | ||||||
|   * Fix #66 : Allow single pass encodings. |  | ||||||
| 
 | 
 | ||||||
| * 0.3.4 (09-05-2013) | [0.4.3] - 2013-02-12 | ||||||
|  | -------------------- | ||||||
| 
 | 
 | ||||||
|   * Fix Invalid ratio computing. | - Fix using rotate and resize filters at the same time (#78) | ||||||
| 
 | 
 | ||||||
| * 0.3.3 (09-05-2013) | [0.4.2] - 2013-11-29 | ||||||
|  | -------------------- | ||||||
| 
 | 
 | ||||||
|   * Add convenient Stream::getDimensions method to extract video dimension. | - Add Rotate filter. | ||||||
|   * Add DisplayRatioFixer Frame filter. | - Remove time_start metadata when using synchronize filter | ||||||
|  | - Remove restriction on filesystem resources. | ||||||
| 
 | 
 | ||||||
| * 0.3.2 (08-08-2013) | [0.4.1] - 2013-11-26 | ||||||
|  | -------------------- | ||||||
| 
 | 
 | ||||||
|   * Fix A/V synchronization over flash and HTML5 players. | - Add Clip filter (@guimeira) | ||||||
| 
 | 
 | ||||||
| * 0.3.1 (08-06-2013) | [0.4.0] - 2013-10-21 | ||||||
|  | -------------------- | ||||||
| 
 | 
 | ||||||
|   * Allow use of FFProbe on remote URIs. | - Add support for video to audio transcoding | ||||||
|   * Fix #47 : MediaTypeInterface::save adds filters depending on the codec. | - BC Break : Add FormatInterface::getPasses and FormatInterface::getExtraParams | ||||||
|   * Save frame to target file without prompt. |  | ||||||
| 
 | 
 | ||||||
| * 0.3.0 (07-04-2013) | [0.3.5] - 2013-10-21 | ||||||
|  | -------------------- | ||||||
| 
 | 
 | ||||||
|   * Complete rewrite of the library, lots of BC breaks, check the doc. | - Add vorbis audio format (@jacobbudin). | ||||||
|  | - Fix #66 : Allow single pass encodings. | ||||||
| 
 | 
 | ||||||
| * 0.2.4 (05-10-2013) | [0.3.4] - 2013-09-05 | ||||||
|  | -------------------- | ||||||
| 
 | 
 | ||||||
|   * Add Video\ResizableInterface::getModulus method for better output scaling (@retrojunk) | - Fix Invalid ratio computing. | ||||||
|   * Fix timeout setting on audio/video encoding (@xammep-ua) |  | ||||||
| 
 | 
 | ||||||
| * 0.2.3 (04-21-2013) | [0.3.3] - 2013-09-05 | ||||||
|  | -------------------- | ||||||
| 
 | 
 | ||||||
|   * Add timeout getter and setter on FFMpeg and FFProbe | - Add convenient Stream::getDimensions method to extract video dimension. | ||||||
|   * Add timeout setting via second argument on FFMpeg::load and FFProbe::load | - Add DisplayRatioFixer Frame filter. | ||||||
| 
 | 
 | ||||||
| * 0.2.2 (02-11-2013) | [0.3.2] - 2013-08-08 | ||||||
|  | -------------------- | ||||||
| 
 | 
 | ||||||
|   * Add compatibility with FFMpeg 1.1 | - Fix A/V synchronization over flash and HTML5 players. | ||||||
|   * Upgrade deprecated options (`-ab`, `-qscale` and `-b`) |  | ||||||
|   * Use of a custom stat file for each multi-pass encoding (fix #20) |  | ||||||
|   * Use larger version range for dependencies |  | ||||||
| 
 | 
 | ||||||
| * 0.2.1 (02-04-2013) | [0.3.1] - 2013-08-06 | ||||||
|  | -------------------- | ||||||
| 
 | 
 | ||||||
|   * Parse the output of FFProbe using correct EOL sequences (@ak76) | - Allow use of FFProbe on remote URIs. | ||||||
|   * Add process timeout customization (@pulse00) | - Fix #47 : MediaTypeInterface::save adds filters depending on the codec. | ||||||
|   * Fix `accurate` option (`FFMpeg::extractImage`) | - Save frame to target file without prompt. | ||||||
| 
 | 
 | ||||||
| * 0.2.0 (12-13-2012) | [0.3.0] - 2013-07-04 | ||||||
|  | -------------------- | ||||||
| 
 | 
 | ||||||
|   * Add HelperInterface and support for realtime progress ( @pulse00 ). | - Complete rewrite of the library, lots of BC breaks, check the doc. | ||||||
|   * Add `accurate` option to `FFMpeg::extractImage` method. |  | ||||||
| 
 | 
 | ||||||
| * 0.1.0 (10-30-2012) | [0.2.4] - 2013-05-10 | ||||||
|  | -------------------- | ||||||
| 
 | 
 | ||||||
|   * First stable version. | - Add Video\ResizableInterface::getModulus method for better output scaling (@retrojunk) | ||||||
|  | - Fix timeout setting on audio/video encoding (@xammep-ua) | ||||||
|  | 
 | ||||||
|  | [0.2.3] - 2013-04-21 | ||||||
|  | -------------------- | ||||||
|  | 
 | ||||||
|  | - Add timeout getter and setter on FFMpeg and FFProbe | ||||||
|  | - Add timeout setting via second argument on FFMpeg::load and FFProbe::load | ||||||
|  | 
 | ||||||
|  | [0.2.2] - 2013-02-11 | ||||||
|  | -------------------- | ||||||
|  | 
 | ||||||
|  | - Add compatibility with FFMpeg 1.1 | ||||||
|  | - Upgrade deprecated options (`-ab`, `-qscale` and `-b`) | ||||||
|  | - Use of a custom stat file for each multi-pass encoding (fix #20) | ||||||
|  | - Use larger version range for dependencies | ||||||
|  | 
 | ||||||
|  | [0.2.1] - 2013-02-04 | ||||||
|  | -------------------- | ||||||
|  | 
 | ||||||
|  | - Parse the output of FFProbe using correct EOL sequences (@ak76) | ||||||
|  | - Add process timeout customization (@pulse00) | ||||||
|  | - Fix `accurate` option (`FFMpeg::extractImage`) | ||||||
|  | 
 | ||||||
|  | [0.2.0] - 2012-12-13 | ||||||
|  | -------------------- | ||||||
|  | 
 | ||||||
|  | - Add HelperInterface and support for realtime progress ( @pulse00 ). | ||||||
|  | - Add `accurate` option to `FFMpeg::extractImage` method. | ||||||
|  | 
 | ||||||
|  | 0.1.0 - 2012-10-30 | ||||||
|  | -------------------- | ||||||
|  | 
 | ||||||
|  | - First stable version. | ||||||
|  | 
 | ||||||
|  | [Unreleased]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.6.1...HEAD | ||||||
|  | [0.6.1]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.6.0...0.6.1 | ||||||
|  | [0.6.0]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.5.1...0.6.0 | ||||||
|  | [0.5.1]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.5.0...0.5.1 | ||||||
|  | [0.5.0]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.4.4...0.5.0 | ||||||
|  | [0.4.4]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.4.3...0.4.4 | ||||||
|  | [0.4.3]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.4.2...0.4.3 | ||||||
|  | [0.4.2]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.4.1...0.4.2 | ||||||
|  | [0.4.1]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.4.0...0.4.1 | ||||||
|  | [0.4.0]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.3.5...0.4.0 | ||||||
|  | [0.3.5]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.3.4...0.3.5 | ||||||
|  | [0.3.4]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.3.3...0.3.4 | ||||||
|  | [0.3.3]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.3.2...0.3.3 | ||||||
|  | [0.3.2]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.3.1...0.3.2 | ||||||
|  | [0.3.1]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.3.0...0.3.1 | ||||||
|  | [0.3.0]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.2.4...0.3.0 | ||||||
|  | [0.2.4]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.2.3...0.2.4 | ||||||
|  | [0.2.3]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.2.2...0.2.3 | ||||||
|  | [0.2.2]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.2.1...0.2.2 | ||||||
|  | [0.2.1]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.2.0...0.2.1 | ||||||
|  | [0.2.0]: https://github.com/PHP-FFMpeg/PHP-FFMpeg/compare/0.1.0...0.2.0 | ||||||
|  |  | ||||||
							
								
								
									
										299
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										299
									
								
								README.md
									
										
									
									
									
								
							|  | @ -1,4 +1,4 @@ | ||||||
| #PHP FFmpeg | # PHP FFmpeg | ||||||
| 
 | 
 | ||||||
| [](http://travis-ci.org/PHP-FFMpeg/PHP-FFMpeg) | [](http://travis-ci.org/PHP-FFMpeg/PHP-FFMpeg) | ||||||
| 
 | 
 | ||||||
|  | @ -6,19 +6,19 @@ | ||||||
| 
 | 
 | ||||||
| An Object Oriented library to convert video/audio files with FFmpeg / AVConv. | An Object Oriented library to convert video/audio files with FFmpeg / AVConv. | ||||||
| 
 | 
 | ||||||
| Check another amazing repo : [PHP FFMpeg extras](https://github.com/alchemy-fr/PHP-FFMpeg-Extras), you will find lots of Audio/Video formats there. | Check another amazing repo: [PHP FFMpeg extras](https://github.com/alchemy-fr/PHP-FFMpeg-Extras), you will find lots of Audio/Video formats there. | ||||||
| 
 | 
 | ||||||
| ## Your attention please | ## Your attention please | ||||||
| 
 | 
 | ||||||
| ### How this library works : | ### How this library works: | ||||||
| 
 | 
 | ||||||
| This library requires a working FFMpeg install. You will need both FFMpeg and FFProbe binaries to use it. | This library requires a working FFMpeg install. You will need both FFMpeg and FFProbe binaries to use it. | ||||||
| Be sure that these binaries can be located with system PATH to get the benefit of the binary detection, | Be sure that these binaries can be located with system PATH to get the benefit of the binary detection, | ||||||
| otherwise you should have to explicitely give the binaries path on load. | otherwise you should have to explicitly give the binaries path on load. | ||||||
| 
 | 
 | ||||||
| For Windows users : Please find the binaries at http://ffmpeg.zeranoe.com/builds/. | For Windows users : Please find the binaries at http://ffmpeg.zeranoe.com/builds/. | ||||||
| 
 | 
 | ||||||
| ### Known issues : | ### Known issues: | ||||||
| 
 | 
 | ||||||
| - Using rotate and resize will produce a corrupted output when using | - Using rotate and resize will produce a corrupted output when using | ||||||
| [libav](http://libav.org/) 0.8. The bug is fixed in version 9. This bug does not | [libav](http://libav.org/) 0.8. The bug is fixed in version 9. This bug does not | ||||||
|  | @ -28,17 +28,16 @@ appear in latest ffmpeg version. | ||||||
| 
 | 
 | ||||||
| The recommended way to install PHP-FFMpeg is through [Composer](https://getcomposer.org). | The recommended way to install PHP-FFMpeg is through [Composer](https://getcomposer.org). | ||||||
| 
 | 
 | ||||||
| ```json | ```bash | ||||||
| { | $ composer require php-ffmpeg/php-ffmpeg | ||||||
|     "require": { |  | ||||||
|         "php-ffmpeg/php-ffmpeg": "~0.5" |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ## Basic Usage | ## Basic Usage | ||||||
| 
 | 
 | ||||||
| ```php | ```php | ||||||
|  | 
 | ||||||
|  | require 'vendor/autoload.php'; | ||||||
|  | 
 | ||||||
| $ffmpeg = FFMpeg\FFMpeg::create(); | $ffmpeg = FFMpeg\FFMpeg::create(); | ||||||
| $video = $ffmpeg->open('video.mpg'); | $video = $ffmpeg->open('video.mpg'); | ||||||
| $video | $video | ||||||
|  | @ -62,14 +61,14 @@ to browse the source code as it is self-documented. | ||||||
| ### FFMpeg | ### FFMpeg | ||||||
| 
 | 
 | ||||||
| `FFMpeg\FFMpeg` is the main object to use to manipulate medias. To build it, | `FFMpeg\FFMpeg` is the main object to use to manipulate medias. To build it, | ||||||
| use the static `FFMpeg\FFMpeg::create` : | use the static `FFMpeg\FFMpeg::create`: | ||||||
| 
 | 
 | ||||||
| ```php | ```php | ||||||
| $ffmpeg = FFMpeg\FFMpeg::create(); | $ffmpeg = FFMpeg\FFMpeg::create(); | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| FFMpeg will autodetect ffmpeg and ffprobe binaries. If you want to give binary | FFMpeg will autodetect ffmpeg and ffprobe binaries. If you want to give binary | ||||||
| paths explicitely, you can pass an array as configuration. A `Psr\Logger\LoggerInterface` | paths explicitly, you can pass an array as configuration. A `Psr\Logger\LoggerInterface` | ||||||
| can also be passed to log binary executions. | can also be passed to log binary executions. | ||||||
| 
 | 
 | ||||||
| ```php | ```php | ||||||
|  | @ -86,8 +85,8 @@ $ffmpeg = FFMpeg\FFMpeg::create(array( | ||||||
| `FFMpeg\FFMpeg` creates media based on URIs. URIs could be either a pointer to a | `FFMpeg\FFMpeg` creates media based on URIs. URIs could be either a pointer to a | ||||||
| local filesystem resource, an HTTP resource or any resource supported by FFmpeg. | local filesystem resource, an HTTP resource or any resource supported by FFmpeg. | ||||||
| 
 | 
 | ||||||
| **Note** : To list all supported resource type of your FFmpeg build, use the | **Note**: To list all supported resource type of your FFmpeg build, use the | ||||||
| `-protocols` command : | `-protocols` command: | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
| ffmpeg -protocols | ffmpeg -protocols | ||||||
|  | @ -99,12 +98,12 @@ To open a resource, use the `FFMpeg\FFMpeg::open` method. | ||||||
| $ffmpeg->open('video.mpeg'); | $ffmpeg->open('video.mpeg'); | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Two types of media can be resolved : `FFMpeg\Media\Audio` and `FFMpeg\Media\Video`. | Two types of media can be resolved: `FFMpeg\Media\Audio` and `FFMpeg\Media\Video`. | ||||||
| A third type, `FFMpeg\Media\Frame`, is available through videos. | A third type, `FFMpeg\Media\Frame`, is available through videos. | ||||||
| 
 | 
 | ||||||
| #### Video | ### Video | ||||||
| 
 | 
 | ||||||
| `FFMpeg\Media\Video` can be transcoded, ie : change codec, isolate audio or | `FFMpeg\Media\Video` can be transcoded, ie: change codec, isolate audio or | ||||||
| video. Frames can be extracted. | video. Frames can be extracted. | ||||||
| 
 | 
 | ||||||
| ##### Transcoding | ##### Transcoding | ||||||
|  | @ -115,15 +114,15 @@ pass a `FFMpeg\Format\FormatInterface` for that. | ||||||
| Please note that audio and video bitrate are set on the format. | Please note that audio and video bitrate are set on the format. | ||||||
| 
 | 
 | ||||||
| ```php | ```php | ||||||
| $format = new Format\Video\X264(); | $format = new FFMpeg\Format\Video\X264(); | ||||||
| $format->on('progress', function ($video, $format, $percentage) { | $format->on('progress', function ($video, $format, $percentage) { | ||||||
|     echo "$percentage % transcoded"; |     echo "$percentage % transcoded"; | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| $format | $format | ||||||
|     -> setKiloBitrate(1000) |     ->setKiloBitrate(1000) | ||||||
|     -> setAudioChannels(2) |     ->setAudioChannels(2) | ||||||
|     -> setAudioKiloBitrate(256); |     ->setAudioKiloBitrate(256); | ||||||
| 
 | 
 | ||||||
| $video->save($format, 'video.avi'); | $video->save($format, 'video.avi'); | ||||||
| ``` | ``` | ||||||
|  | @ -136,7 +135,7 @@ below for more informations. | ||||||
| You can extract a frame at any timecode using the `FFMpeg\Media\Video::frame` | You can extract a frame at any timecode using the `FFMpeg\Media\Video::frame` | ||||||
| method. | 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 | You can pass any `FFMpeg\Coordinate\TimeCode` as argument, see dedicated | ||||||
| documentation below for more information. | documentation below for more information. | ||||||
| 
 | 
 | ||||||
|  | @ -145,6 +144,54 @@ $frame = $video->frame(FFMpeg\Coordinate\TimeCode::fromSeconds(42)); | ||||||
| $frame->save('image.jpg'); | $frame->save('image.jpg'); | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
|  | If you want to extract multiple images from your video, you can use the following filter: | ||||||
|  | 
 | ||||||
|  | ```php | ||||||
|  | $video | ||||||
|  |     ->filters() | ||||||
|  |     ->extractMultipleFrames(FFMpeg\Filters\Video\ExtractMultipleFramesFilter::FRAMERATE_EVERY_10SEC, '/path/to/destination/folder/') | ||||||
|  |     ->synchronize(); | ||||||
|  | 
 | ||||||
|  | $video | ||||||
|  |     ->save(new FFMpeg\Format\Video\X264(), '/path/to/new/file'); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ##### 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 the first two arguments and an array of hex string colors for ffmpeg to use for the waveform, see dedicated | ||||||
|  | documentation below for more information. | ||||||
|  | 
 | ||||||
|  | The ouput file MUST use the PNG extension. | ||||||
|  | 
 | ||||||
|  | ```php | ||||||
|  | $waveform = $audio->waveform(640, 120, array('#00FF00')); | ||||||
|  | $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 as mp3 | ||||||
|  | $video->save($audio_format, 'audio.mp3'); | ||||||
|  | 
 | ||||||
|  | // Set the audio file | ||||||
|  | $audio = $ffmpeg->open( 'audio.mp3' ); | ||||||
|  | 
 | ||||||
|  | // Create the waveform | ||||||
|  | $waveform = $audio->waveform(); | ||||||
|  | $waveform->save( 'waveform.png' ); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
| ##### Filters | ##### Filters | ||||||
| 
 | 
 | ||||||
| You can apply filters on `FFMpeg\Media\Video` with the `FFMpeg\Media\Video::addFilter` | You can apply filters on `FFMpeg\Media\Video` with the `FFMpeg\Media\Video::addFilter` | ||||||
|  | @ -173,9 +220,9 @@ $video->filters()->rotate($angle); | ||||||
| 
 | 
 | ||||||
| The `$angle` parameter must be one of the following constants : | The `$angle` parameter must be one of the following constants : | ||||||
| 
 | 
 | ||||||
| - `FFMpeg\Filters\Video\RotateFilter::ROTATE_90` : 90° clockwise | - `FFMpeg\Filters\Video\RotateFilter::ROTATE_90`: 90° clockwise | ||||||
| - `FFMpeg\Filters\Video\RotateFilter::ROTATE_180` : 180° | - `FFMpeg\Filters\Video\RotateFilter::ROTATE_180`: 180° | ||||||
| - `FFMpeg\Filters\Video\RotateFilter::ROTATE_270` : 90° counterclockwise | - `FFMpeg\Filters\Video\RotateFilter::ROTATE_270`: 90° counterclockwise | ||||||
| 
 | 
 | ||||||
| ###### Resize | ###### Resize | ||||||
| 
 | 
 | ||||||
|  | @ -185,12 +232,57 @@ Resizes a video to a given size. | ||||||
| $video->filters()->resize($dimension, $mode, $useStandards); | $video->filters()->resize($dimension, $mode, $useStandards); | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| The resize filter takes three parameters : | The resize filter takes three parameters: | ||||||
| 
 | 
 | ||||||
| - `$dimension`, an instance of `FFMpeg\Coordinate\Dimension` | - `$dimension`, an instance of `FFMpeg\Coordinate\Dimension` | ||||||
| - `$mode`, one of the constants `FFMpeg\Filters\Video\ResizeFilter::RESIZEMODE_*` constants | - `$mode`, one of the constants `FFMpeg\Filters\Video\ResizeFilter::RESIZEMODE_*` constants | ||||||
| - `$useStandards`, a boolean to force the use of the nearest aspect ratio standard. | - `$useStandards`, a boolean to force the use of the nearest aspect ratio standard. | ||||||
| 
 | 
 | ||||||
|  | If you want a video in a non-standard ratio, you can use the padding filter to resize your video in the desired size, and wrap it into black bars. | ||||||
|  | 
 | ||||||
|  | ```php | ||||||
|  | $video->filters()->pad($dimension); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | The pad filter takes one parameter: | ||||||
|  | 
 | ||||||
|  | - `$dimension`, an instance of `FFMpeg\Coordinate\Dimension` | ||||||
|  | 
 | ||||||
|  | Don't forget to save it afterwards. | ||||||
|  | 
 | ||||||
|  | ```php | ||||||
|  | $video->save(new FFMpeg\Format\Video\X264(), $new_file); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ###### Watermark | ||||||
|  | 
 | ||||||
|  | Watermark a video with a given image. | ||||||
|  | 
 | ||||||
|  | ```php | ||||||
|  | $video | ||||||
|  |     ->filters() | ||||||
|  |     ->watermark($watermarkPath, array( | ||||||
|  |         'position' => 'relative', | ||||||
|  |         'bottom' => 50, | ||||||
|  |         'right' => 50, | ||||||
|  |     )); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | The watermark filter takes two parameters: | ||||||
|  | 
 | ||||||
|  | `$watermarkPath`, the path to your watermark file. | ||||||
|  | `$coordinates`, an array defining how you want your watermark positioned. You can use relative positioning as demonstrated above or absolute as such: | ||||||
|  | 
 | ||||||
|  | ```php | ||||||
|  | $video | ||||||
|  |     ->filters() | ||||||
|  |     ->watermark($watermarkPath, array( | ||||||
|  |         'position' => 'absolute', | ||||||
|  |         'x' => 1180, | ||||||
|  |         'y' => 620, | ||||||
|  |     )); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
| ###### Framerate | ###### Framerate | ||||||
| 
 | 
 | ||||||
| Changes the frame rate of the video. | Changes the frame rate of the video. | ||||||
|  | @ -199,7 +291,7 @@ Changes the frame rate of the video. | ||||||
| $video->filters()->framerate($framerate, $gop); | $video->filters()->framerate($framerate, $gop); | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| The framerate filter takes two parameters : | The framerate filter takes two parameters: | ||||||
| 
 | 
 | ||||||
| - `$framerate`, an instance of `FFMpeg\Coordinate\Framerate` | - `$framerate`, an instance of `FFMpeg\Coordinate\Framerate` | ||||||
| - `$gop`, a [GOP](https://wikipedia.org/wiki/Group_of_pictures) value (integer) | - `$gop`, a [GOP](https://wikipedia.org/wiki/Group_of_pictures) value (integer) | ||||||
|  | @ -228,9 +320,21 @@ The clip filter takes two parameters: | ||||||
| - `$start`, an instance of `FFMpeg\Coordinate\TimeCode`, specifies the start point of the clip | - `$start`, an instance of `FFMpeg\Coordinate\TimeCode`, specifies the start point of the clip | ||||||
| - `$duration`, optional, an instance of `FFMpeg\Coordinate\TimeCode`, specifies the duration of the clip | - `$duration`, optional, an instance of `FFMpeg\Coordinate\TimeCode`, specifies the duration of the clip | ||||||
| 
 | 
 | ||||||
| #### Audio | ###### Crop | ||||||
| 
 | 
 | ||||||
| `FFMpeg\Media\Audio` can be transcoded, ie : change codec, isolate audio or | Crops the video based on a width and height(a `Point`) | ||||||
|  | 
 | ||||||
|  | ```php | ||||||
|  | $video->filters()->crop(new FFMpeg\Coordinate\Point("t*100", 0, true), new FFMpeg\Coordinate\Dimension(200, 600)); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | It takes two parameters: | ||||||
|  | - `$point`, an instance of `FFMpeg\Coordinate\Point`, specifies the point to crop | ||||||
|  | - `$dimension`, an instance of `FFMpeg\Coordinate\Dimension`, specifies the dimension of the output video | ||||||
|  | 
 | ||||||
|  | ### Audio | ||||||
|  | 
 | ||||||
|  | `FFMpeg\Media\Audio` can be transcoded too, ie: change codec, isolate audio or | ||||||
| video. Frames can be extracted. | video. Frames can be extracted. | ||||||
| 
 | 
 | ||||||
| ##### Transcoding | ##### Transcoding | ||||||
|  | @ -250,8 +354,8 @@ $format->on('progress', function ($audio, $format, $percentage) { | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| $format | $format | ||||||
|     -> setAudioChannels(2) |     ->setAudioChannels(2) | ||||||
|     -> setAudioKiloBitrate(256); |     ->setAudioKiloBitrate(256); | ||||||
| 
 | 
 | ||||||
| $audio->save($format, 'track.flac'); | $audio->save($format, 'track.flac'); | ||||||
| ``` | ``` | ||||||
|  | @ -267,6 +371,35 @@ method. It only accepts audio filters. | ||||||
| You can build your own filters and some are bundled in PHP-FFMpeg - they are | You can build your own filters and some are bundled in PHP-FFMpeg - they are | ||||||
| accessible through the `FFMpeg\Media\Audio::filters` method. | accessible through the `FFMpeg\Media\Audio::filters` method. | ||||||
| 
 | 
 | ||||||
|  | ##### Clipping | ||||||
|  | Cuts the audio at a desired point. | ||||||
|  | 
 | ||||||
|  | ```php | ||||||
|  | $audio->filters()->clip(FFMpeg\Coordinate\TimeCode::fromSeconds(30), FFMpeg\Coordinate\TimeCode::fromSeconds(15)); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ###### Metadata | ||||||
|  | 
 | ||||||
|  | Add metadata to audio files. Just pass an array of key=value pairs of all | ||||||
|  | metadata you would like to add. If no arguments are passed into the filter | ||||||
|  | all metadata will be removed from input file. Currently supported data is | ||||||
|  | title, artist, album, artist, composer, track, year, description, artwork | ||||||
|  | 
 | ||||||
|  | ```php | ||||||
|  | $audio->filters()->addMetadata(["title" => "Some Title", "track" => 1]); | ||||||
|  | 
 | ||||||
|  | //remove all metadata and video streams from audio file | ||||||
|  | $audio->filters()->addMetadata(); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Add artwork to the audio file | ||||||
|  | ```php | ||||||
|  | $audio->filters()->addMetadata(["artwork" => "/path/to/image/file.jpg"]); | ||||||
|  | ``` | ||||||
|  | NOTE: at present ffmpeg (version 3.2.2) only supports artwork output for .mp3 | ||||||
|  | files | ||||||
|  | 
 | ||||||
| ###### Resample | ###### Resample | ||||||
| 
 | 
 | ||||||
| Resamples an audio file. | Resamples an audio file. | ||||||
|  | @ -293,6 +426,68 @@ $frame->save('target.jpg'); | ||||||
| This method has a second optional boolean parameter. Set it to true to get | This method has a second optional boolean parameter. Set it to true to get | ||||||
| accurate images ; it takes more time to execute. | accurate images ; it takes more time to execute. | ||||||
| 
 | 
 | ||||||
|  | #### Gif | ||||||
|  | 
 | ||||||
|  | A gif is an animated image extracted from a sequence of the video. | ||||||
|  | 
 | ||||||
|  | You can save gif files using the `FFMpeg\Media\Gif::save` method. | ||||||
|  | 
 | ||||||
|  | ```php | ||||||
|  | $video = $ffmpeg->open( '/path/to/video' ); | ||||||
|  | $video | ||||||
|  |     ->gif(FFMpeg\Coordinate\TimeCode::fromSeconds(2), new FFMpeg\Coordinate\Dimension(640, 480), 3) | ||||||
|  |     ->save($new_file); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | This method has a third optional boolean parameter, which is the duration of the animation. | ||||||
|  | If you don't set it, you will get a fixed gif image. | ||||||
|  | 
 | ||||||
|  | #### Concatenation | ||||||
|  | 
 | ||||||
|  | This feature allows you to generate one audio or video file, based on multiple sources. | ||||||
|  | 
 | ||||||
|  | There are two ways to concatenate videos, depending on the codecs of the sources. | ||||||
|  | If your sources have all been encoded with the same codec, you will want to use the `FFMpeg\Media\Concatenate::saveFromSameCodecs` which has way better performances. | ||||||
|  | If your sources have been encoded with different codecs, you will want to use the `FFMpeg\Media\Concatenate::saveFromDifferentCodecs`. | ||||||
|  | 
 | ||||||
|  | The first function will use the initial codec as the one for the generated file. | ||||||
|  | With the second function, you will be able to choose which codec you want for the generated file. | ||||||
|  | 
 | ||||||
|  | You also need to pay attention to the fact that, when using the saveFromDifferentCodecs method, | ||||||
|  | your files MUST have video and audio streams. | ||||||
|  | 
 | ||||||
|  | In both cases, you will have to provide an array of files. | ||||||
|  | 
 | ||||||
|  | To concatenate videos encoded with the same codec, do as follow: | ||||||
|  | 
 | ||||||
|  | ```php | ||||||
|  | // In order to instantiate the video object, you HAVE TO pass a path to a valid video file. | ||||||
|  | // We recommand that you put there the path of any of the video you want to use in this concatenation. | ||||||
|  | $video = $ffmpeg->open( '/path/to/video' ); | ||||||
|  | $video | ||||||
|  |     ->concat(array('/path/to/video1', '/path/to/video2')) | ||||||
|  |     ->saveFromSameCodecs('/path/to/new_file', TRUE); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | The boolean parameter of the save function allows you to use the copy parameter which accelerates drastically the generation of the encoded file. | ||||||
|  | 
 | ||||||
|  | To concatenate videos encoded with the same codec, do as follow: | ||||||
|  | 
 | ||||||
|  | ```php | ||||||
|  | // In order to instantiate the video object, you HAVE TO pass a path to a valid video file. | ||||||
|  | // We recommand that you put there the path of any of the video you want to use in this concatenation. | ||||||
|  | $video = $ffmpeg->open( '/path/to/video' ); | ||||||
|  | 
 | ||||||
|  | $format = new FFMpeg\Format\Video\X264(); | ||||||
|  | $format->setAudioCodec("libmp3lame"); | ||||||
|  | 
 | ||||||
|  | $video | ||||||
|  |     ->concat(array('/path/to/video1', '/path/to/video2')) | ||||||
|  |     ->saveFromDifferentCodecs($format, '/path/to/new_file'); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | More details about concatenation in FFMPEG can be found [here](https://trac.ffmpeg.org/wiki/Concatenate), [here](https://ffmpeg.org/ffmpeg-formats.html#concat-1) and [here](https://ffmpeg.org/ffmpeg.html#Stream-copy). | ||||||
|  | 
 | ||||||
| #### Formats | #### Formats | ||||||
| 
 | 
 | ||||||
| A format implements `FFMpeg\Format\FormatInterface`. To save to a video file, | A format implements `FFMpeg\Format\FormatInterface`. To save to a video file, | ||||||
|  | @ -305,7 +500,7 @@ informations about the transcoding. | ||||||
| Predefined formats already provide progress informations as events. | Predefined formats already provide progress informations as events. | ||||||
| 
 | 
 | ||||||
| ```php | ```php | ||||||
| $format = new Format\Video\X264(); | $format = new FFMpeg\Format\Video\X264(); | ||||||
| $format->on('progress', function ($video, $format, $percentage) { | $format->on('progress', function ($video, $format, $percentage) { | ||||||
|     echo "$percentage % transcoded"; |     echo "$percentage % transcoded"; | ||||||
| }); | }); | ||||||
|  | @ -315,6 +510,18 @@ $video->save($format, 'video.avi'); | ||||||
| 
 | 
 | ||||||
| The callback provided for the event can be any callable. | The callback provided for the event can be any callable. | ||||||
| 
 | 
 | ||||||
|  | ##### Add additional parameters | ||||||
|  | 
 | ||||||
|  | You can add additional parameters to your encoding requests based on your video format. | ||||||
|  | 
 | ||||||
|  | The argument of the setAdditionalParameters method is an array. | ||||||
|  | 
 | ||||||
|  | ```php | ||||||
|  | $format = new FFMpeg\Format\Video\X264(); | ||||||
|  | $format->setAdditionalParameters(array('foo', 'bar')); | ||||||
|  | $video->save($format, 'video.avi'); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
| ##### Create your own format | ##### Create your own format | ||||||
| 
 | 
 | ||||||
| The easiest way to create a format is to extend the abstract | The easiest way to create a format is to extend the abstract | ||||||
|  | @ -355,7 +562,7 @@ FFMpeg use many units for time and space coordinates. | ||||||
| - `FFMpeg\Coordinate\AspectRatio` represents an aspect ratio. | - `FFMpeg\Coordinate\AspectRatio` represents an aspect ratio. | ||||||
| - `FFMpeg\Coordinate\Dimension` represent a dimension. | - `FFMpeg\Coordinate\Dimension` represent a dimension. | ||||||
| - `FFMpeg\Coordinate\FrameRate` represent a framerate. | - `FFMpeg\Coordinate\FrameRate` represent a framerate. | ||||||
| - `FFMpeg\Coordinate\Point` represent a point. | - `FFMpeg\Coordinate\Point` represent a point. (Supports dynamic points since v0.10.0) | ||||||
| - `FFMpeg\Coordinate\TimeCode` represent a timecode. | - `FFMpeg\Coordinate\TimeCode` represent a timecode. | ||||||
| 
 | 
 | ||||||
| ### FFProbe | ### FFProbe | ||||||
|  | @ -379,9 +586,19 @@ $ffprobe | ||||||
|     ->get('duration');             // returns the duration property |     ->get('duration');             // returns the duration property | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ##Using with Silex Microframework | ### Validating media files | ||||||
| 
 | 
 | ||||||
| Service provider is easy to set up : | (since 0.10.0) | ||||||
|  | You can validate media files using PHP-FFMpeg's FFProbe wrapper. | ||||||
|  | 
 | ||||||
|  | ```php | ||||||
|  | $ffprobe = FFMpeg\FFProbe::create(); | ||||||
|  | $ffprobe->isValid('/path/to/file/to/check'); // returns bool | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ## Using with Silex Microframework | ||||||
|  | 
 | ||||||
|  | Service provider is easy to set up: | ||||||
| 
 | 
 | ||||||
| ```php | ```php | ||||||
| $app = new Silex\Application(); | $app = new Silex\Application(); | ||||||
|  | @ -390,7 +607,7 @@ $app->register(new FFMpeg\FFMpegServiceProvider()); | ||||||
| $video = $app['ffmpeg']->open('video.mpeg'); | $video = $app['ffmpeg']->open('video.mpeg'); | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Available options are as follow : | Available options are as follow: | ||||||
| 
 | 
 | ||||||
| ```php | ```php | ||||||
| $app->register(new FFMpeg\FFMpegServiceProvider(), array( | $app->register(new FFMpeg\FFMpegServiceProvider(), array( | ||||||
|  | @ -405,14 +622,6 @@ $app->register(new FFMpeg\FFMpegServiceProvider(), array( | ||||||
| )); | )); | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ## API Browser |  | ||||||
| 
 |  | ||||||
| Browse the [API](http://readthedocs.org/docs/ffmpeg-php/en/latest/_static/API/) |  | ||||||
| 
 |  | ||||||
| ## License | ## License | ||||||
| 
 | 
 | ||||||
| This project is licensed under the [MIT license](http://opensource.org/licenses/MIT). | This project is licensed under the [MIT license](http://opensource.org/licenses/MIT). | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|  |  | ||||||
|  | @ -5,40 +5,60 @@ | ||||||
|     "keywords": ["video processing", "video", "audio processing", "audio", "avconv", "ffmpeg", "avprobe", "ffprobe"], |     "keywords": ["video processing", "video", "audio processing", "audio", "avconv", "ffmpeg", "avprobe", "ffprobe"], | ||||||
|     "license": "MIT", |     "license": "MIT", | ||||||
|     "authors": [ |     "authors": [ | ||||||
|     { |         { | ||||||
|         "name": "Romain Neutron", |             "name": "Romain Neutron", | ||||||
|         "email": "imprec@gmail.com", |             "email": "imprec@gmail.com", | ||||||
|         "homepage": "http://www.lickmychip.com/" |             "homepage": "http://www.lickmychip.com/" | ||||||
|     }, |         }, | ||||||
|     { |         { | ||||||
|         "name": "Phraseanet Team", |             "name": "Phraseanet Team", | ||||||
|         "email": "info@alchemy.fr", |             "email": "info@alchemy.fr", | ||||||
|         "homepage": "http://www.phraseanet.com/" |             "homepage": "http://www.phraseanet.com/" | ||||||
|     } |         }, | ||||||
|  |         { | ||||||
|  |             "name": "Patrik Karisch", | ||||||
|  |             "email": "patrik@karisch.guru", | ||||||
|  |             "homepage": "http://www.karisch.guru" | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "name": "Romain Biard", | ||||||
|  |             "email": "romain.biard@gmail.com", | ||||||
|  |             "homepage": "https://www.strime.io/" | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "name": "Jens Hausdorf", | ||||||
|  |             "email": "hello@jens-hausdorf.de", | ||||||
|  |             "homepage": "https://jens-hausdorf.de" | ||||||
|  |         } | ||||||
|     ], |     ], | ||||||
|     "require": { |     "require": { | ||||||
|         "php"                          : ">=5.3.3", |         "php": "^5.3.9 || ^7.0", | ||||||
|         "alchemy/binary-driver"        : "~1.5", |         "alchemy/binary-driver": "^1.5", | ||||||
|         "doctrine/cache"               : "~1.0", |         "doctrine/cache": "^1.0", | ||||||
|         "evenement/evenement"          : "~1.0", |         "evenement/evenement": "^2.0 || ^1.0", | ||||||
|         "neutron/temporary-filesystem" : "~2.1, >=2.1.1" |         "neutron/temporary-filesystem": "^2.1.1" | ||||||
|     }, |     }, | ||||||
|     "suggest": { |     "suggest": { | ||||||
|         "php-ffmpeg/extras"        : "A compilation of common audio & video drivers for PHP-FFMpeg" |         "php-ffmpeg/extras": "A compilation of common audio & video drivers for PHP-FFMpeg" | ||||||
|     }, |     }, | ||||||
|     "require-dev": { |     "require-dev": { | ||||||
|         "sami/sami"       : "~1.0", |         "sami/sami": "~1.0", | ||||||
|         "silex/silex"     : "~1.0", |         "silex/silex": "~1.0", | ||||||
|         "phpunit/phpunit" : "~3.7" |         "phpunit/phpunit": "^4.8.36" | ||||||
|     }, |     }, | ||||||
|     "autoload": { |     "autoload": { | ||||||
|         "psr-0": { |         "psr-0": { | ||||||
|             "FFMpeg": "src" |             "FFMpeg": "src" | ||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|  |     "autoload-dev": { | ||||||
|  |         "psr-4": { | ||||||
|  |             "Tests\\FFMpeg\\": "tests" | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|     "extra": { |     "extra": { | ||||||
|         "branch-alias": { |         "branch-alias": { | ||||||
|             "dev-master": "0.5-dev" |             "dev-master": "0.7-dev" | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -119,7 +119,17 @@ | ||||||
|             </tr> |             </tr> | ||||||
|                     <tr> |                     <tr> | ||||||
|                 <td class="type"> |                 <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> | ||||||
|                 <td class="last"> |                 <td class="last"> | ||||||
|                     <a href="#method_getPasses">getPasses</a>() |                     <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> | ||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|                 <h3 id="method_getPasses"> |                 <h3 id="method_getPasses"> | ||||||
|         <div class="location">at line 68</div> |         <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            string |         <code>            public            integer | ||||||
|     <strong>getPasses</strong>()</code> |     <strong>getPasses</strong>()</code> | ||||||
|     </h3> |     </h3> | ||||||
|     <div class="details"> |     <div class="details"> | ||||||
|  | @ -517,7 +552,7 @@ | ||||||
| 
 | 
 | ||||||
|                     <table> |                     <table> | ||||||
|         <tr> |         <tr> | ||||||
|             <td>string</td> |             <td>integer</td> | ||||||
|             <td> |             <td> | ||||||
| </td> | </td> | ||||||
|         </tr> |         </tr> | ||||||
|  |  | ||||||
|  | @ -171,6 +171,16 @@ | ||||||
|                     <p>Exports the audio in the desired format, applies registered filters.</p> |                     <p>Exports the audio in the desired format, applies registered filters.</p> | ||||||
|                 </td> |                 </td> | ||||||
|                 <td></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> |             </tr> | ||||||
|             </table> |             </table> | ||||||
| 
 | 
 | ||||||
|  | @ -609,6 +619,59 @@ | ||||||
|                     </div> |                     </div> | ||||||
|     </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> | ||||||
|             <div id="footer"> |             <div id="footer"> | ||||||
|  |  | ||||||
							
								
								
									
										621
									
								
								docs/source/API/API/FFMpeg/Media/Waveform.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										621
									
								
								docs/source/API/API/FFMpeg/Media/Waveform.html
									
										
									
									
									
										Normal 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 <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 <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 <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 <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 <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 <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 <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> | ||||||
|  | @ -1,27 +0,0 @@ | ||||||
| <?xml version="1.0" encoding="UTF-8"?> |  | ||||||
| <phpunit backupGlobals="false" |  | ||||||
|          backupStaticAttributes="false" |  | ||||||
|          colors="true" |  | ||||||
|          convertErrorsToExceptions="true" |  | ||||||
|          convertNoticesToExceptions="true" |  | ||||||
|          convertWarningsToExceptions="true" |  | ||||||
|          processIsolation="false" |  | ||||||
|          stopOnFailure="false" |  | ||||||
|          syntaxCheck="true" |  | ||||||
|          verbose="false" |  | ||||||
|          bootstrap="tests/bootstrap.php" |  | ||||||
| > |  | ||||||
|     <testsuites> |  | ||||||
|         <testsuite name="FFMpeg Tests Suite"> |  | ||||||
|             <directory>tests/FFMpeg/Functional</directory> |  | ||||||
|         </testsuite> |  | ||||||
|     </testsuites> |  | ||||||
|     <filter> |  | ||||||
|       <blacklist> |  | ||||||
|         <directory>vendor</directory> |  | ||||||
|         <directory>tests</directory> |  | ||||||
|       </blacklist> |  | ||||||
|     </filter> |  | ||||||
| 
 |  | ||||||
| </phpunit> |  | ||||||
| 
 |  | ||||||
|  | @ -12,16 +12,19 @@ | ||||||
|          bootstrap="tests/bootstrap.php" |          bootstrap="tests/bootstrap.php" | ||||||
| > | > | ||||||
|     <testsuites> |     <testsuites> | ||||||
|         <testsuite name="FFMpeg Tests Suite"> |         <testsuite name="unit"> | ||||||
|             <directory>tests/FFMpeg/Tests</directory> |             <directory>tests/Unit</directory> | ||||||
|  |         </testsuite> | ||||||
|  |         <testsuite name="functional"> | ||||||
|  |             <directory>tests/Functional</directory> | ||||||
|         </testsuite> |         </testsuite> | ||||||
|     </testsuites> |     </testsuites> | ||||||
|  | 
 | ||||||
|     <filter> |     <filter> | ||||||
|       <blacklist> |       <blacklist> | ||||||
|         <directory>vendor</directory> |         <directory>vendor</directory> | ||||||
|         <directory>tests</directory> |         <directory>tests</directory> | ||||||
|       </blacklist> |       </blacklist> | ||||||
|     </filter> |     </filter> | ||||||
| 
 |  | ||||||
| </phpunit> | </phpunit> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -16,10 +16,15 @@ class Point | ||||||
|     private $x; |     private $x; | ||||||
|     private $y; |     private $y; | ||||||
| 
 | 
 | ||||||
|     public function __construct($x, $y) |     public function __construct($x, $y, $dynamic = false) | ||||||
|     { |     { | ||||||
|         $this->x = (int) $x; |         if ($dynamic) { | ||||||
|         $this->y = (int) $y; |             $this->x = $x; | ||||||
|  |             $this->y = $y; | ||||||
|  |         } else { | ||||||
|  |             $this->x = (int)$x; | ||||||
|  |             $this->y = (int)$y; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  |  | ||||||
|  | @ -89,4 +89,32 @@ class TimeCode | ||||||
| 
 | 
 | ||||||
|         return new static($hours, $minutes, $seconds, $frames); |         return new static($hours, $minutes, $seconds, $frames); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns this timecode in seconds | ||||||
|  |      * @return int | ||||||
|  |      */ | ||||||
|  |     public function toSeconds() { | ||||||
|  |         $seconds = 0; | ||||||
|  | 
 | ||||||
|  |         $seconds += $this->hours * 60 * 60; | ||||||
|  |         $seconds += $this->minutes * 60; | ||||||
|  |         $seconds += $this->seconds; | ||||||
|  | 
 | ||||||
|  |         // TODO: Handle frames?
 | ||||||
|  | 
 | ||||||
|  |         return (int) $seconds; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Helper function wether `$timecode` is after this one | ||||||
|  |      * | ||||||
|  |      * @param   TimeCode    $timecode   The Timecode to compare | ||||||
|  |      * @return bool | ||||||
|  |      */ | ||||||
|  |     public function isAfter(TimeCode $timecode) { | ||||||
|  |         // convert everything to seconds and compare
 | ||||||
|  |         return ($this->toSeconds() > $timecode->toSeconds()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -170,6 +170,25 @@ class FFProbe | ||||||
|         return $this->probe($pathfile, '-show_format', static::TYPE_FORMAT); |         return $this->probe($pathfile, '-show_format', static::TYPE_FORMAT); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * @api | ||||||
|  |      * | ||||||
|  |      * Checks wether the given `$pathfile` is considered a valid media file. | ||||||
|  |      * | ||||||
|  |      * @param string $pathfile | ||||||
|  |      * @return bool | ||||||
|  |      * @since 0.10.0 | ||||||
|  |      */ | ||||||
|  |     public function isValid($pathfile) | ||||||
|  |     { | ||||||
|  |         try { | ||||||
|  |             return $this->format($pathfile)->get('duration') > 0; | ||||||
|  |         } catch(\Exception $e) { | ||||||
|  |             // complete invalid data
 | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * @api |      * @api | ||||||
|      * |      * | ||||||
|  |  | ||||||
|  | @ -11,8 +11,6 @@ | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\FFProbe\DataMapping; | namespace FFMpeg\FFProbe\DataMapping; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Exception\InvalidArgumentException; |  | ||||||
| 
 |  | ||||||
| abstract class AbstractData implements \Countable | abstract class AbstractData implements \Countable | ||||||
| { | { | ||||||
|     private $properties; |     private $properties; | ||||||
|  |  | ||||||
							
								
								
									
										58
									
								
								src/FFMpeg/Filters/Audio/AddMetadataFilter.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/FFMpeg/Filters/Audio/AddMetadataFilter.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | ||||||
|  | <?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\Filters\Audio; | ||||||
|  | 
 | ||||||
|  | use FFMpeg\Filters\Audio\AudioFilterInterface; | ||||||
|  | use FFMpeg\Format\AudioInterface; | ||||||
|  | use FFMpeg\Media\Audio; | ||||||
|  | 
 | ||||||
|  | class AddMetadataFilter implements AudioFilterInterface | ||||||
|  | { | ||||||
|  | 	/** @var Array */ | ||||||
|  | 	private $metaArr; | ||||||
|  | 	/** @var Integer */ | ||||||
|  | 	private $priority; | ||||||
|  | 
 | ||||||
|  | 	function __construct($metaArr = null, $priority = 9) | ||||||
|  | 	{ | ||||||
|  | 		$this->metaArr = $metaArr; | ||||||
|  | 		$this->priority = $priority; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public function getPriority() | ||||||
|  | 	{ | ||||||
|  | 		//must be of high priority in case theres a second input stream (artwork) to register with audio
 | ||||||
|  | 		return $this->priority; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public function apply(Audio $audio, AudioInterface $format) | ||||||
|  | 	{ | ||||||
|  | 		$meta = $this->metaArr; | ||||||
|  | 
 | ||||||
|  | 		if (is_null($meta)) { | ||||||
|  | 			return ['-map_metadata', '-1', '-vn']; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		$metadata = []; | ||||||
|  | 
 | ||||||
|  | 		if (array_key_exists("artwork", $meta)) { | ||||||
|  | 			array_push($metadata, "-i", $meta['artwork'], "-map", "0", "-map", "1"); | ||||||
|  | 			unset($meta['artwork']); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		foreach ($meta as $k => $v) { | ||||||
|  | 			array_push($metadata, "-metadata", "$k=$v"); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return $metadata; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										84
									
								
								src/FFMpeg/Filters/Audio/AudioClipFilter.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								src/FFMpeg/Filters/Audio/AudioClipFilter.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,84 @@ | ||||||
|  | <?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\Filters\Audio; | ||||||
|  | 
 | ||||||
|  | use FFMpeg\Coordinate\TimeCode; | ||||||
|  | use FFMpeg\Format\AudioInterface; | ||||||
|  | use FFMpeg\Media\Audio; | ||||||
|  | 
 | ||||||
|  | class AudioClipFilter implements AudioFilterInterface { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @var TimeCode | ||||||
|  |      */ | ||||||
|  |     private $start; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @var TimeCode | ||||||
|  |      */ | ||||||
|  |     private $duration; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @var int | ||||||
|  |      */ | ||||||
|  |     private $priority; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     public function __construct(TimeCode $start, TimeCode $duration = null, $priority = 0) { | ||||||
|  |         $this->start = $start; | ||||||
|  |         $this->duration = $duration; | ||||||
|  |         $this->priority = $priority; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @inheritDoc | ||||||
|  |      */ | ||||||
|  |     public function getPriority() { | ||||||
|  |         return $this->priority; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |      /** | ||||||
|  |       * Returns the start position the audio is being cutted | ||||||
|  |       * | ||||||
|  |       * @return TimeCode | ||||||
|  |       */ | ||||||
|  |      public function getStart() { | ||||||
|  |          return $this->start; | ||||||
|  |      } | ||||||
|  | 
 | ||||||
|  |      /** | ||||||
|  |       * Returns how long the audio is being cutted. Returns null when the duration is infinite, | ||||||
|  |       * | ||||||
|  |       * @return TimeCode|null | ||||||
|  |       */ | ||||||
|  |      public function getDuration() { | ||||||
|  |          return $this->duration; | ||||||
|  |      } | ||||||
|  | 
 | ||||||
|  |      /** | ||||||
|  |       * @inheritDoc | ||||||
|  |       */ | ||||||
|  |      public function apply(Audio $audio, AudioInterface $format) { | ||||||
|  |          $commands = array('-ss', (string) $this->start); | ||||||
|  | 
 | ||||||
|  |          if ($this->duration !== null) { | ||||||
|  |             $commands[] = '-t'; | ||||||
|  |             $commands[] = (string) $this->duration; | ||||||
|  |          } | ||||||
|  | 
 | ||||||
|  |          $commands[] = '-acodec'; | ||||||
|  |          $commands[] = 'copy'; | ||||||
|  | 
 | ||||||
|  |          return $commands; | ||||||
|  |      } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -1,8 +1,19 @@ | ||||||
| <?php | <?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\Filters\Audio; | namespace FFMpeg\Filters\Audio; | ||||||
| 
 | 
 | ||||||
|  | use FFMpeg\Filters\Audio\AddMetadataFilter; | ||||||
| use FFMpeg\Media\Audio; | use FFMpeg\Media\Audio; | ||||||
|  | use FFMpeg\Coordinate\TimeCode; | ||||||
| 
 | 
 | ||||||
| class AudioFilters | class AudioFilters | ||||||
| { | { | ||||||
|  | @ -26,4 +37,38 @@ class AudioFilters | ||||||
| 
 | 
 | ||||||
|         return $this; |         return $this; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Add metadata to an audio file. If no arguments are given then filter | ||||||
|  |      * will remove all metadata from the audio file | ||||||
|  |      * @param Array|Null $data  If array must contain one of these key/value pairs: | ||||||
|  |      *    - "title": Title metadata | ||||||
|  |      *    - "artist": Artist metadata | ||||||
|  |      *    - "composer": Composer metadata | ||||||
|  |      *    - "album": Album metadata | ||||||
|  |      *    - "track": Track metadata | ||||||
|  |      *    - "artwork": Song artwork. String of file path | ||||||
|  |      *    - "year": Year metadata | ||||||
|  |      *    - "genre": Genre metadata | ||||||
|  |      *    - "description": Description metadata | ||||||
|  |      */ | ||||||
|  |     public function addMetadata($data = null) | ||||||
|  |     { | ||||||
|  |         $this->media->addFilter(new AddMetadataFilter($data)); | ||||||
|  | 
 | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Cuts the audio at `$start`, optionally define the end | ||||||
|  |      * | ||||||
|  |      * @param   TimeCode    $start      Where the clipping starts(seek to time) | ||||||
|  |      * @param   TimeCode    $duration   How long the clipped audio should be | ||||||
|  |      * @return AudioFilters | ||||||
|  |      */ | ||||||
|  |     public function clip($start, $duration = null) { | ||||||
|  |         $this->media->addFilter(new AudioClipFilter($start, $duration)); | ||||||
|  | 
 | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,5 +1,14 @@ | ||||||
| <?php | <?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\Filters\Audio; | namespace FFMpeg\Filters\Audio; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Media\Audio; | use FFMpeg\Media\Audio; | ||||||
|  |  | ||||||
							
								
								
									
										20
									
								
								src/FFMpeg/Filters/Concat/ConcatFilterInterface.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/FFMpeg/Filters/Concat/ConcatFilterInterface.php
									
										
									
									
									
										Normal 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\Concat; | ||||||
|  | 
 | ||||||
|  | use FFMpeg\Filters\FilterInterface; | ||||||
|  | use FFMpeg\Media\Concat; | ||||||
|  | 
 | ||||||
|  | interface ConcatFilterInterface extends FilterInterface | ||||||
|  | { | ||||||
|  |     public function apply(Concat $concat); | ||||||
|  | } | ||||||
							
								
								
									
										24
									
								
								src/FFMpeg/Filters/Concat/ConcatFilters.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/FFMpeg/Filters/Concat/ConcatFilters.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | ||||||
|  | <?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\Concat; | ||||||
|  | 
 | ||||||
|  | use FFMpeg\Media\Concat; | ||||||
|  | 
 | ||||||
|  | class ConcatFilters | ||||||
|  | { | ||||||
|  |     private $concat; | ||||||
|  | 
 | ||||||
|  |     public function __construct(Concat $concat) | ||||||
|  |     { | ||||||
|  |         $this->concat = $concat; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								src/FFMpeg/Filters/Gif/GifFilterInterface.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/FFMpeg/Filters/Gif/GifFilterInterface.php
									
										
									
									
									
										Normal 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\Gif; | ||||||
|  | 
 | ||||||
|  | use FFMpeg\Filters\FilterInterface; | ||||||
|  | use FFMpeg\Media\Gif; | ||||||
|  | 
 | ||||||
|  | interface GifFilterInterface extends FilterInterface | ||||||
|  | { | ||||||
|  |     public function apply(Gif $gif); | ||||||
|  | } | ||||||
							
								
								
									
										24
									
								
								src/FFMpeg/Filters/Gif/GifFilters.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/FFMpeg/Filters/Gif/GifFilters.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | ||||||
|  | <?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\Gif; | ||||||
|  | 
 | ||||||
|  | use FFMpeg\Media\Gif; | ||||||
|  | 
 | ||||||
|  | class GifFilters | ||||||
|  | { | ||||||
|  |     private $gif; | ||||||
|  | 
 | ||||||
|  |     public function __construct(Gif $gif) | ||||||
|  |     { | ||||||
|  |         $this->gif = $gif; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										128
									
								
								src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								src/FFMpeg/Filters/Video/ExtractMultipleFramesFilter.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,128 @@ | ||||||
|  | <?php | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  |  * This file is part of PHP-FFmpeg. | ||||||
|  |  * | ||||||
|  |  * (c) Strime <romain@strime.io> | ||||||
|  |  * | ||||||
|  |  * For the full copyright and license information, please view the LICENSE | ||||||
|  |  * file that was distributed with this source code. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | namespace FFMpeg\Filters\Video; | ||||||
|  | 
 | ||||||
|  | use FFMpeg\Exception\InvalidArgumentException; | ||||||
|  | use FFMpeg\Exception\RuntimeException; | ||||||
|  | use FFMpeg\Media\Video; | ||||||
|  | use FFMpeg\Format\VideoInterface; | ||||||
|  | 
 | ||||||
|  | class ExtractMultipleFramesFilter implements VideoFilterInterface | ||||||
|  | { | ||||||
|  |     /** will extract a frame every second */ | ||||||
|  |     const FRAMERATE_EVERY_SEC = '1/1'; | ||||||
|  |     /** will extract a frame every 2 seconds */ | ||||||
|  |     const FRAMERATE_EVERY_2SEC = '1/2'; | ||||||
|  |     /** will extract a frame every 5 seconds */ | ||||||
|  |     const FRAMERATE_EVERY_5SEC = '1/5'; | ||||||
|  |     /** will extract a frame every 10 seconds */ | ||||||
|  |     const FRAMERATE_EVERY_10SEC = '1/10'; | ||||||
|  |     /** will extract a frame every 30 seconds */ | ||||||
|  |     const FRAMERATE_EVERY_30SEC = '1/30'; | ||||||
|  |     /** will extract a frame every minute */ | ||||||
|  |     const FRAMERATE_EVERY_60SEC = '1/60'; | ||||||
|  | 
 | ||||||
|  |     /** @var integer */ | ||||||
|  |     private $priority; | ||||||
|  |     private $frameRate; | ||||||
|  |     private $destinationFolder; | ||||||
|  | 
 | ||||||
|  |     public function __construct($frameRate = self::FRAMERATE_EVERY_SEC, $destinationFolder = __DIR__, $priority = 0) | ||||||
|  |     { | ||||||
|  |         $this->priority = $priority; | ||||||
|  |         $this->frameRate = $frameRate; | ||||||
|  | 
 | ||||||
|  |         // Make sure that the destination folder has a trailing slash
 | ||||||
|  |         if(strcmp( substr($destinationFolder, -1), "/") != 0) | ||||||
|  |             $destinationFolder .= "/"; | ||||||
|  | 
 | ||||||
|  |         // Set the destination folder
 | ||||||
|  |         $this->destinationFolder = $destinationFolder; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * {@inheritdoc} | ||||||
|  |      */ | ||||||
|  |     public function getPriority() | ||||||
|  |     { | ||||||
|  |         return $this->priority; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * {@inheritdoc} | ||||||
|  |      */ | ||||||
|  |     public function getFrameRate() | ||||||
|  |     { | ||||||
|  |         return $this->frameRate; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * {@inheritdoc} | ||||||
|  |      */ | ||||||
|  |     public function getDestinationFolder() | ||||||
|  |     { | ||||||
|  |         return $this->destinationFolder; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * {@inheritdoc} | ||||||
|  |      */ | ||||||
|  |     public function apply(Video $video, VideoInterface $format) | ||||||
|  |     { | ||||||
|  |         $commands = array(); | ||||||
|  |         $duration = 0; | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             // Get the duration of the video
 | ||||||
|  |             foreach ($video->getStreams()->videos() as $stream) { | ||||||
|  |                 if ($stream->has('duration')) { | ||||||
|  |                     $duration = $stream->get('duration'); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // Get the number of frames per second we have to extract.
 | ||||||
|  |             if(preg_match('/(\d+)(?:\s*)([\+\-\*\/])(?:\s*)(\d+)/', $this->frameRate, $matches) !== FALSE){ | ||||||
|  |                 $operator = $matches[2]; | ||||||
|  | 
 | ||||||
|  |                 switch($operator){ | ||||||
|  |                     case '/': | ||||||
|  |                         $nbFramesPerSecond = $matches[1] / $matches[3]; | ||||||
|  |                         break; | ||||||
|  | 
 | ||||||
|  |                     default: | ||||||
|  |                         throw new InvalidArgumentException('The frame rate is not a proper division: ' . $this->frameRate); | ||||||
|  |                         break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // Set the number of digits to use in the exported filenames
 | ||||||
|  |             $nbImages = ceil( $duration * $nbFramesPerSecond ); | ||||||
|  | 
 | ||||||
|  |             if($nbImages < 100) | ||||||
|  |                 $nbDigitsInFileNames = "02"; | ||||||
|  |             elseif($nbImages < 1000) | ||||||
|  |                 $nbDigitsInFileNames = "03"; | ||||||
|  |             else | ||||||
|  |                 $nbDigitsInFileNames = "06"; | ||||||
|  | 
 | ||||||
|  |             // Set the parameters
 | ||||||
|  |             $commands[] = '-vf'; | ||||||
|  |             $commands[] = 'fps=' . $this->frameRate; | ||||||
|  |             $commands[] = $this->destinationFolder . 'frame-%'.$nbDigitsInFileNames.'d.jpg'; | ||||||
|  |         } | ||||||
|  |         catch (RuntimeException $e) { | ||||||
|  |             throw new RuntimeException('An error occured while extracting the frames: ' . $e->getMessage() . '. The code: ' . $e->getCode()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return $commands; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										59
									
								
								src/FFMpeg/Filters/Video/PadFilter.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/FFMpeg/Filters/Video/PadFilter.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,59 @@ | ||||||
|  | <?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\Video; | ||||||
|  | 
 | ||||||
|  | use FFMpeg\Coordinate\Dimension; | ||||||
|  | use FFMpeg\Media\Video; | ||||||
|  | use FFMpeg\Format\VideoInterface; | ||||||
|  | 
 | ||||||
|  | class PadFilter implements VideoFilterInterface | ||||||
|  | { | ||||||
|  |     /** @var Dimension */ | ||||||
|  |     private $dimension; | ||||||
|  |     /** @var integer */ | ||||||
|  |     private $priority; | ||||||
|  | 
 | ||||||
|  |     public function __construct(Dimension $dimension, $priority = 0) | ||||||
|  |     { | ||||||
|  |         $this->dimension = $dimension; | ||||||
|  |         $this->priority = $priority; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * {@inheritdoc} | ||||||
|  |      */ | ||||||
|  |     public function getPriority() | ||||||
|  |     { | ||||||
|  |         return $this->priority; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @return Dimension | ||||||
|  |      */ | ||||||
|  |     public function getDimension() | ||||||
|  |     { | ||||||
|  |         return $this->dimension; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * {@inheritdoc} | ||||||
|  |      */ | ||||||
|  |     public function apply(Video $video, VideoInterface $format) | ||||||
|  |     { | ||||||
|  |         $commands = array(); | ||||||
|  | 
 | ||||||
|  |         $commands[] = '-vf'; | ||||||
|  |         $commands[] = 'scale=iw*min(' . $this->dimension->getWidth() . '/iw\,' . $this->dimension->getHeight() .'/ih):ih*min(' . $this->dimension->getWidth() . '/iw\,' . $this->dimension->getHeight() .'/ih),pad=' . $this->dimension->getWidth() . ':' . $this->dimension->getHeight() . ':(' . $this->dimension->getWidth() . '-iw)/2:(' . $this->dimension->getHeight() .'-ih)/2'; | ||||||
|  | 
 | ||||||
|  |         return $commands; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -98,8 +98,10 @@ class ResizeFilter implements VideoFilterInterface | ||||||
|         if (null !== $dimensions) { |         if (null !== $dimensions) { | ||||||
|             $dimensions = $this->getComputedDimensions($dimensions, $format->getModulus()); |             $dimensions = $this->getComputedDimensions($dimensions, $format->getModulus()); | ||||||
| 
 | 
 | ||||||
|             $commands[] = '-s'; |             // Using Filter to have ordering
 | ||||||
|             $commands[] = $dimensions->getWidth() . 'x' . $dimensions->getHeight(); |             $commands[] = '-vf'; | ||||||
|  |             $commands[] = '[in]scale=' . $dimensions->getWidth() . ':' . $dimensions->getHeight() . ' [out]'; | ||||||
|  |              | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return $commands; |         return $commands; | ||||||
|  |  | ||||||
|  | @ -46,7 +46,7 @@ class VideoFilters extends AudioFilters | ||||||
|      * Changes the video framerate. |      * Changes the video framerate. | ||||||
|      * |      * | ||||||
|      * @param FrameRate $framerate |      * @param FrameRate $framerate | ||||||
|      * @param type      $gop |      * @param Integer      $gop | ||||||
|      * |      * | ||||||
|      * @return VideoFilters |      * @return VideoFilters | ||||||
|      */ |      */ | ||||||
|  | @ -57,6 +57,21 @@ class VideoFilters extends AudioFilters | ||||||
|         return $this; |         return $this; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Extract multiple frames from the video | ||||||
|  |      * | ||||||
|  |      * @param string $frameRate | ||||||
|  |      * @param string  $destinationFolder | ||||||
|  |      * | ||||||
|  |      * @return $this | ||||||
|  |      */ | ||||||
|  |     public function extractMultipleFrames($frameRate = ExtractMultipleFramesFilter::FRAMERATE_EVERY_2SEC, $destinationFolder = __DIR__) | ||||||
|  |     { | ||||||
|  |         $this->media->addFilter(new ExtractMultipleFramesFilter($frameRate, $destinationFolder)); | ||||||
|  | 
 | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * Synchronizes audio and video. |      * Synchronizes audio and video. | ||||||
|      * |      * | ||||||
|  | @ -98,6 +113,20 @@ class VideoFilters extends AudioFilters | ||||||
|         return $this; |         return $this; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Adds padding (black bars) to a video. | ||||||
|  |      * | ||||||
|  |      * @param Dimension $dimension | ||||||
|  |      * | ||||||
|  |      * @return VideoFilters | ||||||
|  |      */ | ||||||
|  |     public function pad(Dimension $dimension) | ||||||
|  |     { | ||||||
|  |         $this->media->addFilter(new PadFilter($dimension)); | ||||||
|  | 
 | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public function rotate($angle) |     public function rotate($angle) | ||||||
|     { |     { | ||||||
|         $this->media->addFilter(new RotateFilter($angle, 30)); |         $this->media->addFilter(new RotateFilter($angle, 30)); | ||||||
|  | @ -132,4 +161,18 @@ class VideoFilters extends AudioFilters | ||||||
| 
 | 
 | ||||||
|         return $this; |         return $this; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Applies a custom filter: -vf foo bar | ||||||
|  |      * | ||||||
|  |      * @param string    $parameters | ||||||
|  |      * | ||||||
|  |      * @return VideoFilters | ||||||
|  |      */ | ||||||
|  |     public function custom($parameters) | ||||||
|  |     { | ||||||
|  |         $this->media->addFilter(new CustomFilter($parameters)); | ||||||
|  | 
 | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										74
									
								
								src/FFMpeg/Filters/Waveform/WaveformDownmixFilter.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/FFMpeg/Filters/Waveform/WaveformDownmixFilter.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,74 @@ | ||||||
|  | <?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) | ||||||
|  |     { | ||||||
|  |         $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; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								src/FFMpeg/Filters/Waveform/WaveformFilterInterface.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/FFMpeg/Filters/Waveform/WaveformFilterInterface.php
									
										
									
									
									
										Normal 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); | ||||||
|  | } | ||||||
							
								
								
									
										38
									
								
								src/FFMpeg/Filters/Waveform/WaveformFilters.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/FFMpeg/Filters/Waveform/WaveformFilters.php
									
										
									
									
									
										Normal 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; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -121,10 +121,10 @@ abstract class DefaultAudio extends EventEmitter implements AudioInterface, Prog | ||||||
|     /** |     /** | ||||||
|      * {@inheritdoc} |      * {@inheritdoc} | ||||||
|      */ |      */ | ||||||
|     public function createProgressListener(MediaTypeInterface $media, FFProbe $ffprobe, $pass, $total) |     public function createProgressListener(MediaTypeInterface $media, FFProbe $ffprobe, $pass, $total, $duration = 0) | ||||||
|     { |     { | ||||||
|         $format = $this; |         $format = $this; | ||||||
|         $listener = new AudioProgressListener($ffprobe, $media->getPathfile(), $pass, $total); |         $listener = new AudioProgressListener($ffprobe, $media->getPathfile(), $pass, $total, $duration); | ||||||
|         $listener->on('progress', function () use ($media, $format) { |         $listener->on('progress', function () use ($media, $format) { | ||||||
|            $format->emit('progress', array_merge(array($media, $format), func_get_args())); |            $format->emit('progress', array_merge(array($media, $format), func_get_args())); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|  | @ -80,12 +80,13 @@ abstract class AbstractProgressListener extends EventEmitter implements Listener | ||||||
|      * |      * | ||||||
|      * @throws RuntimeException |      * @throws RuntimeException | ||||||
|      */ |      */ | ||||||
|     public function __construct(FFProbe $ffprobe, $pathfile, $currentPass, $totalPass) |     public function __construct(FFProbe $ffprobe, $pathfile, $currentPass, $totalPass, $duration = 0) | ||||||
|     { |     { | ||||||
|         $this->ffprobe = $ffprobe; |         $this->ffprobe = $ffprobe; | ||||||
|         $this->pathfile = $pathfile; |         $this->pathfile = $pathfile; | ||||||
|         $this->currentPass = $currentPass; |         $this->currentPass = $currentPass; | ||||||
|         $this->totalPass = $totalPass; |         $this->totalPass = $totalPass; | ||||||
|  |         $this->duration = $duration; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -120,6 +121,14 @@ abstract class AbstractProgressListener extends EventEmitter implements Listener | ||||||
|         return $this->totalPass; |         return $this->totalPass; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * @return int | ||||||
|  |      */ | ||||||
|  |     public function getCurrentTime() | ||||||
|  |     { | ||||||
|  |         return $this->currentTime; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * {@inheritdoc} |      * {@inheritdoc} | ||||||
|      */ |      */ | ||||||
|  | @ -171,6 +180,12 @@ abstract class AbstractProgressListener extends EventEmitter implements Listener | ||||||
| 
 | 
 | ||||||
|         if ($this->lastOutput !== null) { |         if ($this->lastOutput !== null) { | ||||||
|             $delta = $currentTime - $this->lastOutput; |             $delta = $currentTime - $this->lastOutput; | ||||||
|  | 
 | ||||||
|  |             // Check the type of the currentSize variable and convert it to an integer if needed.
 | ||||||
|  |             if(!is_numeric($currentSize)) { | ||||||
|  |                 $currentSize = (int)$currentSize; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|             $deltaSize = $currentSize - $this->currentSize; |             $deltaSize = $currentSize - $this->currentSize; | ||||||
|             $rate = $deltaSize * $delta; |             $rate = $deltaSize * $delta; | ||||||
|             if ($rate > 0) { |             if ($rate > 0) { | ||||||
|  | @ -240,9 +255,8 @@ abstract class AbstractProgressListener extends EventEmitter implements Listener | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         $this->totalSize = $format->get('size') / 1024; |         $this->duration = (int) $this->duration > 0 ? $this->duration : $format->get('duration'); | ||||||
|         $this->duration = $format->get('duration'); |         $this->totalSize = $format->get('size') / 1024 * ($this->duration / $format->get('duration')); | ||||||
| 
 |  | ||||||
|         $this->initialized = true; |         $this->initialized = true; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,8 +24,9 @@ interface ProgressableInterface extends EventEmitterInterface | ||||||
|      * @param FFProbe            $ffprobe |      * @param FFProbe            $ffprobe | ||||||
|      * @param Integer            $pass    The current pas snumber |      * @param Integer            $pass    The current pas snumber | ||||||
|      * @param Integer            $total   The total pass number |      * @param Integer            $total   The total pass number | ||||||
|  |      * @param Integer            $duration   The new video duration | ||||||
|      * |      * | ||||||
|      * @return array An array of listeners |      * @return array An array of listeners | ||||||
|      */ |      */ | ||||||
|     public function createProgressListener(MediaTypeInterface $media, FFProbe $ffprobe, $pass, $total); |     public function createProgressListener(MediaTypeInterface $media, FFProbe $ffprobe, $pass, $total, $duration = 0); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -32,6 +32,9 @@ abstract class DefaultVideo extends DefaultAudio implements VideoInterface | ||||||
|     /** @var Integer */ |     /** @var Integer */ | ||||||
|     protected $modulus = 16; |     protected $modulus = 16; | ||||||
| 
 | 
 | ||||||
|  |     /** @var Array */ | ||||||
|  |     protected $additionalParamaters; | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * {@inheritdoc} |      * {@inheritdoc} | ||||||
|      */ |      */ | ||||||
|  | @ -97,10 +100,35 @@ abstract class DefaultVideo extends DefaultAudio implements VideoInterface | ||||||
|     /** |     /** | ||||||
|      * {@inheritdoc} |      * {@inheritdoc} | ||||||
|      */ |      */ | ||||||
|     public function createProgressListener(MediaTypeInterface $media, FFProbe $ffprobe, $pass, $total) |     public function getAdditionalParameters() | ||||||
|  |     { | ||||||
|  |         return $this->additionalParamaters; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Sets additional parameters. | ||||||
|  |      * | ||||||
|  |      * @param  array                    $additionalParamaters | ||||||
|  |      * @throws InvalidArgumentException | ||||||
|  |      */ | ||||||
|  |     public function setAdditionalParameters($additionalParamaters) | ||||||
|  |     { | ||||||
|  |         if (!is_array($additionalParamaters)) { | ||||||
|  |             throw new InvalidArgumentException('Wrong additionalParamaters value'); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         $this->additionalParamaters = $additionalParamaters; | ||||||
|  | 
 | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * {@inheritdoc} | ||||||
|  |      */ | ||||||
|  |     public function createProgressListener(MediaTypeInterface $media, FFProbe $ffprobe, $pass, $total, $duration = 0) | ||||||
|     { |     { | ||||||
|         $format = $this; |         $format = $this; | ||||||
|         $listeners = array(new VideoProgressListener($ffprobe, $media->getPathfile(), $pass, $total)); |         $listeners = array(new VideoProgressListener($ffprobe, $media->getPathfile(), $pass, $total, $duration)); | ||||||
| 
 | 
 | ||||||
|         foreach ($listeners as $listener) { |         foreach ($listeners as $listener) { | ||||||
|             $listener->on('progress', function () use ($format, $media) { |             $listener->on('progress', function () use ($format, $media) { | ||||||
|  |  | ||||||
|  | @ -52,6 +52,6 @@ class WebM extends DefaultVideo | ||||||
|      */ |      */ | ||||||
|     public function getAvailableVideoCodecs() |     public function getAvailableVideoCodecs() | ||||||
|     { |     { | ||||||
|         return array('libvpx'); |         return array('libvpx', 'libvpx-vp9'); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -19,6 +19,9 @@ class X264 extends DefaultVideo | ||||||
|     /** @var boolean */ |     /** @var boolean */ | ||||||
|     private $bframesSupport = true; |     private $bframesSupport = true; | ||||||
| 
 | 
 | ||||||
|  |     /** @var integer */ | ||||||
|  |     private $passes = 2; | ||||||
|  | 
 | ||||||
|     public function __construct($audioCodec = 'libfaac', $videoCodec = 'libx264') |     public function __construct($audioCodec = 'libfaac', $videoCodec = 'libx264') | ||||||
|     { |     { | ||||||
|         $this |         $this | ||||||
|  | @ -51,7 +54,7 @@ class X264 extends DefaultVideo | ||||||
|      */ |      */ | ||||||
|     public function getAvailableAudioCodecs() |     public function getAvailableAudioCodecs() | ||||||
|     { |     { | ||||||
|         return array('libvo_aacenc', 'libfaac', 'libmp3lame', 'libfdk_aac'); |         return array('aac', 'libvo_aacenc', 'libfaac', 'libmp3lame', 'libfdk_aac'); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -62,12 +65,23 @@ class X264 extends DefaultVideo | ||||||
|         return array('libx264'); |         return array('libx264'); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * @param $passes | ||||||
|  |      * | ||||||
|  |      * @return X264 | ||||||
|  |      */ | ||||||
|  |     public function setPasses($passes) | ||||||
|  |     { | ||||||
|  |         $this->passes = $passes; | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * {@inheritDoc} |      * {@inheritDoc} | ||||||
|      */ |      */ | ||||||
|     public function getPasses() |     public function getPasses() | ||||||
|     { |     { | ||||||
|         return 2; |         return $this->passes; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  |  | ||||||
|  | @ -54,4 +54,11 @@ interface VideoInterface extends AudioInterface | ||||||
|      * @return array |      * @return array | ||||||
|      */ |      */ | ||||||
|     public function getAvailableVideoCodecs(); |     public function getAvailableVideoCodecs(); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the list of available video codecs for this format. | ||||||
|  |      * | ||||||
|  |      * @return array | ||||||
|  |      */ | ||||||
|  |     public function getAdditionalParameters(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -52,11 +52,9 @@ class Audio extends AbstractStreamableMedia | ||||||
|     /** |     /** | ||||||
|      * Exports the audio in the desired format, applies registered filters. |      * Exports the audio in the desired format, applies registered filters. | ||||||
|      * |      * | ||||||
|      * @param FormatInterface $format |      * @param FormatInterface   $format | ||||||
|      * @param string          $outputPathfile |      * @param string            $outputPathfile | ||||||
|      * |  | ||||||
|      * @return Audio |      * @return Audio | ||||||
|      * |  | ||||||
|      * @throws RuntimeException |      * @throws RuntimeException | ||||||
|      */ |      */ | ||||||
|     public function save(FormatInterface $format, $outputPathfile) |     public function save(FormatInterface $format, $outputPathfile) | ||||||
|  | @ -64,9 +62,42 @@ class Audio extends AbstractStreamableMedia | ||||||
|         $listeners = null; |         $listeners = null; | ||||||
| 
 | 
 | ||||||
|         if ($format instanceof ProgressableInterface) { |         if ($format instanceof ProgressableInterface) { | ||||||
|             $listeners = $format->createProgressListener($this, $this->ffprobe, 1, 1); |             $listeners = $format->createProgressListener($this, $this->ffprobe, 1, 1, 0); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         $commands = $this->buildCommand($format, $outputPathfile); | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             $this->driver->command($commands, false, $listeners); | ||||||
|  |         } catch (ExecutionFailureException $e) { | ||||||
|  |             $this->cleanupTemporaryFile($outputPathfile); | ||||||
|  |             throw new RuntimeException('Encoding failed', $e->getCode(), $e); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the final command as a string, useful for debugging purposes. | ||||||
|  |      * | ||||||
|  |      * @param FormatInterface   $format | ||||||
|  |      * @param string            $outputPathfile | ||||||
|  |      * @return string | ||||||
|  |      * @since 0.11.0 | ||||||
|  |      */ | ||||||
|  |     public function getFinalCommand(FormatInterface $format, $outputPathfile) { | ||||||
|  |         return implode(' ', $this->buildCommand($format, $outputPathfile)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Builds the command which will be executed with the provided format | ||||||
|  |      * | ||||||
|  |      * @param FormatInterface   $format | ||||||
|  |      * @param string            $outputPathfile | ||||||
|  |      * @return string[] An array which are the components of the command | ||||||
|  |      * @since 0.11.0 | ||||||
|  |      */ | ||||||
|  |     protected function buildCommand(FormatInterface $format, $outputPathfile) { | ||||||
|         $commands = array('-y', '-i', $this->pathfile); |         $commands = array('-y', '-i', $this->pathfile); | ||||||
| 
 | 
 | ||||||
|         $filters = clone $this->filters; |         $filters = clone $this->filters; | ||||||
|  | @ -93,13 +124,19 @@ class Audio extends AbstractStreamableMedia | ||||||
|         } |         } | ||||||
|         $commands[] = $outputPathfile; |         $commands[] = $outputPathfile; | ||||||
| 
 | 
 | ||||||
|         try { |         return $commands; | ||||||
|             $this->driver->command($commands, false, $listeners); |     } | ||||||
|         } catch (ExecutionFailureException $e) { |  | ||||||
|             $this->cleanupTemporaryFile($outputPathfile); |  | ||||||
|             throw new RuntimeException('Encoding failed', $e->getCode(), $e); |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         return $this; |     /** | ||||||
|  |      * Gets the waveform of the video. | ||||||
|  |      * | ||||||
|  |      * @param  integer $width | ||||||
|  |      * @param  integer $height | ||||||
|  |      * @param array $colors Array of colors for ffmpeg to use. Color format is #000000 (RGB hex string with #)
 | ||||||
|  |      * @return Waveform | ||||||
|  |      */ | ||||||
|  |     public function waveform($width = 640, $height = 120, $colors = array(Waveform::DEFAULT_COLOR)) | ||||||
|  |     { | ||||||
|  |         return new Waveform($this, $this->driver, $this->ffprobe, $width, $height, $colors); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										264
									
								
								src/FFMpeg/Media/Concat.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										264
									
								
								src/FFMpeg/Media/Concat.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,264 @@ | ||||||
|  | <?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\Media; | ||||||
|  | 
 | ||||||
|  | use Alchemy\BinaryDriver\Exception\ExecutionFailureException; | ||||||
|  | use Alchemy\BinaryDriver\Exception\InvalidArgumentException; | ||||||
|  | use FFMpeg\Filters\Concat\ConcatFilterInterface; | ||||||
|  | use FFMpeg\Filters\Concat\ConcatFilters; | ||||||
|  | use FFMpeg\Driver\FFMpegDriver; | ||||||
|  | use FFMpeg\FFProbe; | ||||||
|  | use FFMpeg\Filters\Audio\SimpleFilter; | ||||||
|  | use FFMpeg\Exception\RuntimeException; | ||||||
|  | use FFMpeg\Format\FormatInterface; | ||||||
|  | use FFMpeg\Filters\FilterInterface; | ||||||
|  | use FFMpeg\Format\ProgressableInterface; | ||||||
|  | use FFMpeg\Format\AudioInterface; | ||||||
|  | use FFMpeg\Format\VideoInterface; | ||||||
|  | use Neutron\TemporaryFilesystem\Manager as FsManager; | ||||||
|  | 
 | ||||||
|  | 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 array   $outputPathfile | ||||||
|  |      * @param string  $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 = FsManager::create(); | ||||||
|  |         $sourcesFile = $fs->createTemporaryFile('ffmpeg-concat'); | ||||||
|  | 
 | ||||||
|  |         // Set the content of this file
 | ||||||
|  |         $fileStream = @fopen($sourcesFile, 'w'); | ||||||
|  | 
 | ||||||
|  |         if($fileStream === false) { | ||||||
|  |             throw new ExecutionFailureException('Cannot open the temporary file.'); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         $count_videos = 0; | ||||||
|  |         if(is_array($this->sources) && (count($this->sources) > 0)) { | ||||||
|  |             foreach ($this->sources as $videoPath) { | ||||||
|  |                 $line = ""; | ||||||
|  | 
 | ||||||
|  |                 if($count_videos != 0) | ||||||
|  |                     $line .= "\n"; | ||||||
|  | 
 | ||||||
|  |                 $line .= "file ".$videoPath; | ||||||
|  | 
 | ||||||
|  |                 fwrite($fileStream, $line); | ||||||
|  | 
 | ||||||
|  |                 $count_videos++; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             throw new InvalidArgumentException('The list of videos is not a valid array.'); | ||||||
|  |         } | ||||||
|  |         fclose($fileStream); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         $commands = array( | ||||||
|  |             '-f', 'concat', '-safe', '0', | ||||||
|  |             '-i', $sourcesFile | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         // Check if stream copy is activated
 | ||||||
|  |         if($streamCopy === TRUE) { | ||||||
|  |             $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, array($outputPathfile)); | ||||||
|  | 
 | ||||||
|  |         // Execute the command
 | ||||||
|  |         try { | ||||||
|  |             $this->driver->command($commands); | ||||||
|  |         } catch (ExecutionFailureException $e) { | ||||||
|  |             $this->cleanupTemporaryFile($outputPathfile); | ||||||
|  |             $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 | ||||||
|  |      * | ||||||
|  |      * @throws RuntimeException | ||||||
|  |      */ | ||||||
|  |     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) || (count($this->sources) == 0)) { | ||||||
|  |             throw new InvalidArgumentException('The list of videos is not a valid array.'); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Create the commands variable
 | ||||||
|  |         $commands = array(); | ||||||
|  | 
 | ||||||
|  |         // Prepare the parameters
 | ||||||
|  |         $nbSources = 0; | ||||||
|  |         $files = array(); | ||||||
|  | 
 | ||||||
|  |         // 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(array('-threads', $this->driver->getConfiguration()->get('ffmpeg.threads')))); | ||||||
|  |         } | ||||||
|  |         if ($format instanceof VideoInterface) { | ||||||
|  |             if (null !== $format->getVideoCodec()) { | ||||||
|  |                 $filters->add(new SimpleFilter(array('-vcodec', $format->getVideoCodec()))); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if ($format instanceof AudioInterface) { | ||||||
|  |             if (null !== $format->getAudioCodec()) { | ||||||
|  |                 $filters->add(new SimpleFilter(array('-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; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -85,27 +85,32 @@ class Frame extends AbstractMediaType | ||||||
|      * |      * | ||||||
|      * @throws RuntimeException |      * @throws RuntimeException | ||||||
|      */ |      */ | ||||||
|     public function save($pathfile, $accurate = false) |     public function save($pathfile, $accurate = false, $returnBase64 = false) | ||||||
|     { |     { | ||||||
|         /** |         /** | ||||||
|          * might be optimized with http://ffmpeg.org/trac/ffmpeg/wiki/Seeking%20with%20FFmpeg |          * might be optimized with http://ffmpeg.org/trac/ffmpeg/wiki/Seeking%20with%20FFmpeg | ||||||
|          * @see http://ffmpeg.org/ffmpeg.html#Main-options
 |          * @see http://ffmpeg.org/ffmpeg.html#Main-options
 | ||||||
|          */ |          */ | ||||||
|  |         $outputFormat = $returnBase64 ? "image2pipe" : "image2"; | ||||||
|         if (!$accurate) { |         if (!$accurate) { | ||||||
|             $commands = array( |             $commands = array( | ||||||
|                 '-y', '-ss', (string) $this->timecode, |                 '-y', '-ss', (string) $this->timecode, | ||||||
|                 '-i', $this->pathfile, |                 '-i', $this->pathfile, | ||||||
|                 '-vframes', '1', |                 '-vframes', '1', | ||||||
|                 '-f', 'image2' |                 '-f', $outputFormat | ||||||
|             ); |             ); | ||||||
|         } else { |         } else { | ||||||
|             $commands = array( |             $commands = array( | ||||||
|                 '-y', '-i', $this->pathfile, |                 '-y', '-i', $this->pathfile, | ||||||
|                 '-vframes', '1', '-ss', (string) $this->timecode, |                 '-vframes', '1', '-ss', (string) $this->timecode, | ||||||
|                 '-f', 'image2' |                 '-f', $outputFormat | ||||||
|             ); |             ); | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         if($returnBase64) { | ||||||
|  |             array_push($commands, "-"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         foreach ($this->filters as $filter) { |         foreach ($this->filters as $filter) { | ||||||
|             $commands = array_merge($commands, $filter->apply($this)); |             $commands = array_merge($commands, $filter->apply($this)); | ||||||
|         } |         } | ||||||
|  | @ -113,12 +118,16 @@ class Frame extends AbstractMediaType | ||||||
|         $commands = array_merge($commands, array($pathfile)); |         $commands = array_merge($commands, array($pathfile)); | ||||||
| 
 | 
 | ||||||
|         try { |         try { | ||||||
|             $this->driver->command($commands); |             if(!$returnBase64) { | ||||||
|  |                 $this->driver->command($commands); | ||||||
|  |                 return $this; | ||||||
|  |             } | ||||||
|  |             else { | ||||||
|  |                 return $this->driver->command($commands); | ||||||
|  |             } | ||||||
|         } catch (ExecutionFailureException $e) { |         } catch (ExecutionFailureException $e) { | ||||||
|             $this->cleanupTemporaryFile($pathfile); |             $this->cleanupTemporaryFile($pathfile); | ||||||
|             throw new RuntimeException('Unable to save frame', $e->getCode(), $e); |             throw new RuntimeException('Unable to save frame', $e->getCode(), $e); | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         return $this; |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										137
									
								
								src/FFMpeg/Media/Gif.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								src/FFMpeg/Media/Gif.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,137 @@ | ||||||
|  | <?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\Media; | ||||||
|  | 
 | ||||||
|  | use Alchemy\BinaryDriver\Exception\ExecutionFailureException; | ||||||
|  | use FFMpeg\Filters\Gif\GifFilterInterface; | ||||||
|  | use FFMpeg\Filters\Gif\GifFilters; | ||||||
|  | use FFMpeg\Driver\FFMpegDriver; | ||||||
|  | use FFMpeg\FFProbe; | ||||||
|  | use FFMpeg\Exception\RuntimeException; | ||||||
|  | use FFMpeg\Coordinate\TimeCode; | ||||||
|  | use FFMpeg\Coordinate\Dimension; | ||||||
|  | 
 | ||||||
|  | class Gif extends AbstractMediaType | ||||||
|  | { | ||||||
|  |     /** @var TimeCode */ | ||||||
|  |     private $timecode; | ||||||
|  |     /** @var Dimension */ | ||||||
|  |     private $dimension; | ||||||
|  |     /** @var integer */ | ||||||
|  |     private $duration; | ||||||
|  |     /** @var Video */ | ||||||
|  |     private $video; | ||||||
|  | 
 | ||||||
|  |     public function __construct(Video $video, FFMpegDriver $driver, FFProbe $ffprobe, TimeCode $timecode, Dimension $dimension, $duration = null) | ||||||
|  |     { | ||||||
|  |         parent::__construct($video->getPathfile(), $driver, $ffprobe); | ||||||
|  |         $this->timecode = $timecode; | ||||||
|  |         $this->dimension = $dimension; | ||||||
|  |         $this->duration = $duration; | ||||||
|  |         $this->video = $video; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns the video related to the gif. | ||||||
|  |      * | ||||||
|  |      * @return Video | ||||||
|  |      */ | ||||||
|  |     public function getVideo() | ||||||
|  |     { | ||||||
|  |         return $this->video; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * {@inheritdoc} | ||||||
|  |      * | ||||||
|  |      * @return GifFilters | ||||||
|  |      */ | ||||||
|  |     public function filters() | ||||||
|  |     { | ||||||
|  |         return new GifFilters($this); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * {@inheritdoc} | ||||||
|  |      * | ||||||
|  |      * @return Gif | ||||||
|  |      */ | ||||||
|  |     public function addFilter(GifFilterInterface $filter) | ||||||
|  |     { | ||||||
|  |         $this->filters->add($filter); | ||||||
|  | 
 | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @return TimeCode | ||||||
|  |      */ | ||||||
|  |     public function getTimeCode() | ||||||
|  |     { | ||||||
|  |         return $this->timecode; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @return Dimension | ||||||
|  |      */ | ||||||
|  |     public function getDimension() | ||||||
|  |     { | ||||||
|  |         return $this->dimension; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Saves the gif in the given filename. | ||||||
|  |      * | ||||||
|  |      * @param string  $pathfile | ||||||
|  |      * | ||||||
|  |      * @return Gif | ||||||
|  |      * | ||||||
|  |      * @throws RuntimeException | ||||||
|  |      */ | ||||||
|  |     public function save($pathfile) | ||||||
|  |     { | ||||||
|  |         /** | ||||||
|  |          * @see http://ffmpeg.org/ffmpeg.html#Main-options
 | ||||||
|  |          */ | ||||||
|  |         $commands = array( | ||||||
|  |             '-ss', (string)$this->timecode | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         if(null !== $this->duration) { | ||||||
|  |             $commands[] = '-t'; | ||||||
|  |             $commands[] = (string)$this->duration; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         $commands[] = '-i'; | ||||||
|  |         $commands[] = $this->pathfile; | ||||||
|  |         $commands[] = '-vf'; | ||||||
|  |         $commands[] = 'scale=' . $this->dimension->getWidth() . ':-1'; | ||||||
|  |         $commands[] = '-gifflags'; | ||||||
|  |         $commands[] = '+transdiff'; | ||||||
|  |         $commands[] = '-y'; | ||||||
|  | 
 | ||||||
|  |         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 gif', $e->getCode(), $e); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -13,6 +13,7 @@ namespace FFMpeg\Media; | ||||||
| 
 | 
 | ||||||
| use Alchemy\BinaryDriver\Exception\ExecutionFailureException; | use Alchemy\BinaryDriver\Exception\ExecutionFailureException; | ||||||
| use FFMpeg\Coordinate\TimeCode; | use FFMpeg\Coordinate\TimeCode; | ||||||
|  | use FFMpeg\Coordinate\Dimension; | ||||||
| use FFMpeg\Filters\Audio\SimpleFilter; | use FFMpeg\Filters\Audio\SimpleFilter; | ||||||
| use FFMpeg\Exception\InvalidArgumentException; | use FFMpeg\Exception\InvalidArgumentException; | ||||||
| use FFMpeg\Exception\RuntimeException; | use FFMpeg\Exception\RuntimeException; | ||||||
|  | @ -23,12 +24,24 @@ use FFMpeg\Format\ProgressableInterface; | ||||||
| use FFMpeg\Format\AudioInterface; | use FFMpeg\Format\AudioInterface; | ||||||
| use FFMpeg\Format\VideoInterface; | use FFMpeg\Format\VideoInterface; | ||||||
| use Neutron\TemporaryFilesystem\Manager as FsManager; | use Neutron\TemporaryFilesystem\Manager as FsManager; | ||||||
|  | use FFMpeg\Filters\Video\ClipFilter; | ||||||
| 
 | 
 | ||||||
| class Video extends Audio | class Video extends Audio | ||||||
| { | { | ||||||
|     /** |     /** | ||||||
|      * {@inheritdoc} |      * FileSystem Manager instance | ||||||
|      * |      * @var Manager | ||||||
|  |      */ | ||||||
|  |     protected $fs; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * FileSystem Manager ID | ||||||
|  |      * @var int | ||||||
|  |      */ | ||||||
|  |     protected $fsId; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @inheritDoc | ||||||
|      * @return VideoFilters |      * @return VideoFilters | ||||||
|      */ |      */ | ||||||
|     public function filters() |     public function filters() | ||||||
|  | @ -37,8 +50,7 @@ class Video extends Audio | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * {@inheritdoc} |      * @inheritDoc | ||||||
|      * |  | ||||||
|      * @return Video |      * @return Video | ||||||
|      */ |      */ | ||||||
|     public function addFilter(FilterInterface $filter) |     public function addFilter(FilterInterface $filter) | ||||||
|  | @ -51,15 +63,78 @@ class Video extends Audio | ||||||
|     /** |     /** | ||||||
|      * Exports the video in the desired format, applies registered filters. |      * Exports the video in the desired format, applies registered filters. | ||||||
|      * |      * | ||||||
|      * @param FormatInterface $format |      * @param FormatInterface   $format | ||||||
|      * @param string          $outputPathfile |      * @param string            $outputPathfile | ||||||
|      * |  | ||||||
|      * @return Video |      * @return Video | ||||||
|      * |  | ||||||
|      * @throws RuntimeException |      * @throws RuntimeException | ||||||
|      */ |      */ | ||||||
|     public function save(FormatInterface $format, $outputPathfile) |     public function save(FormatInterface $format, $outputPathfile) | ||||||
|     { |     { | ||||||
|  |         $passes = $this->buildCommand($format, $outputPathfile); | ||||||
|  | 
 | ||||||
|  |         $failure = null; | ||||||
|  |         $totalPasses = $format->getPasses(); | ||||||
|  | 
 | ||||||
|  |         foreach ($passes as $pass => $passCommands) { | ||||||
|  |             try { | ||||||
|  |                 /** add listeners here */ | ||||||
|  |                 $listeners = null; | ||||||
|  |          | ||||||
|  |                 if ($format instanceof ProgressableInterface) { | ||||||
|  |                     $filters = clone $this->filters; | ||||||
|  |                     $duration = 0; | ||||||
|  |                      | ||||||
|  |                     // 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
 | ||||||
|  |                     foreach ($filters as $filter) { | ||||||
|  |                         if($filter instanceof ClipFilter){ | ||||||
|  |                             $duration = $filter->getDuration()->toSeconds(); | ||||||
|  |                             break; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     $listeners = $format->createProgressListener($this, $this->ffprobe, $pass + 1, $totalPasses, $duration); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 $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 | ||||||
|  |      */ | ||||||
|  |     public function getFinalCommand(FormatInterface $format, $outputPathfile) { | ||||||
|  |         $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[][] | ||||||
|  |      */ | ||||||
|  |     protected function buildCommand(FormatInterface $format, $outputPathfile) { | ||||||
|         $commands = array('-y', '-i', $this->pathfile); |         $commands = array('-y', '-i', $this->pathfile); | ||||||
| 
 | 
 | ||||||
|         $filters = clone $this->filters; |         $filters = clone $this->filters; | ||||||
|  | @ -119,17 +194,76 @@ class Video extends Audio | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         $fs = FsManager::create(); |         // If the user passed some additional parameters
 | ||||||
|         $fsId = uniqid('ffmpeg-passes'); |         if ($format instanceof VideoInterface) { | ||||||
|         $passPrefix = $fs->createTemporaryDirectory(0777, 50, $fsId) . '/' . uniqid('pass-'); |             if (null !== $format->getAdditionalParameters()) { | ||||||
|  |                 foreach ($format->getAdditionalParameters() as $additionalParameter) { | ||||||
|  |                     $commands[] = $additionalParameter; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Merge Filters into one command
 | ||||||
|  |         $videoFilterVars = $videoFilterProcesses = array(); | ||||||
|  |         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 { | ||||||
|  |                         $videoFilterProcesses[] = $command; | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     foreach($commandSplits as $commandSplit) { | ||||||
|  |                         $command = trim($commandSplit); | ||||||
|  |                         if ( preg_match("/^\[[^\]]+\](.*?)\[[^\]]+\]$/is", $command, $match) ) { | ||||||
|  |                             $videoFilterProcesses[] = $match[1]; | ||||||
|  |                         } else { | ||||||
|  |                             $videoFilterVars[] = $command; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 unset($commands[$i]); | ||||||
|  |                 unset($commands[$i + 1]); | ||||||
|  |                 $i++; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         $videoFilterCommands = $videoFilterVars; | ||||||
|  |         $lastInput = 'in'; | ||||||
|  |         foreach($videoFilterProcesses as $i => $process) { | ||||||
|  |             $command = '[' . $lastInput .']'; | ||||||
|  |             $command .= $process; | ||||||
|  |             $lastInput = 'p' . $i; | ||||||
|  |             if($i === (count($videoFilterProcesses) - 1)) { | ||||||
|  |                 $command .= '[out]'; | ||||||
|  |             } else { | ||||||
|  |                 $command .= '[' . $lastInput . ']'; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             $videoFilterCommands[] = $command; | ||||||
|  |         } | ||||||
|  |         $videoFilterCommand = implode(';', $videoFilterCommands); | ||||||
|  | 
 | ||||||
|  |         if($videoFilterCommand) { | ||||||
|  |             $commands[] = '-vf'; | ||||||
|  |             $commands[] = $videoFilterCommand; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         $this->fs = FsManager::create(); | ||||||
|  |         $this->fsId = uniqid('ffmpeg-passes'); | ||||||
|  |         $passPrefix = $this->fs->createTemporaryDirectory(0777, 50, $this->fsId) . '/' . uniqid('pass-'); | ||||||
|         $passes = array(); |         $passes = array(); | ||||||
|         $totalPasses = $format->getPasses(); |         $totalPasses = $format->getPasses(); | ||||||
| 
 | 
 | ||||||
|         if (1 > $totalPasses) { |         if(!$totalPasses) { | ||||||
|             throw new InvalidArgumentException('Pass number should be a positive value.'); |             throw new InvalidArgumentException('Pass number should be a positive value.'); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         for ($i = 1; $i <= $totalPasses; $i++) { |         for($i = 1; $i <= $totalPasses; $i++) { | ||||||
|             $pass = $commands; |             $pass = $commands; | ||||||
| 
 | 
 | ||||||
|             if ($totalPasses > 1) { |             if ($totalPasses > 1) { | ||||||
|  | @ -144,31 +278,7 @@ class Video extends Audio | ||||||
|             $passes[] = $pass; |             $passes[] = $pass; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         $failure = null; |         return $passes; | ||||||
| 
 |  | ||||||
|         foreach ($passes as $pass => $passCommands) { |  | ||||||
|             try { |  | ||||||
|                 /** add listeners here */ |  | ||||||
|                 $listeners = null; |  | ||||||
| 
 |  | ||||||
|                 if ($format instanceof ProgressableInterface) { |  | ||||||
|                     $listeners = $format->createProgressListener($this, $this->ffprobe, $pass + 1, $totalPasses); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 $this->driver->command($passCommands, false, $listeners); |  | ||||||
|             } catch (ExecutionFailureException $e) { |  | ||||||
|                 $failure = $e; |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         $fs->clean($fsId); |  | ||||||
| 
 |  | ||||||
|         if (null !== $failure) { |  | ||||||
|             throw new RuntimeException('Encoding failed', $failure->getCode(), $failure); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         return $this; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -181,4 +291,28 @@ class Video extends Audio | ||||||
|     { |     { | ||||||
|         return new Frame($this, $this->driver, $this->ffprobe, $at); |         return new Frame($this, $this->driver, $this->ffprobe, $at); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 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); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Concatenates a list of videos into one unique video. | ||||||
|  |      * | ||||||
|  |      * @param  array $sources | ||||||
|  |      * @return Concat | ||||||
|  |      */ | ||||||
|  |     public function concat($sources) | ||||||
|  |     { | ||||||
|  |         return new Concat($sources, $this->driver, $this->ffprobe); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										163
									
								
								src/FFMpeg/Media/Waveform.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								src/FFMpeg/Media/Waveform.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,163 @@ | ||||||
|  | <?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\Exception\InvalidArgumentException; | ||||||
|  | use FFMpeg\Filters\Waveform\WaveformFilterInterface; | ||||||
|  | use FFMpeg\Filters\Waveform\WaveformFilters; | ||||||
|  | use FFMpeg\Driver\FFMpegDriver; | ||||||
|  | use FFMpeg\FFProbe; | ||||||
|  | use FFMpeg\Exception\RuntimeException; | ||||||
|  | 
 | ||||||
|  | class Waveform extends AbstractMediaType | ||||||
|  | { | ||||||
|  |     const DEFAULT_COLOR = '#000000'; | ||||||
|  | 
 | ||||||
|  |     /** @var Video */ | ||||||
|  |     protected $audio; | ||||||
|  |     protected $width; | ||||||
|  |     protected $height; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @var array | ||||||
|  |      */ | ||||||
|  |     protected $colors; | ||||||
|  | 
 | ||||||
|  |     public function __construct(Audio $audio, FFMpegDriver $driver, FFProbe $ffprobe, $width, $height, $colors = array(self::DEFAULT_COLOR)) | ||||||
|  |     { | ||||||
|  |         parent::__construct($audio->getPathfile(), $driver, $ffprobe); | ||||||
|  |         $this->audio = $audio; | ||||||
|  |         $this->width = $width; | ||||||
|  |         $this->height = $height; | ||||||
|  | 
 | ||||||
|  |         $this->setColors($colors); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 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; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Parameter should be an array containing at least one valid color represented as a HTML color string. For | ||||||
|  |      * example #FFFFFF or #000000. By default the color is set to black. Keep in mind that if you save the waveform
 | ||||||
|  |      * as jpg file, it will appear completely black and to avoid this you can set the waveform color to white (#FFFFFF).
 | ||||||
|  |      * Saving waveforms to png is strongly suggested. | ||||||
|  |      * | ||||||
|  |      * @param array $colors | ||||||
|  |      */ | ||||||
|  |     public function setColors(array $colors) | ||||||
|  |     { | ||||||
|  |         foreach ($colors as $row => $value) | ||||||
|  |         { | ||||||
|  |             if (!preg_match('/^#(?:[0-9a-fA-F]{6})$/', $value)) | ||||||
|  |             { | ||||||
|  |                 //invalid color
 | ||||||
|  |                 //unset($colors[$row]);
 | ||||||
|  | 
 | ||||||
|  |                 throw new InvalidArgumentException("The provided color '$value' is invalid"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (count($colors)) | ||||||
|  |         { | ||||||
|  |             $this->colors = $colors; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns an array of colors that will be passed to ffmpeg to use for waveform generation. Colors are applied ONLY | ||||||
|  |      * to the waveform. Background cannot be controlled that easily and it is probably easier to save the waveform | ||||||
|  |      * as a transparent png file and then add background of choice. | ||||||
|  |      * | ||||||
|  |      * @return array | ||||||
|  |      */ | ||||||
|  |     public function getColors() | ||||||
|  |     { | ||||||
|  |         return $this->colors; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Compiles the selected colors into a string, using a pipe separator. | ||||||
|  |      * | ||||||
|  |      * @return string | ||||||
|  |      */ | ||||||
|  |     protected function compileColors() | ||||||
|  |     { | ||||||
|  |         return implode('|', $this->colors); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 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( | ||||||
|  |             '-y', '-i', $this->pathfile, '-filter_complex', | ||||||
|  |             'showwavespic=colors='.$this->compileColors().':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; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,16 +0,0 @@ | ||||||
| <?php |  | ||||||
| 
 |  | ||||||
| namespace FFMpeg\Tests\Coordinate; |  | ||||||
| 
 |  | ||||||
| use FFMpeg\Tests\TestCase; |  | ||||||
| use FFMpeg\Coordinate\Point; |  | ||||||
| 
 |  | ||||||
| class PointTest extends TestCase |  | ||||||
| { |  | ||||||
|     public function testGetters() |  | ||||||
|     { |  | ||||||
|         $point = new Point(4, 25); |  | ||||||
|         $this->assertEquals(4, $point->getX()); |  | ||||||
|         $this->assertEquals(25, $point->getY()); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Functional; | namespace Tests\FFMpeg\Functional; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\FFProbe; | use FFMpeg\FFProbe; | ||||||
| 
 | 
 | ||||||
|  | @ -9,13 +9,26 @@ class FFProbeTest extends FunctionalTestCase | ||||||
|     public function testProbeOnFile() |     public function testProbeOnFile() | ||||||
|     { |     { | ||||||
|         $ffprobe = FFProbe::create(); |         $ffprobe = FFProbe::create(); | ||||||
|         $this->assertGreaterThan(0, count($ffprobe->streams(__DIR__ . '/../../files/Audio.mp3'))); |         $this->assertGreaterThan(0, count($ffprobe->streams(__DIR__ . '/../files/Audio.mp3'))); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function testValidateExistingFile() | ||||||
|  |     { | ||||||
|  |         $ffprobe = FFProbe::create(); | ||||||
|  |         $this->assertTrue($ffprobe->isValid(__DIR__ . '/../files/sample.3gp')); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     public function testValidateNonExistingFile() | ||||||
|  |     { | ||||||
|  |         $ffprobe = FFProbe::create(); | ||||||
|  |         $this->assertFalse($ffprobe->isValid(__DIR__ . '/../files/WrongFile.mp4')); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * @expectedException FFMpeg\Exception\RuntimeException |      * @expectedException FFMpeg\Exception\RuntimeException | ||||||
|      */ |      */ | ||||||
|     public function testProbeOnUnexistantFile() |     public function testProbeOnNonExistantFile() | ||||||
|     { |     { | ||||||
|         $ffprobe = FFProbe::create(); |         $ffprobe = FFProbe::create(); | ||||||
|         $ffprobe->streams('/path/to/no/file'); |         $ffprobe->streams('/path/to/no/file'); | ||||||
|  | @ -24,6 +37,6 @@ class FFProbeTest extends FunctionalTestCase | ||||||
|     public function testProbeOnRemoteFile() |     public function testProbeOnRemoteFile() | ||||||
|     { |     { | ||||||
|         $ffprobe = FFProbe::create(); |         $ffprobe = FFProbe::create(); | ||||||
|         $this->assertGreaterThan(0, count($ffprobe->streams('http://video-js.zencoder.com/oceans-clip.mp4'))); |         $this->assertGreaterThan(0, count($ffprobe->streams('http://vjs.zencdn.net/v/oceans.mp4'))); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -1,10 +1,11 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Functional; | namespace Tests\FFMpeg\Functional; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\FFMpeg; | use FFMpeg\FFMpeg; | ||||||
|  | use PHPUnit\Framework\TestCase; | ||||||
| 
 | 
 | ||||||
| abstract class FunctionalTestCase extends \PHPUnit_Framework_TestCase | abstract class FunctionalTestCase extends TestCase | ||||||
| { | { | ||||||
|     /** |     /** | ||||||
|      * @return FFMpeg |      * @return FFMpeg | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Functional; | namespace Tests\FFMpeg\Functional; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Coordinate\Dimension; | use FFMpeg\Coordinate\Dimension; | ||||||
| use FFMpeg\Filters\Video\ResizeFilter; | use FFMpeg\Filters\Video\ResizeFilter; | ||||||
|  | @ -18,14 +18,44 @@ class VideoTranscodeTest extends FunctionalTestCase | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         $ffmpeg = $this->getFFMpeg(); |         $ffmpeg = $this->getFFMpeg(); | ||||||
|         $video = $ffmpeg->open(__DIR__ . '/../../files/Test.ogv'); |         $video = $ffmpeg->open(__DIR__ . '/../files/Test.ogv'); | ||||||
| 
 | 
 | ||||||
|         $this->assertInstanceOf('FFMpeg\Media\Video', $video); |         $this->assertInstanceOf('FFMpeg\Media\Video', $video); | ||||||
| 
 | 
 | ||||||
|         $lastPercentage = null; |         $lastPercentage = null; | ||||||
|         $phpunit = $this; |         $phpunit = $this; | ||||||
| 
 | 
 | ||||||
|         $codec = new X264('libvo_aacenc'); |         $codec = new X264('aac'); | ||||||
|  |         $codec->on('progress', function ($video, $codec, $percentage) use ($phpunit, &$lastPercentage) { | ||||||
|  |             if (null !== $lastPercentage) { | ||||||
|  |                 $phpunit->assertGreaterThanOrEqual($lastPercentage, $percentage); | ||||||
|  |             } | ||||||
|  |             $lastPercentage = $percentage; | ||||||
|  |             $phpunit->assertGreaterThanOrEqual(0, $percentage); | ||||||
|  |             $phpunit->assertLessThanOrEqual(100, $percentage); | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         $video->save($codec, $filename); | ||||||
|  |         $this->assertFileExists($filename); | ||||||
|  |         unlink($filename); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function testAacTranscodeX264() | ||||||
|  |     { | ||||||
|  |         $filename = __DIR__ . '/output/output-x264_2.mp4'; | ||||||
|  |         if (is_file($filename)) { | ||||||
|  |             unlink(__DIR__ . '/output/output-x264_2.mp4'); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         $ffmpeg = $this->getFFMpeg(); | ||||||
|  |         $video = $ffmpeg->open(__DIR__ . '/../files/sample.3gp'); | ||||||
|  | 
 | ||||||
|  |         $this->assertInstanceOf('FFMpeg\Media\Video', $video); | ||||||
|  | 
 | ||||||
|  |         $lastPercentage = null; | ||||||
|  |         $phpunit = $this; | ||||||
|  | 
 | ||||||
|  |         $codec = new X264('aac'); | ||||||
|         $codec->on('progress', function ($video, $codec, $percentage) use ($phpunit, &$lastPercentage) { |         $codec->on('progress', function ($video, $codec, $percentage) use ($phpunit, &$lastPercentage) { | ||||||
|             if (null !== $lastPercentage) { |             if (null !== $lastPercentage) { | ||||||
|                 $phpunit->assertGreaterThanOrEqual($lastPercentage, $percentage); |                 $phpunit->assertGreaterThanOrEqual($lastPercentage, $percentage); | ||||||
|  | @ -46,16 +76,16 @@ class VideoTranscodeTest extends FunctionalTestCase | ||||||
|     public function testTranscodeInvalidFile() |     public function testTranscodeInvalidFile() | ||||||
|     { |     { | ||||||
|         $ffmpeg = $this->getFFMpeg(); |         $ffmpeg = $this->getFFMpeg(); | ||||||
|         $ffmpeg->open(__DIR__ . '/../../files/UnknownFileTest.ogv'); |         $ffmpeg->open(__DIR__ . '/../files/UnknownFileTest.ogv'); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public function testSaveInvalidForgedVideo() |     public function testSaveInvalidForgedVideo() | ||||||
|     { |     { | ||||||
|         $ffmpeg = $this->getFFMpeg(); |         $ffmpeg = $this->getFFMpeg(); | ||||||
|         $video = new Video(__DIR__ . '/../../files/UnknownFileTest.ogv', $ffmpeg->getFFMpegDriver(), $ffmpeg->getFFProbe()); |         $video = new Video(__DIR__ . '/../files/UnknownFileTest.ogv', $ffmpeg->getFFMpegDriver(), $ffmpeg->getFFProbe()); | ||||||
| 
 | 
 | ||||||
|         $this->setExpectedException('FFMpeg\Exception\RuntimeException'); |         $this->setExpectedException('FFMpeg\Exception\RuntimeException'); | ||||||
|         $video->save(new X264('libvo_aacenc'), __DIR__ . '/output/output-x264.mp4'); |         $video->save(new X264('aac'), __DIR__ . '/output/output-x264.mp4'); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public function testTranscodePortraitVideo() |     public function testTranscodePortraitVideo() | ||||||
|  | @ -72,12 +102,12 @@ class VideoTranscodeTest extends FunctionalTestCase | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         $ffmpeg = $this->getFFMpeg(); |         $ffmpeg = $this->getFFMpeg(); | ||||||
|         $video = $ffmpeg->open(__DIR__ . '/../../files/portrait.MOV'); |         $video = $ffmpeg->open(__DIR__ . '/../files/portrait.MOV'); | ||||||
| 
 | 
 | ||||||
|         $video->filters() |         $video->filters() | ||||||
|             ->resize(new Dimension(320, 240), ResizeFilter::RESIZEMODE_INSET) |             ->resize(new Dimension(320, 240), ResizeFilter::RESIZEMODE_INSET) | ||||||
|             ->rotate(RotateFilter::ROTATE_90); |             ->rotate(RotateFilter::ROTATE_90); | ||||||
|         $video->save(new X264('libvo_aacenc'), $filename); |         $video->save(new X264('aac'), $filename); | ||||||
| 
 | 
 | ||||||
|         $dimension = $ffmpeg->getFFProbe() |         $dimension = $ffmpeg->getFFProbe() | ||||||
|             ->streams($filename) |             ->streams($filename) | ||||||
|  | @ -1,9 +1,9 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Coordinate; | namespace Tests\FFMpeg\Unit\Coordinate; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Coordinate\Dimension; | use FFMpeg\Coordinate\Dimension; | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\Coordinate\AspectRatio; | use FFMpeg\Coordinate\AspectRatio; | ||||||
| 
 | 
 | ||||||
| class AspectRatioTest extends TestCase | class AspectRatioTest extends TestCase | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Coordinate; | namespace Tests\FFMpeg\Unit\Coordinate; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\Coordinate\Dimension; | use FFMpeg\Coordinate\Dimension; | ||||||
| 
 | 
 | ||||||
| class DimensionTest extends TestCase | class DimensionTest extends TestCase | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Coordinate; | namespace Tests\FFMpeg\Unit\Coordinate; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\Coordinate\FrameRate; | use FFMpeg\Coordinate\FrameRate; | ||||||
| 
 | 
 | ||||||
| class FrameRateTest extends TestCase | class FrameRateTest extends TestCase | ||||||
							
								
								
									
										23
									
								
								tests/Unit/Coordinate/PointTest.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								tests/Unit/Coordinate/PointTest.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | ||||||
|  | <?php | ||||||
|  | 
 | ||||||
|  | namespace Tests\FFMpeg\Unit\Coordinate; | ||||||
|  | 
 | ||||||
|  | use Tests\FFMpeg\Unit\TestCase; | ||||||
|  | use FFMpeg\Coordinate\Point; | ||||||
|  | 
 | ||||||
|  | class PointTest extends TestCase | ||||||
|  | { | ||||||
|  |     public function testGetters() | ||||||
|  |     { | ||||||
|  |         $point = new Point(4, 25); | ||||||
|  |         $this->assertEquals(4, $point->getX()); | ||||||
|  |         $this->assertEquals(25, $point->getY()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function testDynamicPointGetters() | ||||||
|  |     { | ||||||
|  |         $point = new Point("t*100", "t", true); | ||||||
|  |         $this->assertEquals("t*100", $point->getX()); | ||||||
|  |         $this->assertEquals("t", $point->getY()); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Coordinate; | namespace Tests\FFMpeg\Unit\Coordinate; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\Coordinate\TimeCode; | use FFMpeg\Coordinate\TimeCode; | ||||||
| 
 | 
 | ||||||
| class TimeCodeTest extends TestCase | class TimeCodeTest extends TestCase | ||||||
|  | @ -1,10 +1,10 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Driver; | namespace Tests\FFMpeg\Unit\Driver; | ||||||
| 
 | 
 | ||||||
| use Alchemy\BinaryDriver\Configuration; | use Alchemy\BinaryDriver\Configuration; | ||||||
| use FFMpeg\Driver\FFMpegDriver; | use FFMpeg\Driver\FFMpegDriver; | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use Symfony\Component\Process\ExecutableFinder; | use Symfony\Component\Process\ExecutableFinder; | ||||||
| 
 | 
 | ||||||
| class FFMpegDriverTest extends TestCase | class FFMpegDriverTest extends TestCase | ||||||
|  | @ -1,10 +1,10 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Driver; | namespace Tests\FFMpeg\Unit\Driver; | ||||||
| 
 | 
 | ||||||
| use Alchemy\BinaryDriver\Configuration; | use Alchemy\BinaryDriver\Configuration; | ||||||
| use FFMpeg\Driver\FFProbeDriver; | use FFMpeg\Driver\FFProbeDriver; | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use Symfony\Component\Process\ExecutableFinder; | use Symfony\Component\Process\ExecutableFinder; | ||||||
| 
 | 
 | ||||||
| class FFProbeDriverTest extends TestCase | class FFProbeDriverTest extends TestCase | ||||||
|  | @ -1,11 +1,12 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests; | namespace Tests\FFMpeg\Unit; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\FFMpegServiceProvider; | use FFMpeg\FFMpegServiceProvider; | ||||||
| use Silex\Application; | use Silex\Application; | ||||||
|  | use PHPUnit\Framework\TestCase as BaseTestCase; | ||||||
| 
 | 
 | ||||||
| class FFMpegServiceProviderTest extends \PHPUnit_Framework_TestCase | class FFMpegServiceProviderTest extends BaseTestCase | ||||||
| { | { | ||||||
|     public function testWithConfig() |     public function testWithConfig() | ||||||
|     { |     { | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests; | namespace Tests\FFMpeg\Unit; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\FFMpeg; | use FFMpeg\FFMpeg; | ||||||
| use FFMpeg\FFProbe\DataMapping\StreamCollection; | use FFMpeg\FFProbe\DataMapping\StreamCollection; | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\FFProbe\DataMapping; | namespace Tests\FFMpeg\Unit\FFProbe\DataMapping; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\FFProbe\DataMapping\AbstractData; | use FFMpeg\FFProbe\DataMapping\AbstractData; | ||||||
| 
 | 
 | ||||||
| class AbstractDataTest extends TestCase | class AbstractDataTest extends TestCase | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\FFProbe\DataMapping; | namespace Tests\FFMpeg\Unit\FFProbe\DataMapping; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\FFProbe\DataMapping\StreamCollection; | use FFMpeg\FFProbe\DataMapping\StreamCollection; | ||||||
| 
 | 
 | ||||||
| class StreamCollectionTest extends TestCase | class StreamCollectionTest extends TestCase | ||||||
|  | @ -1,9 +1,9 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\FFProbe\DataMapping; | namespace Tests\FFMpeg\Unit\FFProbe\DataMapping; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Coordinate\Dimension; | use FFMpeg\Coordinate\Dimension; | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\FFProbe\DataMapping\Stream; | use FFMpeg\FFProbe\DataMapping\Stream; | ||||||
| 
 | 
 | ||||||
| class StreamTest extends TestCase | class StreamTest extends TestCase | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\FFProbe; | namespace Tests\FFMpeg\Unit\FFProbe; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\FFProbe\Mapper; | use FFMpeg\FFProbe\Mapper; | ||||||
| use FFMpeg\FFProbe; | use FFMpeg\FFProbe; | ||||||
| use FFMpeg\FFProbe\DataMapping\Format; | use FFMpeg\FFProbe\DataMapping\Format; | ||||||
|  | @ -31,8 +31,8 @@ class MapperTest extends TestCase | ||||||
| 
 | 
 | ||||||
|     public function provideMappings() |     public function provideMappings() | ||||||
|     { |     { | ||||||
|         $format = json_decode(file_get_contents(__DIR__ . '/../../../fixtures/ffprobe/show_format.json'), true); |         $format = json_decode(file_get_contents(__DIR__ . '/../../fixtures/ffprobe/show_format.json'), true); | ||||||
|         $streams = json_decode(file_get_contents(__DIR__ . '/../../../fixtures/ffprobe/show_streams.json'), true); |         $streams = json_decode(file_get_contents(__DIR__ . '/../../fixtures/ffprobe/show_streams.json'), true); | ||||||
| 
 | 
 | ||||||
|         return array( |         return array( | ||||||
|             array(FFProbe::TYPE_FORMAT, $format, new Format($format['format'])), |             array(FFProbe::TYPE_FORMAT, $format, new Format($format['format'])), | ||||||
|  | @ -1,9 +1,9 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\FFProbe; | namespace Tests\FFMpeg\Unit\FFProbe; | ||||||
| 
 | 
 | ||||||
| use Alchemy\BinaryDriver\Exception\ExecutionFailureException; | use Alchemy\BinaryDriver\Exception\ExecutionFailureException; | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\FFProbe\OptionsTester; | use FFMpeg\FFProbe\OptionsTester; | ||||||
| 
 | 
 | ||||||
| class OptionsTesterTest extends TestCase | class OptionsTesterTest extends TestCase | ||||||
|  | @ -55,7 +55,7 @@ class OptionsTesterTest extends TestCase | ||||||
| 
 | 
 | ||||||
|     public function provideOptions() |     public function provideOptions() | ||||||
|     { |     { | ||||||
|         $data = file_get_contents(__DIR__ . '/../../../fixtures/ffprobe/help.raw'); |         $data = file_get_contents(__DIR__ . '/../../fixtures/ffprobe/help.raw'); | ||||||
| 
 | 
 | ||||||
|         return array( |         return array( | ||||||
|             array(true, $data, '-print_format'), |             array(true, $data, '-print_format'), | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\FFProbe; | namespace Tests\FFMpeg\Unit\FFProbe; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\FFProbe\OutputParser; | use FFMpeg\FFProbe\OutputParser; | ||||||
| use FFMpeg\FFProbe; | use FFMpeg\FFProbe; | ||||||
| 
 | 
 | ||||||
|  | @ -28,11 +28,11 @@ class OutputParserTest extends TestCase | ||||||
| 
 | 
 | ||||||
|     public function provideTypeDataAndOutput() |     public function provideTypeDataAndOutput() | ||||||
|     { |     { | ||||||
|         $expectedFormat = json_decode(file_get_contents(__DIR__ . '/../../../fixtures/ffprobe/show_format.json'), true); |         $expectedFormat = json_decode(file_get_contents(__DIR__ . '/../../fixtures/ffprobe/show_format.json'), true); | ||||||
|         $expectedStreams = json_decode(file_get_contents(__DIR__ . '/../../../fixtures/ffprobe/show_streams.json'), true); |         $expectedStreams = json_decode(file_get_contents(__DIR__ . '/../../fixtures/ffprobe/show_streams.json'), true); | ||||||
| 
 | 
 | ||||||
|         $rawFormat = file_get_contents(__DIR__ . '/../../../fixtures/ffprobe/show_format.raw'); |         $rawFormat = file_get_contents(__DIR__ . '/../../fixtures/ffprobe/show_format.raw'); | ||||||
|         $rawStreams = file_get_contents(__DIR__ . '/../../../fixtures/ffprobe/show_streams.raw'); |         $rawStreams = file_get_contents(__DIR__ . '/../../fixtures/ffprobe/show_streams.raw'); | ||||||
| 
 | 
 | ||||||
|         return array( |         return array( | ||||||
|             array(FFProbe::TYPE_FORMAT, $rawFormat, $expectedFormat), |             array(FFProbe::TYPE_FORMAT, $rawFormat, $expectedFormat), | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests; | namespace Tests\FFMpeg\Unit; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\FFProbe; | use FFMpeg\FFProbe; | ||||||
| use Symfony\Component\Process\ExecutableFinder; | use Symfony\Component\Process\ExecutableFinder; | ||||||
							
								
								
									
										47
									
								
								tests/Unit/Filters/Audio/AudioClipTest.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								tests/Unit/Filters/Audio/AudioClipTest.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,47 @@ | ||||||
|  | <?php | ||||||
|  | 
 | ||||||
|  | namespace Tests\FFMpeg\Unit\Filters\Audio; | ||||||
|  | 
 | ||||||
|  | use FFMpeg\Filters\Audio\AudioFilters; | ||||||
|  | use FFMpeg\Coordinate\TimeCode; | ||||||
|  | use Tests\FFMpeg\Unit\TestCase; | ||||||
|  | 
 | ||||||
|  | class AudioClipTest extends TestCase { | ||||||
|  | 
 | ||||||
|  |     public function testClipping() { | ||||||
|  |         $capturedFilter = null; | ||||||
|  | 
 | ||||||
|  |         $audio = $this->getAudioMock(); | ||||||
|  |         $audio->expects($this->once()) | ||||||
|  |             ->method('addFilter') | ||||||
|  |             ->with($this->isInstanceOf('FFMpeg\Filters\Audio\AudioClipFilter')) | ||||||
|  |             ->will($this->returnCallback(function ($filter) use (&$capturedFilter) { | ||||||
|  |                 $capturedFilter = $filter; | ||||||
|  |         })); | ||||||
|  |         $format = $this->getMock('FFMpeg\Format\AudioInterface'); | ||||||
|  | 
 | ||||||
|  |         $filters = new AudioFilters($audio); | ||||||
|  | 
 | ||||||
|  |         $filters->clip(TimeCode::fromSeconds(5)); | ||||||
|  |         $this->assertEquals(array(0 => '-ss', 1 => '00:00:05.00', 2 => '-acodec', 3 => 'copy'), $capturedFilter->apply($audio, $format)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function testClippingWithDuration() { | ||||||
|  |         $capturedFilter = null; | ||||||
|  | 
 | ||||||
|  |         $audio = $this->getAudioMock(); | ||||||
|  |         $audio->expects($this->once()) | ||||||
|  |             ->method('addFilter') | ||||||
|  |             ->with($this->isInstanceOf('FFMpeg\Filters\Audio\AudioClipFilter')) | ||||||
|  |             ->will($this->returnCallback(function ($filter) use (&$capturedFilter) { | ||||||
|  |                 $capturedFilter = $filter; | ||||||
|  |         })); | ||||||
|  |         $format = $this->getMock('FFMpeg\Format\AudioInterface'); | ||||||
|  | 
 | ||||||
|  |         $filters = new AudioFilters($audio); | ||||||
|  | 
 | ||||||
|  |         $filters->clip(TimeCode::fromSeconds(5), TimeCode::fromSeconds(5)); | ||||||
|  |         $this->assertEquals(array(0 => '-ss', 1 => '00:00:05.00', 2 => '-t', 3 => '00:00:05.00', 4 => '-acodec', 5 => 'copy'), $capturedFilter->apply($audio, $format)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -1,9 +1,9 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Filters\Audio; | namespace Tests\FFMpeg\Unit\Filters\Audio; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Filters\Audio\AudioFilters; | use FFMpeg\Filters\Audio\AudioFilters; | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| 
 | 
 | ||||||
| class AudioFiltersTest extends TestCase | class AudioFiltersTest extends TestCase | ||||||
| { | { | ||||||
							
								
								
									
										64
									
								
								tests/Unit/Filters/Audio/AudioMetadataTest.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								tests/Unit/Filters/Audio/AudioMetadataTest.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,64 @@ | ||||||
|  | <?php | ||||||
|  | 
 | ||||||
|  | namespace Tests\FFMpeg\Unit\Filters\Audio; | ||||||
|  | 
 | ||||||
|  | use FFMpeg\Filters\Audio\AudioFilters; | ||||||
|  | use Tests\FFMpeg\Unit\TestCase; | ||||||
|  | 
 | ||||||
|  | class AudioMetadataTest extends TestCase | ||||||
|  | { | ||||||
|  |     public function testAddMetadata() | ||||||
|  |     { | ||||||
|  |         $capturedFilter = null; | ||||||
|  | 
 | ||||||
|  |         $audio = $this->getAudioMock(); | ||||||
|  |         $audio->expects($this->once()) | ||||||
|  |             ->method('addFilter') | ||||||
|  |             ->with($this->isInstanceOf('FFMpeg\Filters\Audio\AddMetadataFilter')) | ||||||
|  |             ->will($this->returnCallback(function ($filter) use (&$capturedFilter) { | ||||||
|  |                 $capturedFilter = $filter; | ||||||
|  |             })); | ||||||
|  |         $format = $this->getMock('FFMpeg\Format\AudioInterface'); | ||||||
|  | 
 | ||||||
|  |         $filters = new AudioFilters($audio); | ||||||
|  |         $filters->addMetadata(array('title' => "Hello World")); | ||||||
|  |         $this->assertEquals(array(0 => "-metadata", 1 => "title=Hello World"), $capturedFilter->apply($audio, $format)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function testAddArtwork() | ||||||
|  |     { | ||||||
|  |         $capturedFilter = null; | ||||||
|  | 
 | ||||||
|  |         $audio = $this->getAudioMock(); | ||||||
|  |         $audio->expects($this->once()) | ||||||
|  |             ->method('addFilter') | ||||||
|  |             ->with($this->isInstanceOf('FFMpeg\Filters\Audio\AddMetadataFilter')) | ||||||
|  |             ->will($this->returnCallback(function ($filter) use (&$capturedFilter) { | ||||||
|  |                 $capturedFilter = $filter; | ||||||
|  |             })); | ||||||
|  |         $format = $this->getMock('FFMpeg\Format\AudioInterface'); | ||||||
|  | 
 | ||||||
|  |         $filters = new AudioFilters($audio); | ||||||
|  |         $filters->addMetadata(array('genre' => 'Some Genre', 'artwork' => "/path/to/file.jpg")); | ||||||
|  |         $this->assertEquals(array(0 => "-i", 1 => "/path/to/file.jpg", 2 => "-map", 3 => "0", 4 => "-map", 5 => "1", 6 => "-metadata", 7 => "genre=Some Genre"), $capturedFilter->apply($audio, $format)); | ||||||
|  |         $this->assertEquals(array(0 => "-i", 1 => "/path/to/file.jpg", 2 => "-map", 3 => "0", 4 => "-map", 5 => "1", 6 => "-metadata", 7 => "genre=Some Genre"), $capturedFilter->apply($audio, $format)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function testRemoveMetadata() | ||||||
|  |     { | ||||||
|  |         $capturedFilter = null; | ||||||
|  | 
 | ||||||
|  |         $audio = $this->getAudioMock(); | ||||||
|  |         $audio->expects($this->once()) | ||||||
|  |             ->method('addFilter') | ||||||
|  |             ->with($this->isInstanceOf('FFMpeg\Filters\Audio\AddMetadataFilter')) | ||||||
|  |             ->will($this->returnCallback(function ($filter) use (&$capturedFilter) { | ||||||
|  |                 $capturedFilter = $filter; | ||||||
|  |             })); | ||||||
|  |         $format = $this->getMock('FFMpeg\Format\AudioInterface'); | ||||||
|  | 
 | ||||||
|  |         $filters = new AudioFilters($audio); | ||||||
|  |         $filters->addMetadata(); | ||||||
|  |         $this->assertEquals(array(0 => "-map_metadata", 1 => "-1", 2 => "-vn"), $capturedFilter->apply($audio, $format)); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,9 +1,9 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Filters\Audio; | namespace Tests\FFMpeg\Unit\Filters\Audio; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Filters\Audio\AudioResamplableFilter; | use FFMpeg\Filters\Audio\AudioResamplableFilter; | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| 
 | 
 | ||||||
| class AudioResamplableFilterTest extends TestCase | class AudioResamplableFilterTest extends TestCase | ||||||
| { | { | ||||||
|  | @ -1,10 +1,10 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Filters; | namespace Tests\FFMpeg\Unit\Filters; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Filters\FiltersCollection; | use FFMpeg\Filters\FiltersCollection; | ||||||
| use FFMpeg\Filters\Audio\SimpleFilter; | use FFMpeg\Filters\Audio\SimpleFilter; | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| 
 | 
 | ||||||
| class FiltersCollectionTest extends TestCase | class FiltersCollectionTest extends TestCase | ||||||
| { | { | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Filters\Frame; | namespace Tests\FFMpeg\Unit\Filters\Frame; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\Filters\Frame\DisplayRatioFixerFilter; | use FFMpeg\Filters\Frame\DisplayRatioFixerFilter; | ||||||
| use FFMpeg\Media\Frame; | use FFMpeg\Media\Frame; | ||||||
| use FFMpeg\Coordinate\TimeCode; | use FFMpeg\Coordinate\TimeCode; | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Filters\Frame; | namespace Tests\FFMpeg\Unit\Filters\Frame; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\Filters\Frame\FrameFilters; | use FFMpeg\Filters\Frame\FrameFilters; | ||||||
| 
 | 
 | ||||||
| class FrameFiltersTest extends TestCase | class FrameFiltersTest extends TestCase | ||||||
|  | @ -1,13 +1,13 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Filters\Video; | namespace Tests\FFMpeg\Unit\Filters\Video; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Coordinate\Dimension; | use FFMpeg\Coordinate\Dimension; | ||||||
| use FFMpeg\Coordinate\Point; | use FFMpeg\Coordinate\Point; | ||||||
| use FFMpeg\FFProbe\DataMapping\Stream; | use FFMpeg\FFProbe\DataMapping\Stream; | ||||||
| use FFMpeg\FFProbe\DataMapping\StreamCollection; | use FFMpeg\FFProbe\DataMapping\StreamCollection; | ||||||
| use FFMpeg\Filters\Video\CropFilter; | use FFMpeg\Filters\Video\CropFilter; | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| 
 | 
 | ||||||
| class CropFilterTest extends TestCase | class CropFilterTest extends TestCase | ||||||
| { | { | ||||||
|  | @ -1,10 +1,10 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Filters\Video; | namespace Tests\FFMpeg\Unit\Filters\Video; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Filters\Video\CustomFilter; | use FFMpeg\Filters\Video\CustomFilter; | ||||||
| use FFMpeg\Filters\Video\FrameRateFilter; | use FFMpeg\Filters\Video\FrameRateFilter; | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\Coordinate\FrameRate; | use FFMpeg\Coordinate\FrameRate; | ||||||
| 
 | 
 | ||||||
| class CustomFilterTest extends TestCase | class CustomFilterTest extends TestCase | ||||||
							
								
								
									
										51
									
								
								tests/Unit/Filters/Video/ExtractMultipleFramesFilterTest.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								tests/Unit/Filters/Video/ExtractMultipleFramesFilterTest.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,51 @@ | ||||||
|  | <?php | ||||||
|  | 
 | ||||||
|  | namespace Tests\FFMpeg\Unit\Filters\Video; | ||||||
|  | 
 | ||||||
|  | use FFMpeg\Filters\Video\ExtractMultipleFramesFilter; | ||||||
|  | use Tests\FFMpeg\Unit\TestCase; | ||||||
|  | use FFMpeg\FFProbe\DataMapping\Stream; | ||||||
|  | use FFMpeg\FFProbe\DataMapping\StreamCollection; | ||||||
|  | 
 | ||||||
|  | class ExtractMultipleFramesFilterTest extends TestCase | ||||||
|  | { | ||||||
|  |     /** | ||||||
|  |      * @dataProvider provideFrameRates | ||||||
|  |      */ | ||||||
|  |     public function testApply($frameRate, $destinationFolder, $duration, $modulus, $expected) | ||||||
|  |     { | ||||||
|  |         $video = $this->getVideoMock(); | ||||||
|  |         $pathfile = '/path/to/file'.mt_rand(); | ||||||
|  | 
 | ||||||
|  |         $format = $this->getMock('FFMpeg\Format\VideoInterface'); | ||||||
|  |         $format->expects($this->any()) | ||||||
|  |             ->method('getModulus') | ||||||
|  |             ->will($this->returnValue($modulus)); | ||||||
|  | 
 | ||||||
|  |         $streams = new StreamCollection(array( | ||||||
|  |             new Stream(array( | ||||||
|  |                 'codec_type' => 'video', | ||||||
|  |                 'duration'      => $duration, | ||||||
|  |             )) | ||||||
|  |         )); | ||||||
|  | 
 | ||||||
|  |         $video->expects($this->once()) | ||||||
|  |             ->method('getStreams') | ||||||
|  |             ->will($this->returnValue($streams)); | ||||||
|  | 
 | ||||||
|  |         $filter = new ExtractMultipleFramesFilter($frameRate, $destinationFolder); | ||||||
|  |         $this->assertEquals($expected, $filter->apply($video, $format)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function provideFrameRates() | ||||||
|  |     { | ||||||
|  |         return array( | ||||||
|  |             array(ExtractMultipleFramesFilter::FRAMERATE_EVERY_SEC, '/', 100, 2, array('-vf', 'fps=1/1', '/frame-%03d.jpg')), | ||||||
|  |             array(ExtractMultipleFramesFilter::FRAMERATE_EVERY_2SEC, '/', 100, 2, array('-vf', 'fps=1/2', '/frame-%02d.jpg')), | ||||||
|  |             array(ExtractMultipleFramesFilter::FRAMERATE_EVERY_5SEC, '/', 100, 2, array('-vf', 'fps=1/5', '/frame-%02d.jpg')), | ||||||
|  |             array(ExtractMultipleFramesFilter::FRAMERATE_EVERY_10SEC, '/', 100, 2, array('-vf', 'fps=1/10', '/frame-%02d.jpg')), | ||||||
|  |             array(ExtractMultipleFramesFilter::FRAMERATE_EVERY_30SEC, '/', 100, 2, array('-vf', 'fps=1/30', '/frame-%02d.jpg')), | ||||||
|  |             array(ExtractMultipleFramesFilter::FRAMERATE_EVERY_60SEC, '/', 100, 2, array('-vf', 'fps=1/60', '/frame-%02d.jpg')), | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,9 +1,9 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Filters\Video; | namespace Tests\FFMpeg\Unit\Filters\Video; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Filters\Video\FrameRateFilter; | use FFMpeg\Filters\Video\FrameRateFilter; | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\Coordinate\FrameRate; | use FFMpeg\Coordinate\FrameRate; | ||||||
| 
 | 
 | ||||||
| class FrameRateFilterTest extends TestCase | class FrameRateFilterTest extends TestCase | ||||||
							
								
								
									
										44
									
								
								tests/Unit/Filters/Video/PadFilterTest.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								tests/Unit/Filters/Video/PadFilterTest.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | ||||||
|  | <?php | ||||||
|  | 
 | ||||||
|  | namespace Tests\FFMpeg\Unit\Filters\Video; | ||||||
|  | 
 | ||||||
|  | use FFMpeg\Filters\Video\PadFilter; | ||||||
|  | use Tests\FFMpeg\Unit\TestCase; | ||||||
|  | use FFMpeg\FFProbe\DataMapping\Stream; | ||||||
|  | use FFMpeg\FFProbe\DataMapping\StreamCollection; | ||||||
|  | use FFMpeg\Coordinate\Dimension; | ||||||
|  | 
 | ||||||
|  | class PadFilterTest extends TestCase | ||||||
|  | { | ||||||
|  |     /** | ||||||
|  |      * @dataProvider provideDimensions | ||||||
|  |      */ | ||||||
|  |     public function testApply(Dimension $dimension, $width, $height, $expected) | ||||||
|  |     { | ||||||
|  |         $video = $this->getVideoMock(); | ||||||
|  |         $pathfile = '/path/to/file'.mt_rand(); | ||||||
|  | 
 | ||||||
|  |         $format = $this->getMock('FFMpeg\Format\VideoInterface'); | ||||||
|  | 
 | ||||||
|  |         $streams = new StreamCollection(array( | ||||||
|  |             new Stream(array( | ||||||
|  |                 'codec_type' => 'video', | ||||||
|  |                 'width'      => $width, | ||||||
|  |                 'height'     => $height, | ||||||
|  |             )) | ||||||
|  |         )); | ||||||
|  | 
 | ||||||
|  |         $filter = new PadFilter($dimension); | ||||||
|  |         $this->assertEquals($expected, $filter->apply($video, $format)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function provideDimensions() | ||||||
|  |     { | ||||||
|  |         return array( | ||||||
|  |             array(new Dimension(1000, 800), 640, 480, array('-vf', 'scale=iw*min(1000/iw\,800/ih):ih*min(1000/iw\,800/ih),pad=1000:800:(1000-iw)/2:(800-ih)/2')), | ||||||
|  |             array(new Dimension(300, 600), 640, 480, array('-vf', 'scale=iw*min(300/iw\,600/ih):ih*min(300/iw\,600/ih),pad=300:600:(300-iw)/2:(600-ih)/2')), | ||||||
|  |             array(new Dimension(100, 900), 640, 480, array('-vf', 'scale=iw*min(100/iw\,900/ih):ih*min(100/iw\,900/ih),pad=100:900:(100-iw)/2:(900-ih)/2')), | ||||||
|  |             array(new Dimension(1200, 200), 640, 480, array('-vf', 'scale=iw*min(1200/iw\,200/ih):ih*min(1200/iw\,200/ih),pad=1200:200:(1200-iw)/2:(200-ih)/2')), | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,9 +1,9 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Filters\Video; | namespace Tests\FFMpeg\Unit\Filters\Video; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Filters\Video\ResizeFilter; | use FFMpeg\Filters\Video\ResizeFilter; | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\FFProbe\DataMapping\Stream; | use FFMpeg\FFProbe\DataMapping\Stream; | ||||||
| use FFMpeg\FFProbe\DataMapping\StreamCollection; | use FFMpeg\FFProbe\DataMapping\StreamCollection; | ||||||
| use FFMpeg\Coordinate\Dimension; | use FFMpeg\Coordinate\Dimension; | ||||||
|  | @ -42,34 +42,34 @@ class ResizeFilterTest extends TestCase | ||||||
|     public function provideDimensions() |     public function provideDimensions() | ||||||
|     { |     { | ||||||
|         return array( |         return array( | ||||||
|             array(new Dimension(320, 240), ResizeFilter::RESIZEMODE_FIT, 640, 480, 2, array('-s', '320x240')), |             array(new Dimension(320, 240), ResizeFilter::RESIZEMODE_FIT, 640, 480, 2, array('-vf', '[in]scale=320:240 [out]')), | ||||||
|             array(new Dimension(320, 240), ResizeFilter::RESIZEMODE_INSET, 640, 480, 2, array('-s', '320x240')), |             array(new Dimension(320, 240), ResizeFilter::RESIZEMODE_INSET, 640, 480, 2, array('-vf', '[in]scale=320:240 [out]')), | ||||||
|             array(new Dimension(320, 240), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 640, 480, 2, array('-s', '320x240')), |             array(new Dimension(320, 240), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 640, 480, 2, array('-vf', '[in]scale=320:240 [out]')), | ||||||
|             array(new Dimension(320, 240), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 640, 480, 2, array('-s', '320x240')), |             array(new Dimension(320, 240), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 640, 480, 2, array('-vf', '[in]scale=320:240 [out]')), | ||||||
| 
 | 
 | ||||||
|             array(new Dimension(640, 480), ResizeFilter::RESIZEMODE_FIT, 320, 240, 2, array('-s', '640x480')), |             array(new Dimension(640, 480), ResizeFilter::RESIZEMODE_FIT, 320, 240, 2, array('-vf', '[in]scale=640:480 [out]')), | ||||||
|             array(new Dimension(640, 480), ResizeFilter::RESIZEMODE_INSET, 320, 240, 2, array('-s', '640x480')), |             array(new Dimension(640, 480), ResizeFilter::RESIZEMODE_INSET, 320, 240, 2, array('-vf', '[in]scale=640:480 [out]')), | ||||||
|             array(new Dimension(640, 480), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 320, 240, 2, array('-s', '640x480')), |             array(new Dimension(640, 480), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 320, 240, 2, array('-vf', '[in]scale=640:480 [out]')), | ||||||
|             array(new Dimension(640, 480), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 320, 240, 2, array('-s', '640x480')), |             array(new Dimension(640, 480), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 320, 240, 2, array('-vf', '[in]scale=640:480 [out]')), | ||||||
| 
 | 
 | ||||||
|             array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_FIT, 1280, 720, 2, array('-s', '640x360')), |             array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_FIT, 1280, 720, 2, array('-vf', '[in]scale=640:360 [out]')), | ||||||
|             array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_INSET, 1280, 720, 2, array('-s', '640x360')), |             array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_INSET, 1280, 720, 2, array('-vf', '[in]scale=640:360 [out]')), | ||||||
|             array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 1280, 720, 2, array('-s', '640x360')), |             array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 1280, 720, 2, array('-vf', '[in]scale=640:360 [out]')), | ||||||
|             array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 1280, 720, 2, array('-s', '640x360')), |             array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 1280, 720, 2, array('-vf', '[in]scale=640:360 [out]')), | ||||||
| 
 | 
 | ||||||
|             array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_FIT, 1280, 720, 2, array('-s', '640x360')), |             array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_FIT, 1280, 720, 2, array('-vf', '[in]scale=640:360 [out]')), | ||||||
|             array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_INSET, 1280, 720, 2, array('-s', '640x360')), |             array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_INSET, 1280, 720, 2, array('-vf', '[in]scale=640:360 [out]')), | ||||||
|             array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 1280, 720, 2, array('-s', '640x360')), |             array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 1280, 720, 2, array('-vf', '[in]scale=640:360 [out]')), | ||||||
|             array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 1280, 720, 2, array('-s', '640x360')), |             array(new Dimension(640, 360), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 1280, 720, 2, array('-vf', '[in]scale=640:360 [out]')), | ||||||
| 
 | 
 | ||||||
|             // test non standard dimension
 |             // test non standard dimension
 | ||||||
|             array(new Dimension(700, 150), ResizeFilter::RESIZEMODE_INSET, 123, 456, 2, array('-s', '62x150'), true), |             array(new Dimension(700, 150), ResizeFilter::RESIZEMODE_INSET, 123, 456, 2, array('-vf', '[in]scale=62:150 [out]'), true), | ||||||
|             array(new Dimension(700, 150), ResizeFilter::RESIZEMODE_INSET, 123, 456, 2, array('-s', '40x150'), false), |             array(new Dimension(700, 150), ResizeFilter::RESIZEMODE_INSET, 123, 456, 2, array('-vf', '[in]scale=40:150 [out]'), false), | ||||||
| 
 | 
 | ||||||
|             array(new Dimension(320, 320), ResizeFilter::RESIZEMODE_FIT, 640, 480, 2, array('-s', '320x320')), |             array(new Dimension(320, 320), ResizeFilter::RESIZEMODE_FIT, 640, 480, 2, array('-vf', '[in]scale=320:320 [out]')), | ||||||
|             array(new Dimension(320, 320), ResizeFilter::RESIZEMODE_INSET, 640, 480, 2, array('-s', '320x240')), |             array(new Dimension(320, 320), ResizeFilter::RESIZEMODE_INSET, 640, 480, 2, array('-vf', '[in]scale=320:240 [out]')), | ||||||
|             array(new Dimension(320, 320), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 640, 480, 2, array('-s', '320x240')), |             array(new Dimension(320, 320), ResizeFilter::RESIZEMODE_SCALE_HEIGHT, 640, 480, 2, array('-vf', '[in]scale=320:240 [out]')), | ||||||
|             array(new Dimension(320, 320), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 640, 480, 2, array('-s', '426x320')), |             array(new Dimension(320, 320), ResizeFilter::RESIZEMODE_SCALE_WIDTH, 640, 480, 2, array('-vf', '[in]scale=426:320 [out]')), | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -1,11 +1,11 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Filters\Video; | namespace Tests\FFMpeg\Unit\Filters\Video; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\FFProbe\DataMapping\Stream; | use FFMpeg\FFProbe\DataMapping\Stream; | ||||||
| use FFMpeg\FFProbe\DataMapping\StreamCollection; | use FFMpeg\FFProbe\DataMapping\StreamCollection; | ||||||
| use FFMpeg\Filters\Video\RotateFilter; | use FFMpeg\Filters\Video\RotateFilter; | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| 
 | 
 | ||||||
| class RotateFilterTest extends TestCase | class RotateFilterTest extends TestCase | ||||||
| { | { | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Filters\Video; | namespace Tests\FFMpeg\Unit\Filters\Video; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\Filters\Video\SynchronizeFilter; | use FFMpeg\Filters\Video\SynchronizeFilter; | ||||||
| 
 | 
 | ||||||
| class SynchronizeFilterTest extends TestCase | class SynchronizeFilterTest extends TestCase | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Filters\Video; | namespace Tests\FFMpeg\Unit\Filters\Video; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\Filters\Video\VideoFilters; | use FFMpeg\Filters\Video\VideoFilters; | ||||||
| use FFMpeg\Filters\Video\ResizeFilter; | use FFMpeg\Filters\Video\ResizeFilter; | ||||||
| 
 | 
 | ||||||
|  | @ -1,12 +1,12 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Filters\Video; | namespace Tests\FFMpeg\Unit\Filters\Video; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\FFProbe\DataMapping\Stream; | use FFMpeg\FFProbe\DataMapping\Stream; | ||||||
| use FFMpeg\FFProbe\DataMapping\StreamCollection; | use FFMpeg\FFProbe\DataMapping\StreamCollection; | ||||||
| use FFMpeg\Filters\Video\RotateFilter; | use FFMpeg\Filters\Video\RotateFilter; | ||||||
| use FFMpeg\Filters\Video\WatermarkFilter; | use FFMpeg\Filters\Video\WatermarkFilter; | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| 
 | 
 | ||||||
| class WatermarkFilterTest extends TestCase | class WatermarkFilterTest extends TestCase | ||||||
| { | { | ||||||
|  | @ -19,8 +19,8 @@ class WatermarkFilterTest extends TestCase | ||||||
| 
 | 
 | ||||||
|         $format = $this->getMock('FFMpeg\Format\VideoInterface'); |         $format = $this->getMock('FFMpeg\Format\VideoInterface'); | ||||||
| 
 | 
 | ||||||
|         $filter = new WatermarkFilter(__DIR__ . '/../../../../files/watermark.png'); |         $filter = new WatermarkFilter(__DIR__ . '/../../../files/watermark.png'); | ||||||
|         $this->assertEquals(array('-vf', 'movie='.__DIR__ .'/../../../../files/watermark.png [watermark]; [in][watermark] overlay=0:0 [out]'), $filter->apply($video, $format)); |         $this->assertEquals(array('-vf', 'movie='.__DIR__ .'/../../../files/watermark.png [watermark]; [in][watermark] overlay=0:0 [out]'), $filter->apply($video, $format)); | ||||||
| 
 | 
 | ||||||
|         // check size of video is unchanged
 |         // check size of video is unchanged
 | ||||||
|         $this->assertEquals(320, $stream->get('width')); |         $this->assertEquals(320, $stream->get('width')); | ||||||
|  | @ -33,31 +33,31 @@ class WatermarkFilterTest extends TestCase | ||||||
|         $format = $this->getMock('FFMpeg\Format\VideoInterface'); |         $format = $this->getMock('FFMpeg\Format\VideoInterface'); | ||||||
| 
 | 
 | ||||||
|         // test position absolute
 |         // test position absolute
 | ||||||
|         $filter = new WatermarkFilter(__DIR__ . '/../../../../files/watermark.png', array( |         $filter = new WatermarkFilter(__DIR__ . '/../../../files/watermark.png', array( | ||||||
|             'position' => 'absolute', |             'position' => 'absolute', | ||||||
|             'x' => 10, 'y' => 5 |             'x' => 10, 'y' => 5 | ||||||
|         )); |         )); | ||||||
|         $this->assertEquals(array('-vf', 'movie='.__DIR__ .'/../../../../files/watermark.png [watermark]; [in][watermark] overlay=10:5 [out]'), $filter->apply($video, $format)); |         $this->assertEquals(array('-vf', 'movie='.__DIR__ .'/../../../files/watermark.png [watermark]; [in][watermark] overlay=10:5 [out]'), $filter->apply($video, $format)); | ||||||
| 
 | 
 | ||||||
|         // test position relative
 |         // test position relative
 | ||||||
|         $filter = new WatermarkFilter(__DIR__ . '/../../../../files/watermark.png', array( |         $filter = new WatermarkFilter(__DIR__ . '/../../../files/watermark.png', array( | ||||||
|             'position' => 'relative', |             'position' => 'relative', | ||||||
|             'bottom' => 10, 'left' => 5 |             'bottom' => 10, 'left' => 5 | ||||||
|         )); |         )); | ||||||
|         $this->assertEquals(array('-vf', 'movie='.__DIR__ .'/../../../../files/watermark.png [watermark]; [in][watermark] overlay=5:main_h - 10 - overlay_h [out]'), $filter->apply($video, $format)); |         $this->assertEquals(array('-vf', 'movie='.__DIR__ .'/../../../files/watermark.png [watermark]; [in][watermark] overlay=5:main_h - 10 - overlay_h [out]'), $filter->apply($video, $format)); | ||||||
| 
 | 
 | ||||||
|         // test position relative
 |         // test position relative
 | ||||||
|         $filter = new WatermarkFilter(__DIR__ . '/../../../../files/watermark.png', array( |         $filter = new WatermarkFilter(__DIR__ . '/../../../files/watermark.png', array( | ||||||
|             'position' => 'relative', |             'position' => 'relative', | ||||||
|             'bottom' => 5, 'right' => 4 |             'bottom' => 5, 'right' => 4 | ||||||
|         )); |         )); | ||||||
|         $this->assertEquals(array('-vf', 'movie='.__DIR__ .'/../../../../files/watermark.png [watermark]; [in][watermark] overlay=main_w - 4 - overlay_w:main_h - 5 - overlay_h [out]'), $filter->apply($video, $format)); |         $this->assertEquals(array('-vf', 'movie='.__DIR__ .'/../../../files/watermark.png [watermark]; [in][watermark] overlay=main_w - 4 - overlay_w:main_h - 5 - overlay_h [out]'), $filter->apply($video, $format)); | ||||||
| 
 | 
 | ||||||
|         // test position relative
 |         // test position relative
 | ||||||
|         $filter = new WatermarkFilter(__DIR__ . '/../../../../files/watermark.png', array( |         $filter = new WatermarkFilter(__DIR__ . '/../../../files/watermark.png', array( | ||||||
|             'position' => 'relative', |             'position' => 'relative', | ||||||
|             'left' => 5, 'top' => 11 |             'left' => 5, 'top' => 11 | ||||||
|         )); |         )); | ||||||
|         $this->assertEquals(array('-vf', 'movie='.__DIR__ .'/../../../../files/watermark.png [watermark]; [in][watermark] overlay=5:11 [out]'), $filter->apply($video, $format)); |         $this->assertEquals(array('-vf', 'movie='.__DIR__ .'/../../../files/watermark.png [watermark]; [in][watermark] overlay=5:11 [out]'), $filter->apply($video, $format)); | ||||||
|     } |     } | ||||||
| } | } | ||||||
							
								
								
									
										28
									
								
								tests/Unit/Filters/Waveform/WaveformDownmixFilterTest.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								tests/Unit/Filters/Waveform/WaveformDownmixFilterTest.php
									
										
									
									
									
										Normal 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)); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								tests/Unit/Filters/Waveform/WaveformFiltersTest.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tests/Unit/Filters/Waveform/WaveformFiltersTest.php
									
										
									
									
									
										Normal 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(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Format\Audio; | namespace Tests\FFMpeg\Unit\Format\Audio; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Format\Audio\Aac; | use FFMpeg\Format\Audio\Aac; | ||||||
| 
 | 
 | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Format\Audio; | namespace Tests\FFMpeg\Unit\Format\Audio; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\Format\Audio\DefaultAudio; | use FFMpeg\Format\Audio\DefaultAudio; | ||||||
| 
 | 
 | ||||||
| abstract class AudioTestCase extends TestCase | abstract class AudioTestCase extends TestCase | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Format\Audio; | namespace Tests\FFMpeg\Unit\Format\Audio; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Format\Audio\Flac; | use FFMpeg\Format\Audio\Flac; | ||||||
| 
 | 
 | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Format\Audio; | namespace Tests\FFMpeg\Unit\Format\Audio; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Format\Audio\Mp3; | use FFMpeg\Format\Audio\Mp3; | ||||||
| 
 | 
 | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Format\Audio; | namespace Tests\FFMpeg\Unit\Format\Audio; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Format\Audio\Vorbis; | use FFMpeg\Format\Audio\Vorbis; | ||||||
| 
 | 
 | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Format\Audio; | namespace Tests\FFMpeg\Unit\Format\Audio; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Format\Audio\Wav; | use FFMpeg\Format\Audio\Wav; | ||||||
| 
 | 
 | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Format\ProgressListener; | namespace Tests\FFMpeg\Unit\Format\ProgressListener; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\Format\ProgressListener\AudioProgressListener; | use FFMpeg\Format\ProgressListener\AudioProgressListener; | ||||||
| use FFMpeg\FFProbe\DataMapping\Format; | use FFMpeg\FFProbe\DataMapping\Format; | ||||||
| 
 | 
 | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Format\ProgressListener; | namespace Tests\FFMpeg\Unit\Format\ProgressListener; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| use FFMpeg\Format\ProgressListener\VideoProgressListener; | use FFMpeg\Format\ProgressListener\VideoProgressListener; | ||||||
| use FFMpeg\FFProbe\DataMapping\Format; | use FFMpeg\FFProbe\DataMapping\Format; | ||||||
| 
 | 
 | ||||||
|  | @ -11,7 +11,7 @@ class VideoProgressListenerTest extends TestCase | ||||||
|     /** |     /** | ||||||
|      * @dataProvider provideData |      * @dataProvider provideData | ||||||
|      */ |      */ | ||||||
|     public function testHandle($size, $duration, |     public function testHandle($size, $duration, $newVideoDuration, | ||||||
|         $data, $expectedPercent, $expectedRemaining, $expectedRate, |         $data, $expectedPercent, $expectedRemaining, $expectedRate, | ||||||
|         $data2, $expectedPercent2, $expectedRemaining2, $expectedRate2, |         $data2, $expectedPercent2, $expectedRemaining2, $expectedRate2, | ||||||
|         $currentPass, $totalPass |         $currentPass, $totalPass | ||||||
|  | @ -26,7 +26,7 @@ class VideoProgressListenerTest extends TestCase | ||||||
|                 'duration' => $duration, |                 'duration' => $duration, | ||||||
|             )))); |             )))); | ||||||
| 
 | 
 | ||||||
|         $listener = new VideoProgressListener($ffprobe, __FILE__, $currentPass, $totalPass); |         $listener = new VideoProgressListener($ffprobe, __FILE__, $currentPass, $totalPass, $newVideoDuration); | ||||||
|         $phpunit = $this; |         $phpunit = $this; | ||||||
|         $n = 0; |         $n = 0; | ||||||
|         $listener->on('progress', function ($percent, $remaining, $rate) use (&$n, $phpunit, $expectedPercent, $expectedRemaining, $expectedRate, $expectedPercent2, $expectedRemaining2, $expectedRate2) { |         $listener->on('progress', function ($percent, $remaining, $rate) use (&$n, $phpunit, $expectedPercent, $expectedRemaining, $expectedRate, $expectedPercent2, $expectedRemaining2, $expectedRate2) { | ||||||
|  | @ -57,6 +57,7 @@ class VideoProgressListenerTest extends TestCase | ||||||
|             array( |             array( | ||||||
|                 147073958, |                 147073958, | ||||||
|                 281.147533, |                 281.147533, | ||||||
|  |                 281.147533, | ||||||
|                 'frame=  206 fps=202 q=10.0 size=     571kB time=00:00:07.12 bitrate= 656.8kbits/s dup=9 drop=0', |                 'frame=  206 fps=202 q=10.0 size=     571kB time=00:00:07.12 bitrate= 656.8kbits/s dup=9 drop=0', | ||||||
|                 2, |                 2, | ||||||
|                 0, |                 0, | ||||||
|  | @ -71,6 +72,7 @@ class VideoProgressListenerTest extends TestCase | ||||||
|             array( |             array( | ||||||
|                 147073958, |                 147073958, | ||||||
|                 281.147533, |                 281.147533, | ||||||
|  |                 281.147533, | ||||||
|                 'frame=  206 fps=202 q=10.0 size=     571kB time=00:00:07.12 bitrate= 656.8kbits/s dup=9 drop=0', |                 'frame=  206 fps=202 q=10.0 size=     571kB time=00:00:07.12 bitrate= 656.8kbits/s dup=9 drop=0', | ||||||
|                 1, |                 1, | ||||||
|                 0, |                 0, | ||||||
|  | @ -81,6 +83,21 @@ class VideoProgressListenerTest extends TestCase | ||||||
|                 3868, |                 3868, | ||||||
|                 1, |                 1, | ||||||
|                 2 |                 2 | ||||||
|  |             ), | ||||||
|  |             array( | ||||||
|  |                 147073958, | ||||||
|  |                 281.147533, | ||||||
|  |                 35, | ||||||
|  |                 'frame=  206 fps=202 q=10.0 size=     571kB time=00:00:07.12 bitrate= 656.8kbits/s dup=9 drop=0', | ||||||
|  |                 60, | ||||||
|  |                 0, | ||||||
|  |                 0, | ||||||
|  |                 'frame=  854 fps=113 q=20.0 size=    4430kB time=00:00:33.04 bitrate=1098.5kbits/s dup=36 drop=0', | ||||||
|  |                 97, | ||||||
|  |                 0, | ||||||
|  |                 3868, | ||||||
|  |                 2, | ||||||
|  |                 2 | ||||||
|             ) |             ) | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Format\Video; | namespace Tests\FFMpeg\Unit\Format\Video; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Format\Video\Ogg; | use FFMpeg\Format\Video\Ogg; | ||||||
| 
 | 
 | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Format\Video; | namespace Tests\FFMpeg\Unit\Format\Video; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Tests\Format\Audio\AudioTestCase; | use Tests\FFMpeg\Unit\Format\Audio\AudioTestCase; | ||||||
| 
 | 
 | ||||||
| abstract class VideoTestCase extends AudioTestCase | abstract class VideoTestCase extends AudioTestCase | ||||||
| { | { | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Format\Video; | namespace Tests\FFMpeg\Unit\Format\Video; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Format\Video\WMV3; | use FFMpeg\Format\Video\WMV3; | ||||||
| 
 | 
 | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Format\Video; | namespace Tests\FFMpeg\Unit\Format\Video; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Format\Video\WMV; | use FFMpeg\Format\Video\WMV; | ||||||
| 
 | 
 | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Format\Video; | namespace Tests\FFMpeg\Unit\Format\Video; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Format\Video\WebM; | use FFMpeg\Format\Video\WebM; | ||||||
| 
 | 
 | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Format\Video; | namespace Tests\FFMpeg\Unit\Format\Video; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Format\Video\X264; | use FFMpeg\Format\Video\X264; | ||||||
| 
 | 
 | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Media; | namespace Tests\FFMpeg\Unit\Media; | ||||||
| 
 | 
 | ||||||
| use FFMpeg\Tests\TestCase; | use Tests\FFMpeg\Unit\TestCase; | ||||||
| 
 | 
 | ||||||
| abstract class AbstractMediaTestCase extends TestCase | abstract class AbstractMediaTestCase extends TestCase | ||||||
| { | { | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| <?php | <?php | ||||||
| 
 | 
 | ||||||
| namespace FFMpeg\Tests\Media; | namespace Tests\FFMpeg\Unit\Media; | ||||||
| 
 | 
 | ||||||
| abstract class AbstractStreamableTestCase extends AbstractMediaTestCase | abstract class AbstractStreamableTestCase extends AbstractMediaTestCase | ||||||
| { | { | ||||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue