p3sdev / php-ytdlp-wrapper
Robust PHP 8.4 yt-dlp wrapper with Symfony 7 bundle integration
Package info
github.com/PavlenkoEvgeniy/php-ytdlp-wrapper
Type:symfony-bundle
pkg:composer/p3sdev/php-ytdlp-wrapper
Requires
- php: ^8.4
- symfony/config: ^7.4.4
- symfony/dependency-injection: ^7.4.5
- symfony/http-kernel: ^7.4.5
- symfony/process: ^7.4.5
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.94
- peckphp/peck: ^0.2.0
- phpstan/phpstan: ^2.1.39
- phpunit/phpunit: ^11.5.53
- vimeo/psalm: ^6.15.1
Suggests
- symfony/framework-bundle: Required for full Symfony bundle integration
README
Robust yt-dlp wrapper for PHP 8.4 with a ready-to-use Symfony 7 bundle.
✨ Features
- Safe process execution through
symfony/process - Structured request object (
YtDlpRequest) - Raw execution + JSON extraction helpers
- Strong error model (
BinaryNotFoundException,ProcessFailedException) - Symfony 7 service wiring and configurable bundle options
📋 Requirements
- PHP 8.4+
yt-dlpinstalled on the host machine (binary inPATHor custom path)
📦 Install
composer require p3sdev/php-ytdlp-wrapper
🧩 Symfony 7 Bundle Setup
1️⃣ Register bundle
If Symfony Flex does not auto-register it, add to config/bundles.php:
return [ // ... P3s\YtDlp\YtDlpBundle::class => ['all' => true], ];
2️⃣ Configure bundle
Create config/packages/yt_dlp.yaml:
yt_dlp: binary_path: 'yt-dlp' default_arguments: ['--no-warnings'] working_directory: ~ timeout: 300 environment: {}
🍱 Symfony Flex Recipe
A ready-to-submit Symfony Flex recipe scaffold is available in:
flex-recipe/1.0
To publish it for auto-install support, submit that recipe to symfony/recipes-contrib.
🚀 Usage in Symfony
Inject P3s\YtDlp\YtDlpClientInterface into your service:
<?php declare(strict_types=1); namespace App\Service; use P3s\YtDlp\YtDlpClientInterface; final class VideoService { public function __construct(private readonly YtDlpClientInterface $ytDlp) { } public function download(string $url): void { $result = $this->ytDlp->download($url, [ 'format' => 'bv*+ba/b', 'output' => '%(title)s.%(ext)s', 'paths' => '/tmp/videos', ]); $result->requireSuccessful(); } }
🛠️ Core API
⬇️ download(string|array $urls, array $options = []): ProcessResult
Runs yt-dlp for download/processing workflows.
🧠 rawJson(string|array $urls, array $options = []): ProcessResult
Runs metadata mode (--dump-json --skip-download --no-warnings) and returns full process output.
🔎 extractInfo(string|array $urls, array $options = []): array
Convenience method that returns parsed JSON lines.
⚙️ run(YtDlpRequest $request): ProcessResult
Low-level execution with full control over options, flags, and extra arguments.
🧾 YtDlpRequest
$request = YtDlpRequest::create( urls: ['https://www.youtube.com/watch?v=BaW_jenozKc'], options: [ 'format' => 'bestvideo+bestaudio/best', 'cookies' => '/secure/cookies.txt', 'proxy' => 'socks5://127.0.0.1:1080', 'playlist-items' => '1:3', 'print' => ['id', 'title'], ], flags: ['no-progress'], extraArguments: ['--'], );
⚠️ Errors
BinaryNotFoundException: custom binary path does not exist or is not executableProcessFailedException: command returned non-zero exit codeYtDlpException: base runtime exception
📝 Notes
- The wrapper maps options directly to
yt-dlpCLI flags (format->--format). - Arrays in option values are emitted as repeated flags.
- Boolean
trueemits a flag,falseis ignored.
📄 License
MIT. See LICENSE.
✅ CI
GitHub Actions runs tests on push and pull requests for PHP 8.4 and 8.5.
Workflow file: .github/workflows/tests.yml