{"id":19544029,"url":"https://github.com/soluble-io/soluble-mediatools","last_synced_at":"2025-09-04T05:47:44.001Z","repository":{"id":55508086,"uuid":"136909541","full_name":"soluble-io/soluble-mediatools","owner":"soluble-io","description":"Video / audio conversion, thumbnailing and more ! PHP FFmpeg wrapper","archived":false,"fork":false,"pushed_at":"2020-12-25T12:38:23.000Z","size":5234,"stargazers_count":145,"open_issues_count":1,"forks_count":11,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-07-08T12:26:54.031Z","etag":null,"topics":["converter","ffmpeg","ffmpeg-wrapper","ffprobe","psr-11","psr-16","psr-3","thumbnailer","transcoder","video","video-converter"],"latest_commit_sha":null,"homepage":"https://soluble-io.github.io/soluble-mediatools/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/soluble-io.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-06-11T10:14:58.000Z","updated_at":"2025-06-04T19:08:01.000Z","dependencies_parsed_at":"2022-08-15T02:01:02.821Z","dependency_job_id":null,"html_url":"https://github.com/soluble-io/soluble-mediatools","commit_stats":null,"previous_names":[],"tags_count":46,"template":false,"template_full_name":null,"purl":"pkg:github/soluble-io/soluble-mediatools","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soluble-io%2Fsoluble-mediatools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soluble-io%2Fsoluble-mediatools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soluble-io%2Fsoluble-mediatools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soluble-io%2Fsoluble-mediatools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/soluble-io","download_url":"https://codeload.github.com/soluble-io/soluble-mediatools/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soluble-io%2Fsoluble-mediatools/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267988458,"owners_count":24176996,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-31T02:00:08.723Z","response_time":66,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["converter","ffmpeg","ffmpeg-wrapper","ffprobe","psr-11","psr-16","psr-3","thumbnailer","transcoder","video","video-converter"],"created_at":"2024-11-11T03:24:11.445Z","updated_at":"2025-07-31T04:34:39.648Z","avatar_url":"https://github.com/soluble-io.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Logo](./docs/assets/images/mediatools.png)  \n\n[![PHP 7.1+](https://img.shields.io/badge/php-7.1+-ff69b4.svg)](https://packagist.org/packages/soluble/mediatools)\n[![Build Status](https://travis-ci.org/soluble-io/soluble-mediatools.svg?branch=master)](https://travis-ci.org/soluble-io/soluble-mediatools)\n[![Coverage](https://codecov.io/gh/soluble-io/soluble-mediatools/branch/master/graph/badge.svg)](https://codecov.io/gh/soluble-io/soluble-mediatools)\n[![Code Quality](https://scrutinizer-ci.com/g/soluble-io/soluble-mediatools/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/soluble-io/soluble-mediatools/?branch=master)\n[![Latest Stable Version](https://poser.pugx.org/soluble/mediatools/v/stable.svg)](https://packagist.org/packages/soluble/mediatools)\n[![Total Downloads](https://poser.pugx.org/soluble/mediatools/downloads.png)](https://packagist.org/packages/soluble/mediatools)\n![PHPStan](https://img.shields.io/badge/style-level%207-brightgreen.svg?style=flat-square\u0026label=phpstan)\n[![License](https://poser.pugx.org/soluble/mediatools/license.png)](https://packagist.org/packages/soluble/mediatools)\n\nFlexible audio/video conversions and thumbnailing for hi*php*ies.\nWraps around [ffmpeg](https://www.ffmpeg.org/) and [ffprobe](https://www.ffmpeg.org/ffprobe.html)\nand exposes most of their features, like scaling, clipping, filters, transcoding, audio extraction \nand much more.   \n\nTo prevent limitations, the API rather focus on providing developer fine-tuned parameters \nthan giving ready-made recipes. Transcoding and conversions generally\nrequires specific processing, [judge by yourself](https://soluble-io.github.io/soluble-mediatools/video-conversion-service/#notes).\nTo help starting, the documentation includes a lot of examples and snippets you\ncan easily try and tune later. Check also [alternatives](./README.md#alternatives) wrappers\nfor ffmpeg, they are good and sometimes offer more magic if you're looking for it.\n    \nOn another side, it likes [PSR](https://www.php-fig.org/psr/) (psr-log, psr-container, psr-simplecache), tastes php 7.1 in strict mode, tries to fail as early as possible \nwith clear exception messages and ensure that substitution is possible when you need to customize\n*(SOLID friendly)*. \n\nUnder the hood, it relies on the battle-tested [symfony/process](https://symfony.com/doc/current/components/process.html), its only dependency.\n     \n## Documentation \n\nAll is here: **[https://soluble-io.github.io/soluble-mediatools/](https://soluble-io.github.io/soluble-mediatools/)**\n\n## Requirements\n\n- PHP 7.1+\n- FFmpeg/FFProbe 3.4+, 4.0+.\n \n## Features\n\n\u003e Check the [doc](https://soluble-io.github.io/soluble-mediatools/) to get a more detailed overview !!!\n\n### Implemented services\n\n#### VideoConverter\n\n\u003e Full doc: [here](https://soluble-io.github.io/soluble-mediatools/video-conversion-service/)\n\n```php\n\u003c?php\nuse Soluble\\MediaTools\\Video\\Config\\FFMpegConfig;\nuse Soluble\\MediaTools\\Video\\Exception\\ConverterExceptionInterface;\nuse Soluble\\MediaTools\\Video\\{VideoConverter, VideoConvertParams};\n\n$converter = new VideoConverter(new FFMpegConfig('/path/to/ffmpeg'));\n\n$params = (new VideoConvertParams())\n    -\u003ewithVideoCodec('libx264')    \n    -\u003ewithStreamable(true)\n    -\u003ewithCrf(24);                  \n    \ntry {    \n    $converter-\u003econvert(\n        '/path/inputFile.mov', \n        '/path/outputFile.mp4', \n        $params\n    );    \n} catch(ConverterExceptionInterface $e) {\n    // See chapter about exception !!!    \n}\n       \n```  \n \n#### VideoInfoReader \n\n\u003e Full doc: [here](https://soluble-io.github.io/soluble-mediatools/video-info-service/)\n\n```php\n\u003c?php\nuse Soluble\\MediaTools\\Video\\Config\\FFProbeConfig;\nuse Soluble\\MediaTools\\Video\\Exception\\InfoReaderExceptionInterface;\nuse Soluble\\MediaTools\\Video\\VideoInfoReader;\nuse Soluble\\MediaTools\\Video\\VideoInfo;\n\n$infoReader = new VideoInfoReader(new FFProbeConfig('/path/to/ffprobe'));\n\n// Step 1: Read a media file\n\ntry {\n    $info = $infoReader-\u003egetInfo('/path/video.mp4');\n} catch (InfoReaderExceptionInterface $e) {\n    // not a valid video (see exception)\n}\n\n$duration = $info-\u003egetDuration(); // total duration\n$format   = $info-\u003egetFormatName(); // container format: mkv, mp4\n\n// Step 2: Media streams info (video, subtitle, audio, data).\n\n// Example with first video stream (streams are iterable)\n\ntry {    \n    $video   = $info-\u003egetVideoStreams()-\u003egetFirst();\n} catch (\\Soluble\\MediaTools\\Video\\Exception\\NoStreamException $e) {\n    // No video stream, \n}\n    \n$codec   = $video-\u003egetCodecName(); // i.e: vp9\n$fps     = $video-\u003egetFps($decimals=0); // i.e: 24\n$width   = $video-\u003egetWidth(); // i.e: 1080\n$ratio   = $video-\u003egetAspectRatio();\n\n// Alternate example  \n\nif ($info-\u003ecountStreams(VideoInfo::STREAM_TYPE_SUBTITLE) \u003e 0) {\n    $sub  = $info-\u003egetSubtitleStreams()-\u003egetFirst();\n    $sub-\u003egetCodecName(); // webvtt\n}\n\n``` \n\n#### VideoThumbGenerator \n\n\u003e Full doc: [here](https://soluble-io.github.io/soluble-mediatools/video-thumb-service/)\n\n```php\n\u003c?php\nuse Soluble\\MediaTools\\Video\\Config\\FFMpegConfig;\nuse Soluble\\MediaTools\\Video\\Exception\\ConverterExceptionInterface;\nuse Soluble\\MediaTools\\Video\\{VideoThumbGenerator, VideoThumbParams, SeekTime};\n\n$generator = new VideoThumbGenerator(new FFMpegConfig('/path/to/ffmpeg'));\n\n$params = (new VideoThumbParams())\n    -\u003ewithTime(1.25);\n    \ntry {    \n    $generator-\u003emakeThumbnail(\n        '/path/inputFile.mov', \n        '/path/outputFile.jpg', \n        $params\n    );    \n} catch(ConverterExceptionInterface $e) {\n    // See chapter about exception !!!    \n}\n       \n``` \n\n#### VideoAnalyzer\n\n\u003e Full doc: [here](https://soluble-io.github.io/soluble-mediatools/video-detection-service/)\n\n```php\n\u003c?php\nuse Soluble\\MediaTools\\Video\\Config\\FFMpegConfig;\nuse Soluble\\MediaTools\\Video\\Exception\\AnalyzerExceptionInterface;\nuse Soluble\\MediaTools\\Video\\VideoAnalyzer;\n\n$analyzer = new VideoAnalyzer(new FFMpegConfig('/path/to/ffmpeg'));\n\ntry {    \n    $interlaceGuess = $analyzer-\u003edetectInterlacement(\n        '/path/input.mov',\n        // Optional:\n        //   $maxFramesToAnalyze, default: 1000\n        $maxFramesToAnalyze = 200\n    );\n    \n} catch(AnalyzerExceptionInterface $e) {\n    // See chapter about exception !!!    \n}\n\n$interlaced = $interlaceGuess-\u003eisInterlaced(\n    // Optional: \n    //  $threshold, default 0.25 (if \u003e=25% interlaced frames, then true) \n    0.25\n);\n\n``` \n\n## Alternatives\n\n- [https://github.com/PHP-FFMpeg/PHP-FFMpeg](https://github.com/PHP-FFMpeg/PHP-FFMpeg)\n- [https://github.com/char0n/ffmpeg-php](https://github.com/char0n/ffmpeg-php) \n   \n## Coding standards and interop\n\n* [PSR 4 Autoloader](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md)\n* [PSR 3 Logger interface](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md)\n* [PSR 2 Coding Style Guide](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoluble-io%2Fsoluble-mediatools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoluble-io%2Fsoluble-mediatools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoluble-io%2Fsoluble-mediatools/lists"}