├── .github └── workflows │ ├── code_checks.yml │ └── code_quality.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── composer.json ├── ecs.php ├── phpunit.xml.dist ├── src ├── Attribute │ ├── AttributeInterface.php │ ├── Cover.php │ ├── Duration.php │ ├── FloatRate.php │ ├── Mode.php │ ├── Rate.php │ ├── Ratio.php │ └── Size.php ├── Builder │ ├── MediaInfoCommandBuilder.php │ └── MediaInfoContainerBuilder.php ├── Checker │ ├── AbstractAttributeChecker.php │ ├── AttributeCheckerInterface.php │ ├── CoverChecker.php │ ├── DateTimeChecker.php │ ├── DurationChecker.php │ ├── FloatRateChecker.php │ ├── ModeChecker.php │ ├── RateChecker.php │ ├── RatioChecker.php │ └── SizeChecker.php ├── Container │ └── MediaInfoContainer.php ├── DumpTrait.php ├── Exception │ ├── MediainfoOutputParsingException.php │ └── UnknownTrackTypeException.php ├── Factory │ ├── AttributeFactory.php │ └── TypeFactory.php ├── MediaInfo.php ├── Parser │ ├── AbstractXmlOutputParser.php │ ├── MediaInfoOutputParser.php │ └── OutputParserInterface.php ├── Runner │ └── MediaInfoCommandRunner.php └── Type │ ├── AbstractType.php │ ├── Audio.php │ ├── General.php │ ├── Image.php │ ├── Menu.php │ ├── Other.php │ ├── Subtitle.php │ └── Video.php └── tests ├── Attribute └── AttributeTest.php ├── Builder ├── MediaInfoCommandBuilderTest.php └── MediaInfoContainerBuilderTest.php ├── Container └── MediaInfoContainerTest.php ├── Exception └── UnknownTrackTypeExceptionTest.php ├── Factory └── AttributeFactoryTest.php ├── MediaInfoTest.php ├── Parser └── MediaInfoOutputParserTest.php ├── Runner └── MediaInfoCommandRunnerTest.php ├── Stub └── TrackTestType.php ├── bootstrap.php └── fixtures ├── mediainfo-17.10-output.xml ├── mediainfo-output-invalid-types.xml ├── mediainfo-output.xml └── test.mp3 /.github/workflows/code_checks.yml: -------------------------------------------------------------------------------- 1 | name: Code_Checks 2 | 3 | on: 4 | pull_request: null 5 | push: 6 | branches: 7 | - master 8 | env: 9 | LANG: "en_US.UTF-8" 10 | jobs: 11 | tests: 12 | runs-on: ubuntu-latest 13 | strategy: 14 | matrix: 15 | php: ["7.2", "7.3", "7.4", "8.0", "8.1", "8.2"] 16 | 17 | name: PHP ${{ matrix.php }} tests 18 | steps: 19 | - uses: actions/checkout@v2 20 | - uses: shivammathur/setup-php@v2 21 | with: 22 | php-version: ${{ matrix.php }} 23 | coverage: none # disable xdebug, pcov 24 | - run: composer install --no-progress 25 | - run: vendor/bin/phpunit 26 | 27 | test_lowest_dependencies: 28 | runs-on: ubuntu-latest 29 | steps: 30 | - uses: actions/checkout@v2 31 | - run: git fetch --depth=100000 origin 32 | 33 | # see https://github.com/shivammathur/setup-php 34 | - uses: shivammathur/setup-php@v2 35 | with: 36 | php-version: 7.2 37 | coverage: none 38 | 39 | - run: composer update --no-progress --prefer-lowest 40 | - run: vendor/bin/phpunit 41 | test_symfony_34: 42 | runs-on: ubuntu-latest 43 | steps: 44 | - uses: actions/checkout@v2 45 | - run: git fetch --depth=100000 origin 46 | 47 | # see https://github.com/shivammathur/setup-php 48 | - uses: shivammathur/setup-php@v2 49 | with: 50 | php-version: 7.2 51 | coverage: none 52 | 53 | - run: composer install 54 | - run: composer require --no-interaction --prefer-source symfony/process:3.4.* symfony/filesystem:3.4.* 55 | - run: vendor/bin/phpunit 56 | test_symfony_40: 57 | runs-on: ubuntu-latest 58 | steps: 59 | - uses: actions/checkout@v2 60 | - run: git fetch --depth=100000 origin 61 | 62 | # see https://github.com/shivammathur/setup-php 63 | - uses: shivammathur/setup-php@v2 64 | with: 65 | php-version: 7.3 66 | coverage: none 67 | 68 | - run: composer install 69 | - run: composer require --no-interaction --prefer-source symfony/process:4.0.* symfony/filesystem:4.0.* 70 | - run: vendor/bin/phpunit 71 | test_symfony_44: 72 | runs-on: ubuntu-latest 73 | steps: 74 | - uses: actions/checkout@v2 75 | - run: git fetch --depth=100000 origin 76 | 77 | # see https://github.com/shivammathur/setup-php 78 | - uses: shivammathur/setup-php@v2 79 | with: 80 | php-version: 7.4 81 | coverage: none 82 | 83 | - run: composer install 84 | - run: composer require --no-interaction --prefer-source symfony/process:4.4.* symfony/filesystem:4.4.* 85 | - run: vendor/bin/phpunit 86 | test_symfony_5: 87 | runs-on: ubuntu-latest 88 | steps: 89 | - uses: actions/checkout@v2 90 | - run: git fetch --depth=100000 origin 91 | 92 | # see https://github.com/shivammathur/setup-php 93 | - uses: shivammathur/setup-php@v2 94 | with: 95 | php-version: 7.4 96 | coverage: none 97 | 98 | - run: composer install 99 | - run: composer require --no-interaction --prefer-source symfony/process:~5.0 symfony/filesystem:~5.0 100 | - run: vendor/bin/phpunit 101 | test_symfony_60: 102 | runs-on: ubuntu-latest 103 | steps: 104 | - uses: actions/checkout@v2 105 | - run: git fetch --depth=100000 origin 106 | 107 | # see https://github.com/shivammathur/setup-php 108 | - uses: shivammathur/setup-php@v2 109 | with: 110 | php-version: 8.2 111 | coverage: none 112 | 113 | - run: composer install 114 | - run: composer require --no-interaction --prefer-source symfony/process:~6.0 symfony/filesystem:~6.0 115 | - run: vendor/bin/phpunit 116 | test_symfony_70: 117 | runs-on: ubuntu-latest 118 | steps: 119 | - uses: actions/checkout@v2 120 | - run: git fetch --depth=100000 origin 121 | 122 | # see https://github.com/shivammathur/setup-php 123 | - uses: shivammathur/setup-php@v2 124 | with: 125 | php-version: 8.2 126 | coverage: none 127 | 128 | - run: composer install 129 | - run: composer require --no-interaction --prefer-source symfony/process:~7.0 symfony/filesystem:~7.0 130 | - run: vendor/bin/phpunit 131 | ecs: 132 | runs-on: ubuntu-latest 133 | 134 | steps: 135 | - uses: actions/checkout@v2 136 | # see https://github.com/shivammathur/setup-php 137 | - uses: shivammathur/setup-php@v2 138 | with: 139 | php-version: 8.0 140 | coverage: none 141 | 142 | - run: composer install --no-progress 143 | - run: composer require symplify/easy-coding-standard --dev 144 | - run: vendor/bin/ecs check --ansi 145 | -------------------------------------------------------------------------------- /.github/workflows/code_quality.yml: -------------------------------------------------------------------------------- 1 | name: Code Quality 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | env: 8 | LANG: "en_US.UTF-8" 9 | jobs: 10 | test_coverage: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - run: git fetch --depth=100000 origin 15 | 16 | # see https://github.com/shivammathur/setup-php 17 | - uses: shivammathur/setup-php@v2 18 | with: 19 | php-version: 7.4 20 | coverage: pcov 21 | 22 | - run: composer install --no-progress 23 | - run : | 24 | vendor/bin/phpunit --coverage-clover build/logs/clover.xml 25 | # coveralls.io 26 | wget https://github.com/php-coveralls/php-coveralls/releases/download/v2.1.0/php-coveralls.phar 27 | php php-coveralls.phar --verbose 28 | env: 29 | COVERALLS_REPO_TOKEN: 'WTo6E8OMtzbMN3dkSjujrCJiNrPrAJI43' 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | composer.phar 3 | composer.lock 4 | MediaInfo.exe -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [5.0.0](https://github.com/mhor/php-mediainfo/tree/5.0.0) (2020-03-31) 4 | 5 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/4.1.3...5.0.0) 6 | 7 | **Closed issues:** 8 | 9 | - Process does not work on Windows / wrong ENV-definition [\#106](https://github.com/mhor/php-mediainfo/issues/106) 10 | - Remove compatibility layers [\#99](https://github.com/mhor/php-mediainfo/issues/99) 11 | - Only support new version of mediainfo [\#98](https://github.com/mhor/php-mediainfo/issues/98) 12 | - Convert code to php7 [\#97](https://github.com/mhor/php-mediainfo/issues/97) 13 | - Update dependencies [\#96](https://github.com/mhor/php-mediainfo/issues/96) 14 | 15 | **Merged pull requests:** 16 | 17 | - Use mediainfo\>=17.10 output format by default [\#103](https://github.com/mhor/php-mediainfo/pull/103) ([mhor](https://github.com/mhor)) 18 | - phpunit: migrate getMock usage to prophecy [\#102](https://github.com/mhor/php-mediainfo/pull/102) ([mhor](https://github.com/mhor)) 19 | - PHP 7.4 support [\#101](https://github.com/mhor/php-mediainfo/pull/101) ([mhor](https://github.com/mhor)) 20 | - Update php code [\#109](https://github.com/mhor/php-mediainfo/pull/109) ([mhor](https://github.com/mhor)) 21 | - Update symfony/process component call [\#108](https://github.com/mhor/php-mediainfo/pull/108) ([mhor](https://github.com/mhor)) 22 | 23 | ## [4.1.3](https://github.com/mhor/php-mediainfo/tree/4.1.3) (2020-03-22) 24 | 25 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/4.1.2...4.1.3) 26 | 27 | **Fixed bugs:** 28 | 29 | - Runtime exception for version 4.1.1 due to latest fix - Wrap every command argument in quotes [\#87](https://github.com/mhor/php-mediainfo/issues/87) 30 | 31 | **Merged pull requests:** 32 | 33 | - Update MediaInfoCommandRunner.php [\#107](https://github.com/mhor/php-mediainfo/pull/107) ([cklm](https://github.com/cklm)) 34 | - Update TravisCI configuration [\#94](https://github.com/mhor/php-mediainfo/pull/94) ([mhor](https://github.com/mhor)) 35 | 36 | ## [4.1.2](https://github.com/mhor/php-mediainfo/tree/4.1.2) (2018-07-03) 37 | 38 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/4.1.1...4.1.2) 39 | 40 | ## [4.1.1](https://github.com/mhor/php-mediainfo/tree/4.1.1) (2018-06-27) 41 | 42 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/4.1.0...4.1.1) 43 | 44 | **Fixed bugs:** 45 | 46 | - Mediainfo \>= 17.10 changed XML Format [\#82](https://github.com/mhor/php-mediainfo/issues/82) 47 | - XML format of mediainfo command has changed [\#76](https://github.com/mhor/php-mediainfo/issues/76) 48 | - Wrap every command argument in quotes [\#86](https://github.com/mhor/php-mediainfo/pull/86) ([mitchellklijs](https://github.com/mitchellklijs)) 49 | 50 | ## [4.1.0](https://github.com/mhor/php-mediainfo/tree/4.1.0) (2018-04-08) 51 | 52 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/4.0.2...4.1.0) 53 | 54 | **Fixed bugs:** 55 | 56 | - Add conf to support new versions of mediainfo [\#84](https://github.com/mhor/php-mediainfo/pull/84) ([mhor](https://github.com/mhor)) 57 | 58 | **Closed issues:** 59 | 60 | - Laravel 5.6 support [\#85](https://github.com/mhor/php-mediainfo/issues/85) 61 | 62 | **Merged pull requests:** 63 | 64 | - Fix-Runtime exception for version 4.1.1 [\#88](https://github.com/mhor/php-mediainfo/pull/88) ([amardeokar23](https://github.com/amardeokar23)) 65 | 66 | ## [4.0.2](https://github.com/mhor/php-mediainfo/tree/4.0.2) (2017-12-21) 67 | 68 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/4.0.1...4.0.2) 69 | 70 | **Fixed bugs:** 71 | 72 | - core: fix broken runner, as process input does not work as expected [\#81](https://github.com/mhor/php-mediainfo/pull/81) ([fvilpoix](https://github.com/fvilpoix)) 73 | 74 | ## [4.0.1](https://github.com/mhor/php-mediainfo/tree/4.0.1) (2017-12-19) 75 | 76 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/4.0.0...4.0.1) 77 | 78 | **Implemented enhancements:** 79 | 80 | - Support for Symfony 4 components [\#77](https://github.com/mhor/php-mediainfo/issues/77) 81 | 82 | **Merged pull requests:** 83 | 84 | - Typo on composer.json, allow any version of symfony component 4.0.\* [\#80](https://github.com/mhor/php-mediainfo/pull/80) ([fvilpoix](https://github.com/fvilpoix)) 85 | 86 | ## [4.0.0](https://github.com/mhor/php-mediainfo/tree/4.0.0) (2017-12-15) 87 | 88 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/3.0.0...4.0.0) 89 | 90 | **Closed issues:** 91 | 92 | - Unicode filename fail [\#72](https://github.com/mhor/php-mediainfo/issues/72) 93 | - Migrate to array short syntax [\#69](https://github.com/mhor/php-mediainfo/issues/69) 94 | - use url for path to media file [\#59](https://github.com/mhor/php-mediainfo/issues/59) 95 | 96 | **Merged pull requests:** 97 | 98 | - Apply fixes from StyleCI [\#79](https://github.com/mhor/php-mediainfo/pull/79) ([mhor](https://github.com/mhor)) 99 | - Allow compatibility with symfony4 components [\#78](https://github.com/mhor/php-mediainfo/pull/78) ([fvilpoix](https://github.com/fvilpoix)) 100 | - Update README.md [\#75](https://github.com/mhor/php-mediainfo/pull/75) ([cklm](https://github.com/cklm)) 101 | - I guess it's still accurate but must be specified [\#74](https://github.com/mhor/php-mediainfo/pull/74) ([Nek-](https://github.com/Nek-)) 102 | - change StyleCI config [\#70](https://github.com/mhor/php-mediainfo/pull/70) ([mhor](https://github.com/mhor)) 103 | 104 | ## [3.0.0](https://github.com/mhor/php-mediainfo/tree/3.0.0) (2017-01-17) 105 | 106 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/2.3.1...3.0.0) 107 | 108 | **Fixed bugs:** 109 | 110 | - Rate::getAbsoluteValue\(\) returns a string [\#65](https://github.com/mhor/php-mediainfo/issues/65) 111 | 112 | **Closed issues:** 113 | 114 | - Height is expressed as a Rate [\#67](https://github.com/mhor/php-mediainfo/issues/67) 115 | 116 | **Merged pull requests:** 117 | 118 | - add Ratio attribute type [\#68](https://github.com/mhor/php-mediainfo/pull/68) ([mhor](https://github.com/mhor)) 119 | 120 | ## [2.3.1](https://github.com/mhor/php-mediainfo/tree/2.3.1) (2017-01-15) 121 | 122 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/2.3.0...2.3.1) 123 | 124 | **Merged pull requests:** 125 | 126 | - Fix attributes type [\#66](https://github.com/mhor/php-mediainfo/pull/66) ([mhor](https://github.com/mhor)) 127 | 128 | ## [2.3.0](https://github.com/mhor/php-mediainfo/tree/2.3.0) (2017-01-13) 129 | 130 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/2.2.2...2.3.0) 131 | 132 | **Merged pull requests:** 133 | 134 | - Improve exception messages [\#64](https://github.com/mhor/php-mediainfo/pull/64) ([greg0ire](https://github.com/greg0ire)) 135 | 136 | ## [2.2.2](https://github.com/mhor/php-mediainfo/tree/2.2.2) (2016-09-04) 137 | 138 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/2.2.1...2.2.2) 139 | 140 | **Fixed bugs:** 141 | 142 | - Encoding issues related to simplexml\_load\_string [\#60](https://github.com/mhor/php-mediainfo/issues/60) 143 | 144 | **Merged pull requests:** 145 | 146 | - Check if isset [\#62](https://github.com/mhor/php-mediainfo/pull/62) ([danog](https://github.com/danog)) 147 | 148 | ## [2.2.1](https://github.com/mhor/php-mediainfo/tree/2.2.1) (2016-07-11) 149 | 150 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/2.2.0...2.2.1) 151 | 152 | ## [2.2.0](https://github.com/mhor/php-mediainfo/tree/2.2.0) (2016-05-22) 153 | 154 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/2.1.0...2.2.0) 155 | 156 | **Implemented enhancements:** 157 | 158 | - Remote file Support [\#55](https://github.com/mhor/php-mediainfo/issues/55) 159 | - make MediaInfoContainer dumpable [\#34](https://github.com/mhor/php-mediainfo/issues/34) 160 | 161 | **Merged pull requests:** 162 | 163 | - Simplify build [\#58](https://github.com/mhor/php-mediainfo/pull/58) ([mhor](https://github.com/mhor)) 164 | - Use url as file path [\#56](https://github.com/mhor/php-mediainfo/pull/56) ([mhor](https://github.com/mhor)) 165 | 166 | ## [2.1.0](https://github.com/mhor/php-mediainfo/tree/2.1.0) (2016-05-06) 167 | 168 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/2.0.0...2.1.0) 169 | 170 | **Merged pull requests:** 171 | 172 | - Applied fixes from StyleCI [\#54](https://github.com/mhor/php-mediainfo/pull/54) ([mhor](https://github.com/mhor)) 173 | - \[Travis\] disable XDebug [\#53](https://github.com/mhor/php-mediainfo/pull/53) ([mhor](https://github.com/mhor)) 174 | - mediainfocontainer-dump-xml [\#52](https://github.com/mhor/php-mediainfo/pull/52) ([javiertrejo](https://github.com/javiertrejo)) 175 | 176 | ## [2.0.0](https://github.com/mhor/php-mediainfo/tree/2.0.0) (2016-05-02) 177 | 178 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/1.6.0...2.0.0) 179 | 180 | **Merged pull requests:** 181 | 182 | - Applied fixes from StyleCI [\#51](https://github.com/mhor/php-mediainfo/pull/51) ([mhor](https://github.com/mhor)) 183 | - Feature/mediainfocontainer dump [\#50](https://github.com/mhor/php-mediainfo/pull/50) ([javiertrejo](https://github.com/javiertrejo)) 184 | 185 | ## [1.6.0](https://github.com/mhor/php-mediainfo/tree/1.6.0) (2016-01-24) 186 | 187 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/1.5.3...1.6.0) 188 | 189 | **Fixed bugs:** 190 | 191 | - Warning: escapeshellarg\(\) expects parameter 1 to be string, array given \(...\) [\#45](https://github.com/mhor/php-mediainfo/issues/45) 192 | - Encoding [\#42](https://github.com/mhor/php-mediainfo/issues/42) 193 | 194 | **Merged pull requests:** 195 | 196 | - Make php-mediainfo more configurable [\#47](https://github.com/mhor/php-mediainfo/pull/47) ([mhor](https://github.com/mhor)) 197 | - fix symfony2.3 compatibility [\#46](https://github.com/mhor/php-mediainfo/pull/46) ([mhor](https://github.com/mhor)) 198 | 199 | ## [1.5.3](https://github.com/mhor/php-mediainfo/tree/1.5.3) (2015-12-21) 200 | 201 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/1.5.2...1.5.3) 202 | 203 | ## [1.5.2](https://github.com/mhor/php-mediainfo/tree/1.5.2) (2015-12-21) 204 | 205 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/1.5.1...1.5.2) 206 | 207 | **Merged pull requests:** 208 | 209 | - Added lc\_type env to travis test [\#44](https://github.com/mhor/php-mediainfo/pull/44) ([alangregory](https://github.com/alangregory)) 210 | - tweaked .travis.yml [\#41](https://github.com/mhor/php-mediainfo/pull/41) ([mhor](https://github.com/mhor)) 211 | - improve unit test [\#40](https://github.com/mhor/php-mediainfo/pull/40) ([mhor](https://github.com/mhor)) 212 | 213 | ## [1.5.1](https://github.com/mhor/php-mediainfo/tree/1.5.1) (2015-12-04) 214 | 215 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/1.5.0...1.5.1) 216 | 217 | **Merged pull requests:** 218 | 219 | - Set LANG env variable [\#43](https://github.com/mhor/php-mediainfo/pull/43) ([alangregory](https://github.com/alangregory)) 220 | - make php-mediainfo compatible with symfony3 [\#39](https://github.com/mhor/php-mediainfo/pull/39) ([mhor](https://github.com/mhor)) 221 | - Dedup attributes with different case [\#38](https://github.com/mhor/php-mediainfo/pull/38) ([mhor](https://github.com/mhor)) 222 | - fix .styleci.yml [\#37](https://github.com/mhor/php-mediainfo/pull/37) ([mhor](https://github.com/mhor)) 223 | 224 | ## [1.5.0](https://github.com/mhor/php-mediainfo/tree/1.5.0) (2015-09-16) 225 | 226 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/1.4.4...1.5.0) 227 | 228 | **Fixed bugs:** 229 | 230 | - Type doesn't exist: Menu [\#31](https://github.com/mhor/php-mediainfo/issues/31) 231 | 232 | **Merged pull requests:** 233 | 234 | - Add Menu type [\#32](https://github.com/mhor/php-mediainfo/pull/32) ([mhor](https://github.com/mhor)) 235 | 236 | ## [1.4.4](https://github.com/mhor/php-mediainfo/tree/1.4.4) (2015-09-04) 237 | 238 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/1.4.3...1.4.4) 239 | 240 | **Implemented enhancements:** 241 | 242 | - What about adding 'Maximum bit rate'? [\#29](https://github.com/mhor/php-mediainfo/issues/29) 243 | 244 | **Merged pull requests:** 245 | 246 | - Add maximum\_bit\_rate [\#30](https://github.com/mhor/php-mediainfo/pull/30) ([mhor](https://github.com/mhor)) 247 | 248 | ## [1.4.3](https://github.com/mhor/php-mediainfo/tree/1.4.3) (2015-09-02) 249 | 250 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/1.4.2...1.4.3) 251 | 252 | **Fixed bugs:** 253 | 254 | - if Video, Audio Track-\>format is string, value is invalid. [\#27](https://github.com/mhor/php-mediainfo/issues/27) 255 | 256 | **Closed issues:** 257 | 258 | - Fix StyleCI build [\#25](https://github.com/mhor/php-mediainfo/issues/25) 259 | 260 | **Merged pull requests:** 261 | 262 | - Some Mode field can be strings [\#28](https://github.com/mhor/php-mediainfo/pull/28) ([mhor](https://github.com/mhor)) 263 | - Fixed styleci config [\#26](https://github.com/mhor/php-mediainfo/pull/26) ([GrahamCampbell](https://github.com/GrahamCampbell)) 264 | 265 | ## [1.4.2](https://github.com/mhor/php-mediainfo/tree/1.4.2) (2015-07-08) 266 | 267 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/1.4.1...1.4.2) 268 | 269 | ## [1.4.1](https://github.com/mhor/php-mediainfo/tree/1.4.1) (2015-06-14) 270 | 271 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/1.4.0...1.4.1) 272 | 273 | **Merged pull requests:** 274 | 275 | - Typo fixes [\#24](https://github.com/mhor/php-mediainfo/pull/24) ([GrahamCampbell](https://github.com/GrahamCampbell)) 276 | - Fixes [\#23](https://github.com/mhor/php-mediainfo/pull/23) ([GrahamCampbell](https://github.com/GrahamCampbell)) 277 | - Fixed style to match the other badges [\#20](https://github.com/mhor/php-mediainfo/pull/20) ([GrahamCampbell](https://github.com/GrahamCampbell)) 278 | 279 | ## [1.4.0](https://github.com/mhor/php-mediainfo/tree/1.4.0) (2015-06-14) 280 | 281 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/1.3.0...1.4.0) 282 | 283 | **Merged pull requests:** 284 | 285 | - Async operations [\#19](https://github.com/mhor/php-mediainfo/pull/19) ([Nicholi](https://github.com/Nicholi)) 286 | 287 | ## [1.3.0](https://github.com/mhor/php-mediainfo/tree/1.3.0) (2015-06-13) 288 | 289 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/1.2.1...1.3.0) 290 | 291 | **Merged pull requests:** 292 | 293 | - Optionally Ignore unknown TrackTypes [\#18](https://github.com/mhor/php-mediainfo/pull/18) ([Nicholi](https://github.com/Nicholi)) 294 | 295 | ## [1.2.1](https://github.com/mhor/php-mediainfo/tree/1.2.1) (2015-03-12) 296 | 297 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/1.2.0...1.2.1) 298 | 299 | ## [1.2.0](https://github.com/mhor/php-mediainfo/tree/1.2.0) (2015-01-25) 300 | 301 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/1.0.0...1.2.0) 302 | 303 | **Implemented enhancements:** 304 | 305 | - Support subtitles [\#15](https://github.com/mhor/php-mediainfo/issues/15) 306 | - Implement \_\_toString for custom type [\#13](https://github.com/mhor/php-mediainfo/issues/13) 307 | 308 | **Closed issues:** 309 | 310 | - - [\#14](https://github.com/mhor/php-mediainfo/issues/14) 311 | 312 | **Merged pull requests:** 313 | 314 | - Add Subtitle type [\#17](https://github.com/mhor/php-mediainfo/pull/17) ([mhor](https://github.com/mhor)) 315 | - add \_\_toString function on attributes fix \#13 [\#16](https://github.com/mhor/php-mediainfo/pull/16) ([mhor](https://github.com/mhor)) 316 | - add documentation [\#12](https://github.com/mhor/php-mediainfo/pull/12) ([mhor](https://github.com/mhor)) 317 | 318 | ## [1.0.0](https://github.com/mhor/php-mediainfo/tree/1.0.0) (2014-12-14) 319 | 320 | [Full Changelog](https://github.com/mhor/php-mediainfo/compare/1854a9f02a9e71880afdaa908ff77c01ecdef920...1.0.0) 321 | 322 | **Merged pull requests:** 323 | 324 | - add special type fields [\#11](https://github.com/mhor/php-mediainfo/pull/11) ([mhor](https://github.com/mhor)) 325 | - Increase code coverage [\#10](https://github.com/mhor/php-mediainfo/pull/10) ([mhor](https://github.com/mhor)) 326 | - Create attribute name checker [\#9](https://github.com/mhor/php-mediainfo/pull/9) ([mhor](https://github.com/mhor)) 327 | - Architecture enhancement [\#8](https://github.com/mhor/php-mediainfo/pull/8) ([mhor](https://github.com/mhor)) 328 | - add badges [\#7](https://github.com/mhor/php-mediainfo/pull/7) ([mhor](https://github.com/mhor)) 329 | - cs fix [\#6](https://github.com/mhor/php-mediainfo/pull/6) ([mhor](https://github.com/mhor)) 330 | - architecture improvement + unit tests + cs fix [\#5](https://github.com/mhor/php-mediainfo/pull/5) ([mhor](https://github.com/mhor)) 331 | - cleaning [\#4](https://github.com/mhor/php-mediainfo/pull/4) ([mhor](https://github.com/mhor)) 332 | - cleaning cs docs [\#3](https://github.com/mhor/php-mediainfo/pull/3) ([mhor](https://github.com/mhor)) 333 | - create custom attribute for special values [\#2](https://github.com/mhor/php-mediainfo/pull/2) ([mhor](https://github.com/mhor)) 334 | - create attribute factories [\#1](https://github.com/mhor/php-mediainfo/pull/1) ([mhor](https://github.com/mhor)) 335 | 336 | 337 | 338 | \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* 339 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2017 Maxime Horcholle 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Php-MediaInfo [![Coverage Status](https://coveralls.io/repos/github/mhor/php-mediainfo/badge.svg?branch=master)](https://coveralls.io/github/mhor/php-mediainfo?branch=master) [![Packagist](https://img.shields.io/packagist/v/mhor/php-mediainfo.svg)](https://packagist.org/packages/mhor/php-mediainfo) [![Packagist](https://img.shields.io/packagist/dt/mhor/php-mediainfo.svg)](https://packagist.org/packages/mhor/php-mediainfo) [![Code Checks](https://github.com/mhor/php-mediainfo/actions/workflows/code_checks.yml/badge.svg)](https://github.com/mhor/php-mediainfo/actions/workflows/code_checks.yml) 2 | 3 | ## Introduction 4 | 5 | PHP wrapper around the `mediainfo` command 6 | 7 | ## Table of contents: 8 | - [Installation](#installation) 9 | - [How to use](#how-to-use) 10 | - [Specials types](#specials-types) 11 | - [Extra](#extra) 12 | - [License](#license) 13 | 14 | ## Installation 15 | 16 | ### 1 - Install mediainfo 17 | You should install [mediainfo](http://manpages.ubuntu.com/manpages/gutsy/man1/mediainfo.1.html): 18 | 19 | #### On linux: 20 | 21 | ```bash 22 | $ sudo apt-get install mediainfo 23 | ``` 24 | 25 | #### On Mac: 26 | 27 | ```bash 28 | $ brew install mediainfo 29 | ``` 30 | 31 | ### 2 - Integration in your php project 32 | 33 | To use this library install it through [Composer](https://getcomposer.org/), run: 34 | 35 | ```bash 36 | $ composer require mhor/php-mediainfo 37 | ``` 38 | 39 | ## How to use 40 | 41 | ### Retrieve media information container 42 | 43 | ```php 44 | getInfo('music.mp3'); 50 | //... 51 | ``` 52 | 53 | ### Get general information from media information container 54 | 55 | ```php 56 | $general = $mediaInfoContainer->getGeneral(); 57 | ``` 58 | 59 | ### Get videos information from media information container 60 | 61 | ```php 62 | $videos = $mediaInfoContainer->getVideos(); 63 | 64 | foreach ($videos as $video) { 65 | // ... do something 66 | } 67 | ``` 68 | 69 | ### Get audios information from media information container 70 | 71 | ```php 72 | $audios = $mediaInfoContainer->getAudios(); 73 | 74 | foreach ($audios as $audio) { 75 | // ... do something 76 | } 77 | ``` 78 | 79 | ### Get subtitles information from media information container 80 | 81 | ```php 82 | $subtitles = $mediaInfoContainer->getSubtitles(); 83 | 84 | foreach ($subtitles as $subtitle) { 85 | // ... do something 86 | } 87 | ``` 88 | 89 | ### Get images information from media information container 90 | 91 | ```php 92 | $images = $mediaInfoContainer->getImages(); 93 | 94 | foreach ($images as $image) { 95 | // ... do something 96 | } 97 | ``` 98 | 99 | ### Get menus information from media information container 100 | 101 | ```php 102 | $menus = $mediaInfoContainer->getMenus(); 103 | 104 | foreach ($menus as $menu) { 105 | // ... do something 106 | } 107 | ``` 108 | 109 | ### Example 110 | 111 | ```php 112 | getInfo('./SampleVideo_1280x720_5mb.mkv'); 120 | 121 | echo "Videos channel: \n"; 122 | echo "=======================\n"; 123 | foreach ($mediaInfoContainer->getVideos() as $video) { 124 | if ($video->has('format')) { 125 | echo 'format: '.(string)$video->get('format')."\n"; 126 | } 127 | 128 | if ($video->has('height')) { 129 | echo 'height: '.$video->get('height')->getAbsoluteValue()."\n"; 130 | } 131 | 132 | echo "\n---------------------\n"; 133 | } 134 | 135 | echo "Audios channel: \n"; 136 | echo "=======================\n"; 137 | foreach ($mediaInfoContainer->getAudios() as $audio) { 138 | $availableInfo = $audio->list(); 139 | foreach ($availableInfo as $key) { 140 | echo $audio->get($key); 141 | } 142 | echo "\n---------------------\n"; 143 | } 144 | ``` 145 | 146 | ### Ignore unknown types 147 | 148 | By default, unknown type throw an error this, to avoid this behavior, you can do: 149 | 150 | ```php 151 | $mediaInfo = new MediaInfo(); 152 | $mediaInfo->setConfig('ignore_unknown_track_types', true); 153 | 154 | $mediaInfoContainer = $mediaInfo->getInfo('music.mp3'); 155 | 156 | $others = $mediaInfoContainer->getOthers(); 157 | foreach ($others as $other) { 158 | // ... do something 159 | } 160 | ``` 161 | 162 | ### Access to information 163 | 164 | #### Get all information into an array 165 | 166 | ```php 167 | $informationArray = $general->get(); 168 | ``` 169 | 170 | #### Get one information by field name 171 | 172 | Field Name are in lower case separated by "_" 173 | 174 | ```php 175 | $oneInformation = $general->get('count_of_audio_streams'); 176 | ``` 177 | 178 | #### Check if information exists 179 | 180 | Field Name are in lower case separated by "_" 181 | 182 | ```php 183 | if ($general->has('count_of_audio_streams')) { 184 | echo $general->get('count_of_audio_streams'); 185 | } 186 | ``` 187 | 188 | #### List available information 189 | 190 | ```php 191 | $availableInfo = $general->list(); 192 | foreach ($availableInfo as $key) { 193 | echo $general->get($key); 194 | } 195 | ``` 196 | 197 | ### Specials types 198 | 199 | #### Cover 200 | 201 | For field: 202 | 203 | - cover_data 204 | 205 | [Cover](src/Attribute/Cover.php) type will be applied 206 | 207 | #### Duration 208 | 209 | For fields: 210 | 211 | - duration 212 | - delay_relative_to_video 213 | - video0_delay 214 | - delay 215 | 216 | [Duration](src/Attribute/Duration.php) type will be applied 217 | 218 | #### Mode 219 | 220 | For fields: 221 | 222 | - overall_bit_rate_mode 223 | - overall_bit_rate 224 | - bit_rate_mode 225 | - compression_mode 226 | - codec 227 | - format 228 | - kind_of_stream 229 | - writing_library 230 | - id 231 | - format_settings_sbr 232 | - channel_positions 233 | - default 234 | - forced 235 | - delay_origin 236 | - scan_type 237 | - interlacement 238 | - scan_type 239 | - frame_rate_mode 240 | - format_settings_cabac 241 | - unique_id 242 | 243 | [Mode](src/Attribute/Mode.php) type will be applied 244 | 245 | #### Rate 246 | 247 | For fields: 248 | 249 | - channel_s 250 | - bit_rate 251 | - sampling_rate 252 | - bit_depth 253 | - width 254 | - nominal_bit_rate 255 | - format_settings_reframes 256 | - height 257 | - resolution 258 | - maximum_bit_rate 259 | 260 | [Rate](src/Attribute/Rate.php) type will be applied 261 | 262 | #### FloatRate 263 | 264 | For fields: 265 | 266 | - frame_rate 267 | 268 | [FloatRate](src/Attribute/FloatRate.php) type will be applied 269 | 270 | 271 | #### Ratio 272 | 273 | For fields: 274 | 275 | - display_aspect_ratio 276 | - original_display_aspect_ratio 277 | 278 | [Ratio](src/Attribute/Ratio.php) type will be applied 279 | 280 | #### Size 281 | 282 | For fields: 283 | 284 | - file_size 285 | - stream_size 286 | 287 | [Size](src/Attribute/Size.php) type will be applied 288 | 289 | #### Others 290 | - All date fields will be transformed into `Datetime` php object 291 | 292 | ## Extra 293 | 294 | ### Use custom mediainfo path 295 | 296 | ```php 297 | $mediaInfo = new MediaInfo(); 298 | $mediaInfo->setConfig('command', '/usr/local/bin/mediainfo'); 299 | $mediaInfoContainer = $mediaInfo->getInfo('music.mp3'); 300 | ``` 301 | 302 | ### Support old mediainfo version (<17.10) 303 | 304 | ```php 305 | $mediaInfo = new MediaInfo(); 306 | $mediaInfo->setConfig('use_oldxml_mediainfo_output_format', false); 307 | $mediaInfoContainer = $mediaInfo->getInfo('music.mp3'); 308 | ``` 309 | 310 | ### Use url as filepath 311 | 312 | ```php 313 | $mediaInfo = new MediaInfo(); 314 | $mediaInfoContainer = $mediaInfo->getInfo('http://example.org/music/test.mp3'); 315 | ``` 316 | 317 | ### MediaInfoContainer to JSON, Array or XML 318 | 319 | ```php 320 | $mediaInfo = new MediaInfo(); 321 | $mediaInfoContainer = $mediaInfo->getInfo('music.mp3'); 322 | 323 | $json = json_encode($mediaInfoContainer); 324 | $array = $mediaInfoContainer->__toArray(); 325 | $xml = $mediaInfoContainer->__toXML(); 326 | ``` 327 | 328 | ### Usage for WindowsOS 329 | 330 | Download MediaInfo CLI from [here](https://mediaarea.net/de/MediaInfo/Download/Windows). Extract zip-archive and place MediaInfo.exe somewhere. Use it: 331 | 332 | ```php 333 | $mediaInfo = new MediaInfo(); 334 | $mediaInfo->setConfig('command', 'C:\path\to\directory\MediaInfo.exe'); 335 | $mediaInfoContainer = $mediaInfo->getInfo('music.mp3'); 336 | ``` 337 | 338 | ### Urlencode Config 339 | 340 | By default, MediaInfo tries to detect if a URL is already percent-encode and encodes the URL when it's not. 341 | Setting the `'urlencode'` config setting to `true` forces MediaInfo to encode the URL despite the presence of percentage signs in the URL. 342 | This is for example required when using pre-signed URLs for AWS S3 objects. 343 | 344 | ```php 345 | $mediaInfo = new MediaInfo(); 346 | $mediaInfo->setConfig('urlencode', true); 347 | $mediaInfoContainer = $mediaInfo->getInfo('https://demo.us-west-1.amazonaws.com/video.mp4?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ABC%2F123%2Fus-west-1%2Fs3%2Faws4_request&X-Amz-Date=20200721T114451Z&X-Amz-SignedHeaders=host&X-Amz-Expires=600&X-Amz-Signature=123'); 348 | ``` 349 | 350 | This setting requires MediaInfo `20.03` minimum 351 | 352 | ### Cover data 353 | 354 | Recent versions of MediaInfo don't include cover data by default, without passing an additional flag. To include any available cover data, set the `'include_cover_data'` config setting to `true`. See the [cover type](#cover) for details on retrieving the base64 encoded image from `cover_data`. 355 | 356 | Originally this cover data was always included in the MediaInfo output, so this option is unnecessary for older versions. But [around version 18](https://sourceforge.net/p/mediainfo/discussion/297610/thread/aeb4222d/?limit=25) cover data was removed from the output by default, unless you also pass the `--Cover_Data=base64` flag. 357 | 358 | ```php 359 | $mediaInfo = new MediaInfo(); 360 | $mediaInfo->setConfig('include_cover_data', true); 361 | $mediaInfoContainer = $mediaInfo->getInfo('music.mp3'); 362 | 363 | $general = $mediaInfoContainer->getGeneral(); 364 | if ($general->has('cover_data')) { 365 | $attributeCover = $general->get('cover_data'); 366 | $base64EncodedImage = $attributeCover->getBinaryCover(); 367 | } 368 | ``` 369 | 370 | **Note:** Older versions of MediaInfo will print the following error if passed this flag: 371 | 372 | ```bash 373 | $ mediainfo ./music.mp3 -f --OUTPUT=OLDXML --Cover_Data=base64 374 | Option not known 375 | ``` 376 | 377 | ### Override attribute checkers/types 378 | 379 | This configuration allows you to customize the return values of attributes in php-mediainfo by creating custom checker and attribute classes. You can extend existing classes, override methods, and add additional functionality to provide more comprehensive or specialized information in the attribute objects returned by php-mediainfo. 380 | 381 | 1. Create a new class that implements the ``AttributeCheckerInterface`` 382 | 383 | ```php 384 | class CustomDurationChecker extends \Mhor\MediaInfo\Checker\DurationChecker 385 | { 386 | public function create($durations): \Mhor\MediaInfo\Attribute\Duration 387 | { 388 | return new CustomDuration($durations[0]); 389 | } 390 | 391 | public function getMembersFields(): array 392 | { 393 | return [ 394 | 'duration', 395 | ]; 396 | } 397 | } 398 | ``` 399 | 400 | 2. Create a new class that implements the ``AttributeInterface`` 401 | 402 | ```php 403 | class CustomDuration extends \Mhor\MediaInfo\Attribute\Duration 404 | { 405 | public function getSeconds() 406 | { 407 | return $this->getMilliseconds() / 1000; 408 | } 409 | } 410 | ``` 411 | 412 | 3. Set the new list of attribute checkers into the config 413 | 414 | ```php 415 | $mediaInfo = new MediaInfo(); 416 | $mediaInfo->setConfig('attribute_checkers', [new CustomDurationChecker()]); 417 | $mediaInfoContainer = $mediaInfo->getInfo( 418 | './SampleVideo_1280x720_5mb.mkv' 419 | ); 420 | 421 | foreach ($mediaInfoContainer->getAudios() as $audio) { 422 | echo $audio->get('duration')->getSeconds(); 423 | } 424 | ``` 425 | 426 | ### Symfony integration 427 | 428 | Look at this bundle: [MhorMediaInfoBunde](https://github.com/mhor/MhorMediaInfoBundle) 429 | 430 | ### Codeigniter integration 431 | 432 | Look at [this](https://philsturgeon.uk/blog/2012/05/composer-with-codeigniter/) to use composer with Codeigniter 433 | 434 | ## License 435 | See `LICENSE` for more information 436 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mhor/php-mediainfo", 3 | "type": "library", 4 | "description": "PHP wrapper around the mediainfo command", 5 | "keywords": [ 6 | "mediainfo", 7 | "wrapper", 8 | "metadata", 9 | "id3" 10 | ], 11 | "license": "MIT", 12 | "authors": [ 13 | { 14 | "name": "mhor", 15 | "email": "maxime.horcholle@gmail.com" 16 | } 17 | ], 18 | "require": { 19 | "php": ">=7.2", 20 | "symfony/process": "~3.4|~4.0|~5.0|~6.0|~7.0", 21 | "symfony/filesystem": "~3.4|~4.0|~5.0|~6.0|~7.0" 22 | }, 23 | "require-dev": { 24 | "phpunit/phpunit": "~8.5", 25 | "phpspec/prophecy": "^1.15" 26 | }, 27 | "autoload": { 28 | "psr-4": { 29 | "Mhor\\MediaInfo\\": "src/" 30 | } 31 | }, 32 | "autoload-dev": { 33 | "psr-4": { 34 | "Mhor\\MediaInfo\\Tests\\": "tests/" 35 | } 36 | }, 37 | "extra": { 38 | "branch-alias": { 39 | "dev-master": "6.0.x-dev" 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /ecs.php: -------------------------------------------------------------------------------- 1 | withPaths([__DIR__ . '/src', __DIR__ . '/tests']) 9 | ->withPreparedSets(true) 10 | ->withConfiguredRule(ConcatSpaceFixer::class, ['spacing' => 'none',]) 11 | ->withConfiguredRule(BinaryOperatorSpacesFixer::class, ['operators' => ['=>' => 'align']]); -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ./tests 6 | 7 | 8 | 9 | 10 | ./ 11 | 12 | ./tests 13 | ./vendor 14 | ./ecs.php 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Attribute/AttributeInterface.php: -------------------------------------------------------------------------------- 1 | binaryCover = $cover; 22 | } 23 | 24 | /** 25 | * @return string 26 | */ 27 | public function getBinaryCover(): string 28 | { 29 | return $this->binaryCover; 30 | } 31 | 32 | /** 33 | * @return string 34 | */ 35 | public function __toString(): string 36 | { 37 | return $this->binaryCover; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Attribute/Duration.php: -------------------------------------------------------------------------------- 1 | milliseconds = (int) $duration; 22 | } 23 | 24 | /** 25 | * @return int 26 | */ 27 | public function getMilliseconds(): int 28 | { 29 | return $this->milliseconds; 30 | } 31 | 32 | /** 33 | * @return string 34 | */ 35 | public function __toString(): string 36 | { 37 | return (string) $this->milliseconds; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Attribute/FloatRate.php: -------------------------------------------------------------------------------- 1 | absoluteValue; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Attribute/Mode.php: -------------------------------------------------------------------------------- 1 | shortName = $shortName; 28 | $this->fullName = $fullName; 29 | } 30 | 31 | /** 32 | * @return string 33 | */ 34 | public function getFullName(): string 35 | { 36 | return $this->fullName; 37 | } 38 | 39 | /** 40 | * @return string 41 | */ 42 | public function getShortName(): string 43 | { 44 | return $this->shortName; 45 | } 46 | 47 | /** 48 | * @return string 49 | */ 50 | public function __toString(): string 51 | { 52 | return $this->shortName; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Attribute/Rate.php: -------------------------------------------------------------------------------- 1 | absoluteValue = (float) $absoluteValue; 28 | $this->textValue = $textValue; 29 | } 30 | 31 | /** 32 | * @return int 33 | */ 34 | public function getAbsoluteValue(): int 35 | { 36 | return round($this->absoluteValue); 37 | } 38 | 39 | /** 40 | * @return string 41 | */ 42 | public function getTextValue(): string 43 | { 44 | return $this->textValue; 45 | } 46 | 47 | /** 48 | * @return string 49 | */ 50 | public function __toString(): string 51 | { 52 | return $this->textValue; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Attribute/Ratio.php: -------------------------------------------------------------------------------- 1 | absoluteValue = (float) $absoluteValue; 28 | $this->textValue = $textValue; 29 | } 30 | 31 | /** 32 | * @return float 33 | */ 34 | public function getAbsoluteValue(): float 35 | { 36 | return $this->absoluteValue; 37 | } 38 | 39 | /** 40 | * @return string 41 | */ 42 | public function getTextValue(): string 43 | { 44 | return $this->textValue; 45 | } 46 | 47 | /** 48 | * @return string 49 | */ 50 | public function __toString(): string 51 | { 52 | return $this->textValue; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Attribute/Size.php: -------------------------------------------------------------------------------- 1 | bit = (int) $size; 22 | } 23 | 24 | /** 25 | * @return int 26 | */ 27 | public function getBit(): int 28 | { 29 | return $this->bit; 30 | } 31 | 32 | /** 33 | * @return string 34 | */ 35 | public function __toString(): string 36 | { 37 | return (string) $this->bit; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Builder/MediaInfoCommandBuilder.php: -------------------------------------------------------------------------------- 1 | exists($filePath)) { 25 | throw new \Exception(sprintf('File "%s" does not exist', $filePath)); 26 | } 27 | 28 | if (is_dir($filePath)) { 29 | throw new \Exception(sprintf( 30 | 'Expected a filename, got "%s", which is a directory', 31 | $filePath 32 | )); 33 | } 34 | } 35 | 36 | $configuration += [ 37 | 'command' => null, 38 | 'use_oldxml_mediainfo_output_format' => true, 39 | 'urlencode' => false, 40 | 'include_cover_data' => false, 41 | ]; 42 | 43 | return new MediaInfoCommandRunner($this->buildMediaInfoProcess( 44 | $filePath, 45 | $configuration['command'], 46 | $configuration['use_oldxml_mediainfo_output_format'], 47 | $configuration['urlencode'], 48 | $configuration['include_cover_data'] 49 | )); 50 | } 51 | 52 | /** 53 | * @param string $filePath 54 | * @param string|null $command 55 | * @param bool $forceOldXmlOutput 56 | * @param bool $urlencode 57 | * 58 | * @return Process 59 | */ 60 | private function buildMediaInfoProcess(string $filePath, string $command = null, bool $forceOldXmlOutput = true, bool $urlencode = false, bool $includeCoverData = false): Process 61 | { 62 | if ($command === null) { 63 | $command = MediaInfoCommandRunner::MEDIAINFO_COMMAND; 64 | } 65 | 66 | // arguments are given through ENV vars in order to have system escape them 67 | $arguments = [ 68 | 'MEDIAINFO_VAR_FILE_PATH' => $filePath, 69 | 'MEDIAINFO_VAR_FULL_DISPLAY' => MediaInfoCommandRunner::MEDIAINFO_FULL_DISPLAY_ARGUMENT, 70 | 'MEDIAINFO_VAR_OUTPUT' => MediaInfoCommandRunner::MEDIAINFO_OLDXML_OUTPUT_ARGUMENT, 71 | ]; 72 | 73 | if (!$forceOldXmlOutput) { 74 | $arguments['MEDIAINFO_VAR_OUTPUT'] = MediaInfoCommandRunner::MEDIAINFO_XML_OUTPUT_ARGUMENT; 75 | } 76 | 77 | if ($urlencode) { 78 | $arguments['MEDIAINFO_VAR_URLENCODE'] = MediaInfoCommandRunner::MEDIAINFO_URLENCODE; 79 | } 80 | 81 | if ($includeCoverData) { 82 | $arguments['MEDIAINFO_COVER_DATA'] = MediaInfoCommandRunner::MEDIAINFO_INCLUDE_COVER_DATA; 83 | } 84 | 85 | $env = $arguments + [ 86 | 'LANG' => setlocale(LC_CTYPE, '0'), 87 | ]; 88 | 89 | return new Process( 90 | array_merge([$command], array_values($arguments)), 91 | null, 92 | $env 93 | ); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/Builder/MediaInfoContainerBuilder.php: -------------------------------------------------------------------------------- 1 | mediaInfoContainer = new MediaInfoContainer(); 33 | $this->typeFactory = new TypeFactory(); 34 | $this->attributesFactory = new AttributeFactory($attributesCheckers); 35 | } 36 | 37 | /** 38 | * @return MediaInfoContainer 39 | */ 40 | public function build(): \Mhor\MediaInfo\Container\MediaInfoContainer 41 | { 42 | return $this->mediaInfoContainer; 43 | } 44 | 45 | /** 46 | * @param string $version 47 | */ 48 | public function setVersion($version): void 49 | { 50 | $this->mediaInfoContainer->setVersion($version); 51 | } 52 | 53 | /** 54 | * @param $typeName 55 | * @param array $attributes 56 | * 57 | * @throws \Mhor\MediaInfo\Exception\UnknownTrackTypeException 58 | */ 59 | public function addTrackType($typeName, array $attributes): void 60 | { 61 | $trackType = $this->typeFactory->create($typeName); 62 | $this->addAttributes($trackType, $attributes); 63 | 64 | $this->mediaInfoContainer->add($trackType); 65 | } 66 | 67 | /** 68 | * @param AbstractType $trackType 69 | * @param array $attributes 70 | */ 71 | private function addAttributes(AbstractType $trackType, array $attributes): void 72 | { 73 | foreach ($this->sanitizeAttributes($attributes) as $attribute => $value) { 74 | if ($attribute[0] === '@') { 75 | continue; 76 | } 77 | 78 | $trackType->set( 79 | $attribute, 80 | $this->attributesFactory->create($attribute, $value) 81 | ); 82 | } 83 | } 84 | 85 | /** 86 | * @param array $attributes 87 | * 88 | * @return array 89 | */ 90 | private function sanitizeAttributes(array $attributes): array 91 | { 92 | $sanitizeAttributes = []; 93 | foreach ($attributes as $key => $value) { 94 | $key = $this->formatAttribute($key); 95 | if (isset($sanitizeAttributes[$key])) { 96 | if (!is_array($sanitizeAttributes[$key])) { 97 | $sanitizeAttributes[$key] = [$sanitizeAttributes[$key]]; 98 | } 99 | 100 | if (!is_array($value)) { 101 | $value = [$value]; 102 | } 103 | 104 | $value = $sanitizeAttributes[$key] + $value; 105 | } 106 | 107 | $sanitizeAttributes[$key] = $value; 108 | } 109 | 110 | return $sanitizeAttributes; 111 | } 112 | 113 | /** 114 | * @param string $attribute 115 | * 116 | * @return string 117 | */ 118 | private function formatAttribute(string $attribute): string 119 | { 120 | return trim(str_replace('__', '_', str_replace(' ', '_', strtolower($attribute))), '_'); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/Checker/AbstractAttributeChecker.php: -------------------------------------------------------------------------------- 1 | getMembersFields()); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Checker/AttributeCheckerInterface.php: -------------------------------------------------------------------------------- 1 | general; 73 | } 74 | 75 | /** 76 | * @return Audio[] 77 | */ 78 | public function getAudios(): array 79 | { 80 | return $this->audios; 81 | } 82 | 83 | /** 84 | * @return Image[] 85 | */ 86 | public function getImages(): array 87 | { 88 | return $this->images; 89 | } 90 | 91 | /** 92 | * @return Menu[] 93 | */ 94 | public function getMenus(): array 95 | { 96 | return $this->menus; 97 | } 98 | 99 | /** 100 | * @return Other[] 101 | */ 102 | public function getOthers(): array 103 | { 104 | return $this->others; 105 | } 106 | 107 | /** 108 | * @param string $version 109 | */ 110 | public function setVersion($version): void 111 | { 112 | $this->version = $version; 113 | } 114 | 115 | /** 116 | * @return string|null 117 | */ 118 | public function getVersion(): ?string 119 | { 120 | return $this->version; 121 | } 122 | 123 | /** 124 | * @return Video[] 125 | */ 126 | public function getVideos(): array 127 | { 128 | return $this->videos; 129 | } 130 | 131 | /** 132 | * @return Subtitle[] 133 | */ 134 | public function getSubtitles(): array 135 | { 136 | return $this->subtitles; 137 | } 138 | 139 | /** 140 | * @param General $general 141 | */ 142 | public function setGeneral($general): void 143 | { 144 | $this->general = $general; 145 | } 146 | 147 | /** 148 | * @param AbstractType $trackType 149 | * 150 | * @throws \Exception 151 | */ 152 | public function add(AbstractType $trackType): void 153 | { 154 | switch (get_class($trackType)) { 155 | case self::AUDIO_CLASS: 156 | $this->addAudio($trackType); 157 | break; 158 | case self::VIDEO_CLASS: 159 | $this->addVideo($trackType); 160 | break; 161 | case self::IMAGE_CLASS: 162 | $this->addImage($trackType); 163 | break; 164 | case self::GENERAL_CLASS: 165 | $this->setGeneral($trackType); 166 | break; 167 | case self::SUBTITLE_CLASS: 168 | $this->addSubtitle($trackType); 169 | break; 170 | case self::MENU_CLASS: 171 | $this->addMenu($trackType); 172 | break; 173 | case self::OTHER_CLASS: 174 | $this->addOther($trackType); 175 | break; 176 | default: 177 | throw new \Exception('Unknown type'); 178 | } 179 | } 180 | 181 | /** 182 | * @param Audio $audio 183 | */ 184 | private function addAudio(Audio $audio): void 185 | { 186 | $this->audios[] = $audio; 187 | } 188 | 189 | /** 190 | * @param Video $video 191 | */ 192 | private function addVideo(Video $video): void 193 | { 194 | $this->videos[] = $video; 195 | } 196 | 197 | /** 198 | * @param Image $image 199 | */ 200 | private function addImage(Image $image): void 201 | { 202 | $this->images[] = $image; 203 | } 204 | 205 | /** 206 | * @param Subtitle $subtitle 207 | */ 208 | private function addSubtitle(Subtitle $subtitle): void 209 | { 210 | $this->subtitles[] = $subtitle; 211 | } 212 | 213 | /** 214 | * @param Menu $menu 215 | */ 216 | private function addMenu(Menu $menu): void 217 | { 218 | $this->menus[] = $menu; 219 | } 220 | 221 | /** 222 | * @param Other $other 223 | */ 224 | private function addOther(Other $other): void 225 | { 226 | $this->others[] = $other; 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /src/DumpTrait.php: -------------------------------------------------------------------------------- 1 | jsonSerialize(); 25 | } 26 | 27 | public function __toXML() 28 | { 29 | $components = explode('\\', get_class($this)); 30 | $rootNode = end($components); 31 | $xml = new \SimpleXMLElement("<$rootNode>"); 32 | $array = json_decode(json_encode($this), true); 33 | 34 | $this->composeXML($array, $xml); 35 | 36 | return $xml; 37 | } 38 | 39 | protected function composeXML($data, &$xml): void 40 | { 41 | foreach ($data as $key => $value) { 42 | if (is_numeric($key)) { 43 | $key = 'item'.$key; 44 | } 45 | 46 | if (is_array($value)) { 47 | $subnode = $xml->addChild($key); 48 | $this->composeXML($value, $subnode); 49 | } else { 50 | $xml->addChild("$key", htmlspecialchars("$value")); 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Exception/MediainfoOutputParsingException.php: -------------------------------------------------------------------------------- 1 | trackType = $trackType; 20 | } 21 | 22 | /** 23 | * @return null|string 24 | */ 25 | public function getTrackType() 26 | { 27 | return $this->trackType; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Factory/AttributeFactory.php: -------------------------------------------------------------------------------- 1 | getDefaultAttributeCheckers(); 30 | } 31 | 32 | $this->attributeCheckers = $attributeCheckers; 33 | } 34 | 35 | /** 36 | * @param $attribute 37 | * @param $value 38 | * 39 | * @return mixed 40 | */ 41 | public function create($attribute, $value) 42 | { 43 | foreach ($this->attributeCheckers as $attributeChecker) { 44 | if ($attributeChecker->isMember($attribute)) { 45 | return $attributeChecker->create($value); 46 | } 47 | } 48 | 49 | return $value; 50 | } 51 | 52 | /** 53 | * @return AbstractAttributeChecker[] 54 | */ 55 | private function getDefaultAttributeCheckers(): array 56 | { 57 | return [ 58 | new CoverChecker(), 59 | new DurationChecker(), 60 | new ModeChecker(), 61 | new RateChecker(), 62 | new FloatRateChecker(), 63 | new RatioChecker(), 64 | new SizeChecker(), 65 | new DateTimeChecker(), 66 | ]; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Factory/TypeFactory.php: -------------------------------------------------------------------------------- 1 | null, 22 | 'use_oldxml_mediainfo_output_format' => true, 23 | 'urlencode' => false, 24 | 'include_cover_data' => false, 25 | 'ignore_unknown_track_types' => false, 26 | 'attribute_checkers' => null, 27 | ]; 28 | 29 | /** 30 | * @param string $filePath 31 | * @param bool $ignoreUnknownTrackTypes Optional parameter used to skip unknown track types by passing true. The 32 | * default behavior (false) is throw an exception on unknown track types. 33 | * This parameter is deprecated use self::setConfig('ignore_unknown_track_types', true) 34 | * 35 | * @throws \Mhor\MediaInfo\Exception\UnknownTrackTypeException 36 | * 37 | * @return MediaInfoContainer 38 | */ 39 | public function getInfo(string $filePath, bool $ignoreUnknownTrackTypes = false): MediaInfoContainer 40 | { 41 | $mediaInfoCommandBuilder = new MediaInfoCommandBuilder(); 42 | $output = $mediaInfoCommandBuilder->buildMediaInfoCommandRunner($filePath, $this->configuration)->run(); 43 | 44 | $mediaInfoOutputParser = new MediaInfoOutputParser(); 45 | $mediaInfoOutputParser->parse($output); 46 | 47 | if (true === $ignoreUnknownTrackTypes) { 48 | $this->setConfig('ignore_unknown_track_types', true); 49 | } 50 | 51 | return $mediaInfoOutputParser->getMediaInfoContainer($this->configuration); 52 | } 53 | 54 | /** 55 | * Call to start asynchronous process. 56 | * 57 | * Make call to MediaInfo::getInfoWaitAsync() afterwards to received MediaInfoContainer object. 58 | * 59 | * @param string $filePath 60 | */ 61 | public function getInfoStartAsync(string $filePath): void 62 | { 63 | $mediaInfoCommandBuilder = new MediaInfoCommandBuilder(); 64 | $this->mediaInfoCommandRunnerAsync = $mediaInfoCommandBuilder->buildMediaInfoCommandRunner( 65 | $filePath, 66 | $this->configuration 67 | ); 68 | $this->mediaInfoCommandRunnerAsync->start(); 69 | } 70 | 71 | /** 72 | * @param bool $ignoreUnknownTrackTypes Optional parameter used to skip unknown track types by passing true. The 73 | * default behavior (false) is throw an exception on unknown track types. 74 | * This parameter is deprecated use self::setConfig('ignore_unknown_track_types', true) 75 | * 76 | * @throws \Exception If this function is called before getInfoStartAsync() 77 | * @throws \Mhor\MediaInfo\Exception\UnknownTrackTypeException 78 | * 79 | * @return MediaInfoContainer 80 | */ 81 | public function getInfoWaitAsync(bool $ignoreUnknownTrackTypes = false): MediaInfoContainer 82 | { 83 | if ($this->mediaInfoCommandRunnerAsync == null) { 84 | throw new \Exception('You must run `getInfoStartAsync` before running `getInfoWaitAsync`'); 85 | } 86 | 87 | // blocks here until process is complete 88 | $output = $this->mediaInfoCommandRunnerAsync->wait(); 89 | 90 | $mediaInfoOutputParser = new MediaInfoOutputParser(); 91 | $mediaInfoOutputParser->parse($output); 92 | 93 | if (true === $ignoreUnknownTrackTypes) { 94 | $this->setConfig('ignore_unknown_track_types', true); 95 | } 96 | 97 | return $mediaInfoOutputParser->getMediaInfoContainer($this->configuration); 98 | } 99 | 100 | /** 101 | * @param string $key 102 | * @param mixed $value 103 | * 104 | * @throws \Exception 105 | */ 106 | public function setConfig(string $key, $value) 107 | { 108 | if (!array_key_exists($key, $this->configuration)) { 109 | throw new \Exception( 110 | sprintf('key "%s" does\'t exist', $key) 111 | ); 112 | } 113 | 114 | $this->configuration[$key] = $value; 115 | } 116 | 117 | /** 118 | * @param string $key 119 | * 120 | * @throws \Exception 121 | * 122 | * @return mixed 123 | */ 124 | public function getConfig(string $key) 125 | { 126 | if (!array_key_exists($key, $this->configuration)) { 127 | throw new \Exception( 128 | sprintf('key "%s" does\'t exist', $key) 129 | ); 130 | } 131 | 132 | return $this->configuration[$key]; 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/Parser/AbstractXmlOutputParser.php: -------------------------------------------------------------------------------- 1 | parsedOutput = $this->transformXmlToArray($output); 23 | } 24 | 25 | /** 26 | * @param array $configuration 27 | * 28 | * @return MediaInfoContainer 29 | */ 30 | public function getMediaInfoContainer(array $configuration): \Mhor\MediaInfo\Container\MediaInfoContainer 31 | { 32 | if ($this->parsedOutput === null) { 33 | throw new \Exception('You must run `parse` before running `getMediaInfoContainer`'); 34 | } 35 | 36 | $mediaInfoContainerBuilder = new MediaInfoContainerBuilder($configuration['attribute_checkers']); 37 | $mediaInfoContainerBuilder->setVersion($this->parsedOutput['@attributes']['version']); 38 | 39 | if (!array_key_exists('File', $this->parsedOutput)) { 40 | throw new MediainfoOutputParsingException( 41 | 'XML format of mediainfo >=17.10 command has changed, check php-mediainfo documentation' 42 | ); 43 | } 44 | 45 | foreach ($this->parsedOutput['File']['track'] as $trackType) { 46 | try { 47 | if (isset($trackType['@attributes']['type'])) { 48 | $mediaInfoContainerBuilder->addTrackType($trackType['@attributes']['type'], $trackType); 49 | } 50 | } catch (UnknownTrackTypeException $ex) { 51 | if (!$configuration['ignore_unknown_track_types']) { 52 | // rethrow exception 53 | throw $ex; 54 | } 55 | // else ignore 56 | } 57 | } 58 | 59 | return $mediaInfoContainerBuilder->build(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Parser/OutputParserInterface.php: -------------------------------------------------------------------------------- 1 | process = $process; 27 | } 28 | 29 | /** 30 | * @throws \RuntimeException 31 | * 32 | * @return string 33 | */ 34 | public function run(): string 35 | { 36 | $this->process->run(); 37 | if (!$this->process->isSuccessful()) { 38 | throw new \RuntimeException($this->process->getErrorOutput()); 39 | } 40 | 41 | return $this->process->getOutput(); 42 | } 43 | 44 | /** 45 | * Asynchronously start mediainfo operation. 46 | * Make call to MediaInfoCommandRunner::wait() afterwards to receive output. 47 | */ 48 | public function start(): void 49 | { 50 | // just takes advantage of symfony's underlying Process framework 51 | // process runs in background 52 | $this->process->start(); 53 | } 54 | 55 | /** 56 | * Blocks until call is complete. 57 | * 58 | * @throws \Exception If this function is called before start() 59 | * @throws \RuntimeException 60 | * 61 | * @return string 62 | */ 63 | public function wait(): string 64 | { 65 | // blocks here until process completes 66 | $this->process->wait(); 67 | 68 | if (!$this->process->isSuccessful()) { 69 | throw new \RuntimeException($this->process->getErrorOutput()); 70 | } 71 | 72 | return $this->process->getOutput(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/Type/AbstractType.php: -------------------------------------------------------------------------------- 1 | attributes[$attribute] = $value; 25 | } 26 | 27 | /** 28 | * @param string $attribute 29 | * 30 | * @return mixed 31 | */ 32 | public function get(string $attribute = null) 33 | { 34 | if ($attribute === null) { 35 | return $this->attributes; 36 | } 37 | 38 | if ($this->has($attribute)) { 39 | return $this->attributes[$attribute]; 40 | } 41 | 42 | return null; 43 | } 44 | 45 | /** 46 | * @param string $attribute 47 | * 48 | * @return bool 49 | */ 50 | public function has(string $attribute): bool 51 | { 52 | if (isset($this->attributes[$attribute])) { 53 | return true; 54 | } 55 | 56 | return false; 57 | } 58 | 59 | /** 60 | * @return array 61 | */ 62 | public function list(): array 63 | { 64 | return array_keys($this->attributes); 65 | } 66 | 67 | /** 68 | * Convert the object into json. 69 | * 70 | * @return array 71 | */ 72 | public function jsonSerialize(): array 73 | { 74 | $array = get_object_vars($this); 75 | 76 | if (isset($array['attributes'])) { 77 | $array = $array['attributes']; 78 | } 79 | 80 | return $array; 81 | } 82 | 83 | /** 84 | * Convert the object into array. 85 | * 86 | * @return array 87 | */ 88 | public function __toArray(): array 89 | { 90 | return $this->jsonSerialize(); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/Type/Audio.php: -------------------------------------------------------------------------------- 1 | assertEquals('binary_string', $cover->getBinaryCover()); 20 | $this->assertSame('binary_string', (string) $cover); 21 | } 22 | 23 | public function testDuration(): void 24 | { 25 | $duration = new Duration('1000'); 26 | $this->assertSame(1000, $duration->getMilliseconds()); 27 | $this->assertTrue(is_int($duration->getMilliseconds())); 28 | $this->assertSame('1000', (string) $duration); 29 | } 30 | 31 | public function testMode(): void 32 | { 33 | $mode = new Mode('short', 'full'); 34 | $this->assertEquals('short', $mode->getShortName()); 35 | $this->assertEquals('full', $mode->getFullName()); 36 | $this->assertSame('short', (string) $mode); 37 | } 38 | 39 | public function testRatio(): void 40 | { 41 | $ratio = new Ratio('15555', '15.55 Mo'); 42 | $this->assertSame(15555.0, $ratio->getAbsoluteValue()); 43 | $this->assertTrue(is_float($ratio->getAbsoluteValue())); 44 | $this->assertEquals('15.55 Mo', $ratio->getTextValue()); 45 | $this->assertSame('15.55 Mo', (string) $ratio); 46 | } 47 | 48 | public function testRate(): void 49 | { 50 | $rate = new Rate('720', '720p'); 51 | $this->assertSame(720, $rate->getAbsoluteValue()); 52 | $this->assertTrue(is_int($rate->getAbsoluteValue())); 53 | $this->assertEquals('720p', $rate->getTextValue()); 54 | $this->assertSame('720p', (string) $rate); 55 | } 56 | 57 | public function testFloatRate(): void 58 | { 59 | $rate = new FloatRate('46.875', '46.875 FPS (1024 SPF)'); 60 | $this->assertSame(47, $rate->getAbsoluteValue()); 61 | $this->assertSame(46.875, $rate->getFloatAbsoluteValue()); 62 | $this->assertTrue(is_int($rate->getAbsoluteValue())); 63 | $this->assertTrue(is_float($rate->getFloatAbsoluteValue())); 64 | $this->assertEquals('46.875 FPS (1024 SPF)', $rate->getTextValue()); 65 | $this->assertSame('46.875 FPS (1024 SPF)', (string) $rate); 66 | } 67 | 68 | public function testSize(): void 69 | { 70 | $size = new Size('42'); 71 | $this->assertSame(42, $size->getBit()); 72 | $this->assertTrue(is_int($size->getBit())); 73 | $this->assertSame('42', (string) $size); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tests/Builder/MediaInfoCommandBuilderTest.php: -------------------------------------------------------------------------------- 1 | filePath = __DIR__.'/../fixtures/test.mp3'; 17 | } 18 | 19 | public function testBuilderCommandWithHttpsUrl(): void 20 | { 21 | $mediaInfoCommandBuilder = new MediaInfoCommandBuilder(); 22 | $mediaInfoCommandRunner = $mediaInfoCommandBuilder->buildMediaInfoCommandRunner('https://example.org/'); 23 | 24 | $equalsMediaInfoCommandRunner = new MediaInfoCommandRunner(new Process( 25 | [ 26 | 'mediainfo', 27 | 'https://example.org/', 28 | '-f', 29 | '--OUTPUT=OLDXML', 30 | ], 31 | null, 32 | [ 33 | 'MEDIAINFO_VAR_FILE_PATH' => 'https://example.org/', 34 | 'MEDIAINFO_VAR_FULL_DISPLAY' => '-f', 35 | 'MEDIAINFO_VAR_OUTPUT' => '--OUTPUT=OLDXML', 36 | 'LANG' => 'en_US.UTF-8', 37 | ] 38 | )); 39 | 40 | $this->assertEquals($equalsMediaInfoCommandRunner, $mediaInfoCommandRunner); 41 | } 42 | 43 | public function testBuilderCommandWithHttpUrl(): void 44 | { 45 | $mediaInfoCommandBuilder = new MediaInfoCommandBuilder(); 46 | $mediaInfoCommandRunner = $mediaInfoCommandBuilder->buildMediaInfoCommandRunner('http://example.org/'); 47 | 48 | $equalsMediaInfoCommandRunner = new MediaInfoCommandRunner(new Process( 49 | [ 50 | 'mediainfo', 51 | 'http://example.org/', 52 | '-f', 53 | '--OUTPUT=OLDXML', 54 | ], 55 | null, 56 | [ 57 | 'MEDIAINFO_VAR_FILE_PATH' => 'http://example.org/', 58 | 'MEDIAINFO_VAR_FULL_DISPLAY' => '-f', 59 | 'MEDIAINFO_VAR_OUTPUT' => '--OUTPUT=OLDXML', 60 | 'LANG' => 'en_US.UTF-8', 61 | ] 62 | )); 63 | 64 | $this->assertEquals($equalsMediaInfoCommandRunner, $mediaInfoCommandRunner); 65 | } 66 | 67 | public function testExceptionWithNonExistingFile(): void 68 | { 69 | $this->expectException(\Exception::class); 70 | $this->expectExceptionMessage('File "non existing path" does not exist'); 71 | $mediaInfoCommandBuilder = new MediaInfoCommandBuilder(); 72 | $mediaInfoCommandBuilder->buildMediaInfoCommandRunner('non existing path'); 73 | } 74 | 75 | public function testExceptionWithDirectory(): void 76 | { 77 | $this->expectException(\Exception::class); 78 | $this->expectExceptionMessage('Expected a filename, got ".", which is a directory'); 79 | $mediaInfoCommandBuilder = new MediaInfoCommandBuilder(); 80 | $mediaInfoCommandBuilder->buildMediaInfoCommandRunner('.'); 81 | } 82 | 83 | public function testBuilderCommand(): void 84 | { 85 | $mediaInfoCommandBuilder = new MediaInfoCommandBuilder(); 86 | $mediaInfoCommandRunner = $mediaInfoCommandBuilder->buildMediaInfoCommandRunner($this->filePath); 87 | 88 | $equalsMediaInfoCommandRunner = new MediaInfoCommandRunner(new Process( 89 | [ 90 | 'mediainfo', 91 | $this->filePath, 92 | '-f', 93 | '--OUTPUT=OLDXML', 94 | ], 95 | null, 96 | [ 97 | 'MEDIAINFO_VAR_FILE_PATH' => $this->filePath, 98 | 'MEDIAINFO_VAR_FULL_DISPLAY' => '-f', 99 | 'MEDIAINFO_VAR_OUTPUT' => '--OUTPUT=OLDXML', 100 | 'LANG' => 'en_US.UTF-8', 101 | ] 102 | )); 103 | 104 | $this->assertEquals($equalsMediaInfoCommandRunner, $mediaInfoCommandRunner); 105 | } 106 | 107 | public function testConfiguredCommand(): void 108 | { 109 | $mediaInfoCommandBuilder = new MediaInfoCommandBuilder(); 110 | $mediaInfoCommandRunner = $mediaInfoCommandBuilder->buildMediaInfoCommandRunner( 111 | $this->filePath, 112 | [ 113 | 'command' => '/usr/bin/local/mediainfo', 114 | 'use_oldxml_mediainfo_output_format' => false, 115 | 'urlencode' => true, 116 | 'include_cover_data' => true, 117 | ] 118 | ); 119 | 120 | $equalsMediaInfoCommandRunner = new MediaInfoCommandRunner(new Process( 121 | [ 122 | '/usr/bin/local/mediainfo', 123 | $this->filePath, 124 | '-f', 125 | '--OUTPUT=XML', 126 | '--urlencode', 127 | '--Cover_Data=base64', 128 | ], 129 | null, 130 | [ 131 | 'MEDIAINFO_VAR_FILE_PATH' => $this->filePath, 132 | 'MEDIAINFO_VAR_FULL_DISPLAY' => '-f', 133 | 'MEDIAINFO_VAR_OUTPUT' => '--OUTPUT=XML', 134 | 'MEDIAINFO_VAR_URLENCODE' => '--urlencode', 135 | 'MEDIAINFO_COVER_DATA' => '--Cover_Data=base64', 136 | 'LANG' => 'en_US.UTF-8', 137 | ] 138 | )); 139 | 140 | $this->assertEquals($equalsMediaInfoCommandRunner, $mediaInfoCommandRunner); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /tests/Builder/MediaInfoContainerBuilderTest.php: -------------------------------------------------------------------------------- 1 | build(); 19 | $this->assertEquals(null, $mediaContainer->getVersion()); 20 | 21 | $mediaInfoContainerBuilder->setVersion('2.0'); 22 | $mediaContainer = $mediaInfoContainerBuilder->build(); 23 | 24 | $this->assertEquals('2.0', $mediaContainer->getVersion()); 25 | } 26 | 27 | public function testAddTrackType(): void 28 | { 29 | $mediaInfoContainerBuilder = new MediaInfoContainerBuilder(); 30 | 31 | $mediaInfoContainerBuilder->addTrackType(TypeFactory::AUDIO, []); 32 | $mediaContainer = $mediaInfoContainerBuilder->build(); 33 | $audios = $mediaContainer->getAudios(); 34 | $this->assertEquals(0, is_array($audios[0]->get()) || $audios[0]->get() instanceof \Countable ? count($audios[0]->get()) : 0); 35 | 36 | $mediaInfoContainerBuilder->addTrackType(TypeFactory::VIDEO, []); 37 | $mediaContainer = $mediaInfoContainerBuilder->build(); 38 | $videos = $mediaContainer->getVideos(); 39 | $this->assertEquals(0, is_array($videos[0]->get()) || $videos[0]->get() instanceof \Countable ? count($videos[0]->get()) : 0); 40 | 41 | $mediaInfoContainerBuilder->addTrackType(TypeFactory::GENERAL, []); 42 | $mediaContainer = $mediaInfoContainerBuilder->build(); 43 | $this->assertEquals(0, is_array($mediaContainer->getGeneral()->get()) || $mediaContainer->getGeneral()->get() instanceof \Countable ? count($mediaContainer->getGeneral()->get()) : 0); 44 | 45 | $mediaInfoContainerBuilder->addTrackType(TypeFactory::IMAGE, []); 46 | $mediaContainer = $mediaInfoContainerBuilder->build(); 47 | $images = $mediaContainer->getImages(); 48 | $this->assertEquals(0, is_array($images[0]->get()) || $images[0]->get() instanceof \Countable ? count($images[0]->get()) : 0); 49 | 50 | $mediaInfoContainerBuilder->addTrackType(TypeFactory::SUBTITLE, []); 51 | $mediaContainer = $mediaInfoContainerBuilder->build(); 52 | $subtitles = $mediaContainer->getSubtitles(); 53 | $this->assertEquals(0, is_array($subtitles[0]->get()) || $subtitles[0]->get() instanceof \Countable ? count($subtitles[0]->get()) : 0); 54 | 55 | $mediaInfoContainerBuilder->addTrackType(TypeFactory::OTHER, []); 56 | $mediaContainer = $mediaInfoContainerBuilder->build(); 57 | $others = $mediaContainer->getOthers(); 58 | $this->assertEquals(0, is_array($others[0]->get()) || $others[0]->get() instanceof \Countable ? count($others[0]->get()) : 0); 59 | } 60 | 61 | public function testAddInvalidType(): void 62 | { 63 | $this->expectException(UnknownTrackTypeException::class); 64 | $this->expectExceptionMessage('Type doesn\'t exist: InvalidType'); 65 | 66 | $mediaInfoContainerBuilder = new MediaInfoContainerBuilder(); 67 | $mediaInfoContainerBuilder->addTrackType('InvalidType', []); 68 | 69 | $mediaInfoContainerBuilder = new MediaInfoContainerBuilder(); 70 | 71 | $mediaInfoContainerBuilder->addTrackType('InvalidType', []); 72 | } 73 | 74 | public function testAddInvalidTypeOnMediaInfoContainer(): void 75 | { 76 | $this->expectException(\Exception::class); 77 | $mediaInfoContainerBuilder = new MediaInfoContainerBuilder(); 78 | $mediaInfoContainer = $mediaInfoContainerBuilder->build(); 79 | $mediaInfoContainer->add(new TrackTestType()); 80 | } 81 | 82 | public function attributesProvider(): array 83 | { 84 | return [ 85 | [ 86 | [ 87 | 'Duration' => '10', 88 | 'DuRatioN' => '20', 89 | 'DURATION' => '4000', 90 | ], 91 | ], 92 | [ 93 | [ 94 | 'Duration' => ['10', '30', '40'], 95 | 'DuRatioN' => '20', 96 | 'DURATION' => '4000', 97 | ], 98 | ], 99 | [ 100 | [ 101 | 'Duration' => '10', 102 | 'DuRatioN' => '20', 103 | 'DURATION' => ['60', '70', '80'], 104 | ], 105 | ], 106 | ]; 107 | } 108 | 109 | /** 110 | * @dataProvider attributesProvider 111 | */ 112 | public function testSanitizeAttributes(array $attributes): void 113 | { 114 | $mediaInfoContainerBuilder = new MediaInfoContainerBuilder(); 115 | $mediaInfoContainerBuilder->addTrackType(TypeFactory::AUDIO, $attributes); 116 | 117 | $mediaContainer = $mediaInfoContainerBuilder->build(); 118 | $audios = $mediaContainer->getAudios(); 119 | 120 | $this->assertEquals('Mhor\MediaInfo\Attribute\Duration', get_class($audios[0]->get('duration'))); 121 | 122 | /** @var Duration $duration */ 123 | $duration = $audios[0]->get('duration'); 124 | $this->assertEquals('10', $duration->getMilliseconds()); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /tests/Container/MediaInfoContainerTest.php: -------------------------------------------------------------------------------- 1 | set('Format', 'MPEG Audio'); 19 | $general->set('Duration', new Duration('1200000')); 20 | 21 | $audio = new Audio(); 22 | 23 | $audio->set('Format', 'MPEG Audio'); 24 | $audio->set('Bit rate', '56.0 Kbps'); 25 | 26 | $mediaInfoContainer->add($audio); 27 | $mediaInfoContainer->add($general); 28 | 29 | return $mediaInfoContainer; 30 | } 31 | 32 | public function testToJson(): void 33 | { 34 | $mediaInfoContainer = $this->createContainer(); 35 | 36 | $data = json_encode($mediaInfoContainer); 37 | 38 | $this->assertRegExp('/^\{.+\}$/', $data); 39 | } 40 | 41 | public function testToJsonType(): void 42 | { 43 | $mediaInfoContainer = $this->createContainer(); 44 | 45 | $data = json_encode($mediaInfoContainer->getGeneral()); 46 | 47 | $this->assertRegExp('/^\{.+\}$/', $data); 48 | } 49 | 50 | public function testToArray(): void 51 | { 52 | $mediaInfoContainer = $this->createContainer(); 53 | 54 | $array = $mediaInfoContainer->__toArray(); 55 | 56 | $this->assertArrayHasKey('version', $array); 57 | } 58 | 59 | public function testToArrayType(): void 60 | { 61 | $mediaInfoContainer = $this->createContainer(); 62 | 63 | $array = $mediaInfoContainer->getGeneral()->__toArray(); 64 | 65 | $this->assertTrue(is_array($array)); 66 | } 67 | 68 | public function testToXML(): void 69 | { 70 | $mediaInfoContainer = $this->createContainer(); 71 | 72 | $xml = $mediaInfoContainer->__toXML(); 73 | 74 | $this->assertInstanceOf('SimpleXMLElement', $xml); 75 | } 76 | 77 | public function testToXMLType(): void 78 | { 79 | $mediaInfoContainer = $this->createContainer(); 80 | 81 | $general = $mediaInfoContainer->getGeneral(); 82 | 83 | $xml = $general->__toXML(); 84 | 85 | $this->assertInstanceOf('SimpleXMLElement', $xml); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /tests/Exception/UnknownTrackTypeExceptionTest.php: -------------------------------------------------------------------------------- 1 | assertEquals($unknownTrackTypeException->getTrackType(), 'InvalidType'); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/Factory/AttributeFactoryTest.php: -------------------------------------------------------------------------------- 1 | create( 14 | 'display_aspect_ratio', 15 | [ 16 | '15.55', 17 | '15.55 Mo', 18 | ] 19 | ); 20 | 21 | $this->assertInstanceOf(Attribute\Ratio::class, $ratio); 22 | } 23 | 24 | public function testCreateRate(): void 25 | { 26 | $rate = (new AttributeFactory())->create( 27 | 'height', 28 | [ 29 | '720', 30 | '720p', 31 | ] 32 | ); 33 | 34 | $this->assertInstanceOf(Attribute\Rate::class, $rate); 35 | } 36 | 37 | public function testCreateFloatRate(): void 38 | { 39 | $floatRate = (new AttributeFactory())->create( 40 | 'frame_rate', 41 | [ 42 | '46.875', 43 | '46.875 FPS (1024 SPF)' 44 | ] 45 | ); 46 | 47 | $this->assertInstanceOf(Attribute\FloatRate::class, $floatRate); 48 | } 49 | 50 | public function testCreateSize(): void 51 | { 52 | $size = (new AttributeFactory())->create( 53 | 'file_size', 54 | [ 55 | '19316079', 56 | '18.4 MiB', 57 | ] 58 | ); 59 | 60 | $this->assertInstanceOf(Attribute\Size::class, $size); 61 | } 62 | 63 | public function testCreateMode(): void 64 | { 65 | $mode = (new AttributeFactory())->create( 66 | 'overall_bit_rate', 67 | [ 68 | 'CBR', 69 | 'Constant', 70 | ] 71 | ); 72 | 73 | $this->assertInstanceOf(Attribute\Mode::class, $mode); 74 | } 75 | 76 | public function testCreateDuration(): void 77 | { 78 | $duration = (new AttributeFactory())->create( 79 | 'duration', 80 | [ 81 | '475193', 82 | ] 83 | ); 84 | 85 | $this->assertInstanceOf(Attribute\Duration::class, $duration); 86 | } 87 | 88 | public function testCreateCover(): void 89 | { 90 | $cover = (new AttributeFactory())->create('cover_data', '01010101'); 91 | 92 | $this->assertInstanceOf(Attribute\Cover::class, $cover); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /tests/MediaInfoTest.php: -------------------------------------------------------------------------------- 1 | setConfig('command', 'new/mediainfo/path'); 14 | 15 | $mediaInfo = new MediaInfo(); 16 | $this->assertEquals(false, $mediaInfo->getConfig('urlencode')); 17 | $mediaInfo->setConfig('urlencode', true); 18 | $this->assertEquals(true, $mediaInfo->getConfig('urlencode')); 19 | 20 | $this->expectException(\Exception::class); 21 | $this->expectExceptionMessage('key "unknow_config" does\'t exist'); 22 | 23 | $mediaInfo = new MediaInfo(); 24 | $mediaInfo->setConfig('unknow_config', ''); 25 | } 26 | 27 | public function testGetConfig(): void 28 | { 29 | $mediaInfo = new MediaInfo(); 30 | $this->assertEquals(false, $mediaInfo->getConfig('urlencode')); 31 | 32 | $this->expectException(\Exception::class); 33 | $this->expectExceptionMessage('key "unknow_config" does\'t exist'); 34 | 35 | $mediaInfo = new MediaInfo(); 36 | $mediaInfo->getConfig('unknow_config'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/Parser/MediaInfoOutputParserTest.php: -------------------------------------------------------------------------------- 1 | outputPath = __DIR__.'/../fixtures/mediainfo-output.xml'; 31 | $this->outputMediainfo1710Path = __DIR__.'/../fixtures/mediainfo-17.10-output.xml'; 32 | $this->invalidOutputPath = __DIR__.'/../fixtures/mediainfo-output-invalid-types.xml'; 33 | } 34 | 35 | public function testGetMediaInfoContainerBeforeCallParse(): void 36 | { 37 | $this->expectException(\Exception::class); 38 | $mediaInfoOutputParser = new MediaInfoOutputParser(); 39 | $mediaInfoOutputParser->getMediaInfoContainer([ 40 | 'ignore_unknown_track_types' => false, 41 | 'attribute_checkers' => null, 42 | ]); 43 | } 44 | 45 | public function testGetMediaInfoContainer(): void 46 | { 47 | $mediaInfoOutputParser = new MediaInfoOutputParser(); 48 | $mediaInfoOutputParser->parse(file_get_contents($this->outputPath)); 49 | $mediaInfoContainer = $mediaInfoOutputParser->getMediaInfoContainer([ 50 | 'ignore_unknown_track_types' => false, 51 | 'attribute_checkers' => null, 52 | ]); 53 | 54 | $this->assertEquals('Mhor\MediaInfo\Container\MediaInfoContainer', get_class($mediaInfoContainer)); 55 | 56 | $this->assertEquals(1, count($mediaInfoContainer->getAudios())); 57 | $this->assertEquals(0, count($mediaInfoContainer->getVideos())); 58 | $this->assertEquals(0, count($mediaInfoContainer->getImages())); 59 | $this->assertEquals('Mhor\MediaInfo\Type\General', get_class($mediaInfoContainer->getGeneral())); 60 | 61 | $this->assertEquals(1, count($mediaInfoContainer->getAudios())); 62 | $this->assertEquals(1, count($mediaInfoContainer->getMenus())); 63 | 64 | $audios = $mediaInfoContainer->getAudios(); 65 | $this->assertEquals(20, is_array($audios[0]->get()) || $audios[0]->get() instanceof \Countable ? count($audios[0]->get()) : 0); 66 | $this->assertEquals(20974464, $audios[0]->get('samples_count')); 67 | $this->assertEquals(null, $audios[0]->get('test')); 68 | 69 | $subtitles = $mediaInfoContainer->getSubtitles(); 70 | $this->assertEquals(16, is_array($subtitles[0]->get()) || $subtitles[0]->get() instanceof \Countable ? count($subtitles[0]->get()) : 0); 71 | 72 | $this->assertTrue($subtitles[0]->has('commercial_name')); 73 | $this->assertFalse($subtitles[0]->has('unexisting_attribute')); 74 | 75 | $this->assertCount(16, $subtitles[0]->list()); 76 | $this->assertArrayHasKey('commercial_name', array_flip($subtitles[0]->list())); 77 | $this->assertArrayNotHasKey('unexisting_attribute', array_flip($subtitles[0]->list())); 78 | } 79 | 80 | public function testIgnoreInvalidTrackType(): void 81 | { 82 | $mediaInfoOutputParser = new MediaInfoOutputParser(); 83 | $mediaInfoOutputParser->parse(file_get_contents($this->invalidOutputPath)); 84 | // the xml specifically has an unknown type in it 85 | // when passing true we want to ignore/skip unknown track types 86 | $mediaInfoContainer = $mediaInfoOutputParser->getMediaInfoContainer([ 87 | 'ignore_unknown_track_types' => true, 88 | 'attribute_checkers' => null, 89 | ]); 90 | $this->assertInstanceOf(MediaInfoContainer::class, $mediaInfoContainer); 91 | } 92 | 93 | public function testThrowMediaInfoOutputParsingException(): void 94 | { 95 | $this->expectException(MediainfoOutputParsingException::class); 96 | $mediaInfoOutputParser = new MediaInfoOutputParser(); 97 | $mediaInfoOutputParser->parse(file_get_contents($this->outputMediainfo1710Path)); 98 | // will throw exception here as default behavior 99 | $mediaInfoContainer = $mediaInfoOutputParser->getMediaInfoContainer([ 100 | 'ignore_unknown_track_types' => false, 101 | 'attribute_checkers' => null, 102 | ]); 103 | } 104 | 105 | public function testThrowInvalidTrackType(): void 106 | { 107 | $this->expectException(UnknownTrackTypeException::class); 108 | $mediaInfoOutputParser = new MediaInfoOutputParser(); 109 | $mediaInfoOutputParser->parse(file_get_contents($this->invalidOutputPath)); 110 | // will throw exception here as default behavior 111 | $mediaInfoContainer = $mediaInfoOutputParser->getMediaInfoContainer([ 112 | 'ignore_unknown_track_types' => false, 113 | 'attribute_checkers' => null, 114 | ]); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /tests/Runner/MediaInfoCommandRunnerTest.php: -------------------------------------------------------------------------------- 1 | filePath = __DIR__.'/../fixtures/test.mp3'; 24 | $this->outputPath = __DIR__.'/../fixtures/mediainfo-output.xml'; 25 | } 26 | 27 | public function testRun() 28 | { 29 | $process = $this->prophesize(Process::class); 30 | $process 31 | ->run() 32 | ->shouldBeCalled() 33 | ->willReturn(1); 34 | 35 | $process 36 | ->getOutput() 37 | ->shouldBeCalled() 38 | ->willReturn(file_get_contents($this->outputPath)); 39 | 40 | $process 41 | ->isSuccessful() 42 | ->shouldBeCalled() 43 | ->willReturn(true); 44 | 45 | $mediaInfoCommandRunner = new MediaInfoCommandRunner($process->reveal()); 46 | 47 | $this->assertEquals(file_get_contents($this->outputPath), $mediaInfoCommandRunner->run()); 48 | } 49 | 50 | public function testRunException() 51 | { 52 | $this->expectException(\RuntimeException::class); 53 | 54 | $process = $this->prophesize(Process::class); 55 | $process 56 | ->run() 57 | ->shouldBeCalled() 58 | ->willReturn(0); 59 | 60 | $process 61 | ->getErrorOutput() 62 | ->shouldBeCalled() 63 | ->willReturn('Error'); 64 | 65 | $process 66 | ->isSuccessful() 67 | ->shouldBeCalled() 68 | ->willReturn(false); 69 | 70 | $mediaInfoCommandRunner = new MediaInfoCommandRunner($process->reveal()); 71 | 72 | $mediaInfoCommandRunner->run(); 73 | } 74 | 75 | public function testRunAsync() 76 | { 77 | $process = $this->prophesize(Process::class); 78 | $process 79 | ->start() 80 | ->shouldBeCalled(); 81 | 82 | $process 83 | ->wait() 84 | ->shouldBeCalled() 85 | ->willReturn(true); 86 | 87 | $process 88 | ->getOutput() 89 | ->shouldBeCalled() 90 | ->willReturn(file_get_contents($this->outputPath)); 91 | 92 | $process 93 | ->isSuccessful() 94 | ->shouldBeCalled() 95 | ->willReturn(true); 96 | 97 | $mediaInfoCommandRunner = new MediaInfoCommandRunner($process->reveal()); 98 | 99 | $mediaInfoCommandRunner->start(); 100 | 101 | // do some stuff in between, count to 5 102 | $i = 0; 103 | do { 104 | $i++; 105 | } while ($i < 5); 106 | 107 | // block and complete operation 108 | $output = $mediaInfoCommandRunner->wait(); 109 | 110 | $this->assertEquals(file_get_contents($this->outputPath), $output); 111 | } 112 | 113 | public function testRunAsyncFail() 114 | { 115 | $this->expectException(\RuntimeException::class); 116 | $this->expectExceptionMessage('Error'); 117 | 118 | $process = $this->prophesize(Process::class); 119 | $process 120 | ->start() 121 | ->shouldBeCalled(); 122 | 123 | $process 124 | ->wait() 125 | ->shouldBeCalled() 126 | ->willReturn(true); 127 | 128 | $process 129 | ->getErrorOutput() 130 | ->shouldBeCalled() 131 | ->willReturn('Error'); 132 | 133 | $process 134 | ->isSuccessful() 135 | ->shouldBeCalled() 136 | ->willReturn(false); 137 | 138 | $mediaInfoCommandRunner = new MediaInfoCommandRunner($process->reveal()); 139 | 140 | $mediaInfoCommandRunner->start(); 141 | 142 | // do some stuff in between, count to 5 143 | $i = 0; 144 | do { 145 | $i++; 146 | } while ($i < 5); 147 | 148 | // block and complete operation 149 | $mediaInfoCommandRunner->wait(); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /tests/Stub/TrackTestType.php: -------------------------------------------------------------------------------- 1 | = 0) { 11 | setlocale(LC_CTYPE, 'en_US.UTF-8'); 12 | } 13 | 14 | if ((!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__.'/../../../.composer/autoload.php'))) { 15 | exit('You must set up the project dependencies, run the following commands:'.PHP_EOL. 16 | 'curl -s http://getcomposer.org/installer | php'.PHP_EOL. 17 | 'php composer.phar install'.PHP_EOL); 18 | } 19 | 20 | return $loader; 21 | -------------------------------------------------------------------------------- /tests/fixtures/mediainfo-17.10-output.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | MediaInfoLib 4 | 5 | 6 | 242721404234216185607275687535790177333 7 | 1 8 | 1 9 | mkv 10 | Matroska 11 | 2 12 | 5247430 13 | 26.330 14 | 1594358 15 | Yes 16 | UTC 2017-05-30 15:26:21 17 | 2017-05-30 17:26:21 18 | Lavf53.24.2 19 | Lavf53.24.2 20 | 21 | 22 | 0 23 | 1 24 | 1 25 | MPEG-4 Visual 26 | Simple 27 | 1 28 | No 29 | No 30 | 0 31 | Default (H.263) 32 | V_MPEG4/ISO/ASP 33 | 1280 34 | 720 35 | 1280 36 | 720 37 | 1.000 38 | 1.778 39 | VFR 40 | YUV 41 | 4:2:0 42 | 8 43 | Progressive 44 | Lossy 45 | 0.000 46 | Lavc54.92.100 47 | Yes 48 | No 49 | 50 | 51 | 1 52 | 2 53 | 2 54 | AAC 55 | LC 56 | A_AAC-2 57 | 26.330 58 | 6 59 | Front: L C R, Side: L R, LFE 60 | C L R Ls Rs LFE 61 | 1024 62 | 48000 63 | 1263840 64 | 46.875 65 | Lossy 66 | 0.005 67 | Container 68 | Yes 69 | No 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /tests/fixtures/mediainfo-output-invalid-types.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 284 6 | 1 7 | General 8 | General 9 | 0 10 | 1 11 | MPEG Audio 12 | MPEG Audio 13 | MPEG-1 Audio layer 3 14 | test.mp3 15 | test.mp3 16 | mp3 17 | MPEG Audio 18 | MPEG Audio 19 | m1a mpa1 mp1 m2a mpa2 mp2 mp3 20 | MPEG Audio 21 | audio/mpeg 22 | MPEG Audio 23 | MPEG Audio 24 | m1a mpa1 mp1 m2a mpa2 mp2 mp3 25 | 19316079 26 | 18.4 MiB 27 | 18 MiB 28 | 18 MiB 29 | 18.4 MiB 30 | 18.42 MiB 31 | 475193 32 | 7mn 55s 33 | 7mn 55s 193ms 34 | 7mn 55s 35 | 00:07:55.193 36 | CBR 37 | Constant 38 | 320000 39 | 320 Kbps 40 | 308340 41 | 301 KiB (2%) 42 | 301 KiB 43 | 301 KiB 44 | 301 KiB 45 | 301.1 KiB 46 | 301 KiB (2%) 47 | 0.01596 48 | Track Title 49 | Album Title 50 | Various Artists 51 | Track Title 52 | 2 53 | 2 54 | Track Artist 55 | 2014 56 | sample_binary_cover 57 | UTC 2014-12-06 16:43:30 58 | 2014-12-06 17:43:30 59 | 60 | 61 | 62 | 222 63 | 1 64 | Audio 65 | Audio 66 | 0 67 | MPEG Audio 68 | MPEG Audio 69 | Version 1 70 | Layer 3 71 | audio/mpeg 72 | MPA1L3 73 | MPEG-1 Audio layer 3 74 | 475611 75 | 7mn 55s 76 | 7mn 55s 611ms 77 | 7mn 55s 78 | 00:07:55.611 79 | CBR 80 | Constant 81 | 320000 82 | 320 Kbps 83 | 2 84 | 2 channels 85 | 44100 86 | 44.1 KHz 87 | 20974464 88 | 18207 89 | Lossy 90 | Lossy 91 | 19007739 92 | 18.1 MiB (98%) 93 | 18 MiB 94 | 18 MiB 95 | 18.1 MiB 96 | 18.13 MiB 97 | 18.1 MiB (98%) 98 | 0.98404 99 | 100 | 101 | 195 102 | 8 103 | Text 104 | Text 105 | 6 106 | 7 107 | 9 108 | 11 109 | 11 110 | 652628868 111 | UTF-8 112 | UTF-8 113 | S_TEXT/UTF8 114 | UTF-8 Plain Text 115 | S_TEXT/UTF8 116 | UTF-8 117 | UTF-8 Plain Text 118 | ja 119 | Japanese 120 | Japanese 121 | ja 122 | jpn 123 | ja 124 | No 125 | No 126 | No 127 | No 128 | 129 | 130 | 131 | 132 | 1 133 | test 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /tests/fixtures/mediainfo-output.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 284 6 | 1 7 | General 8 | General 9 | 0 10 | 1 11 | MPEG Audio 12 | MPEG Audio 13 | MPEG-1 Audio layer 3 14 | test.mp3 15 | test.mp3 16 | mp3 17 | MPEG Audio 18 | MPEG Audio 19 | m1a mpa1 mp1 m2a mpa2 mp2 mp3 20 | MPEG Audio 21 | audio/mpeg 22 | MPEG Audio 23 | MPEG Audio 24 | m1a mpa1 mp1 m2a mpa2 mp2 mp3 25 | 19316079 26 | 18.4 MiB 27 | 18 MiB 28 | 18 MiB 29 | 18.4 MiB 30 | 18.42 MiB 31 | 475193 32 | 7mn 55s 33 | 7mn 55s 193ms 34 | 7mn 55s 35 | 00:07:55.193 36 | test_field 37 | CBR 38 | Constant 39 | 320000 40 | 320 Kbps 41 | 308340 42 | 301 KiB (2%) 43 | 301 KiB 44 | 301 KiB 45 | 301 KiB 46 | 301.1 KiB 47 | 301 KiB (2%) 48 | 0.01596 49 | Track Title 50 | Album Title 51 | Various Artists 52 | Track Title 53 | 2 54 | 2 55 | Track Artist 56 | 2014 57 | sample_binary_cover 58 | UTC 2014-12-06 16:43:30 59 | 2014-12-06 17:43:30 60 | 61 | 62 | 63 | 222 64 | 1 65 | Audio 66 | 0 67 | MPEG Audio 68 | MPEG Audio 69 | Version 1 70 | Layer 3 71 | audio/mpeg 72 | MPA1L3 73 | MPEG-1 Audio layer 3 74 | 475611 75 | 7mn 55s 76 | 7mn 55s 611ms 77 | 7mn 55s 78 | 00:07:55.611 79 | CBR 80 | Constant 81 | 320000 82 | 320 Kbps 83 | 2 84 | 2 channels 85 | 44100 86 | 44.1 KHz 87 | 20974464 88 | 18207 89 | Lossy 90 | Lossy 91 | 19007739 92 | 18.1 MiB (98%) 93 | 18 MiB 94 | 18 MiB 95 | 18.1 MiB 96 | 18.13 MiB 97 | 18.1 MiB (98%) 98 | 0.98404 99 | 100 | 101 | 195 102 | 8 103 | Text 104 | Text 105 | 6 106 | 7 107 | 9 108 | 11 109 | 11 110 | 652628868 111 | UTF-8 112 | UTF-8 113 | S_TEXT/UTF8 114 | UTF-8 Plain Text 115 | S_TEXT/UTF8 116 | UTF-8 117 | UTF-8 Plain Text 118 | ja 119 | Japanese 120 | Japanese 121 | ja 122 | jpn 123 | ja 124 | No 125 | No 126 | No 127 | No 128 | 129 | 130 | 84 131 | 1 132 | Menu 133 | Menu 134 | 0 135 | 77 136 | 84 137 | <_00_00_00000>en:Chapter 1 138 | <_00_01_35000>en:Chapter 2 139 | <_00_03_04800>en:Chapter 3 140 | <_00_13_05200>en:Chapter 4 141 | <_00_22_14700>en:Chapter 5 142 | <_00_23_44600>en:Chapter 6 143 | <_00_24_01000>en:Chapter 7 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /tests/fixtures/test.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhor/php-mediainfo/c0b31474d6fdfadf44e7cbf3af718b68d35c8695/tests/fixtures/test.mp3 --------------------------------------------------------------------------------