{"id":45667242,"url":"https://github.com/foxws/laravel-streamer","last_synced_at":"2026-04-26T15:01:29.178Z","repository":{"id":336640486,"uuid":"1150532066","full_name":"foxws/laravel-streamer","owner":"foxws","description":"A Laravel integration for Google's Shaka Streamer, enabling you to create adaptive streaming content (HLS, DASH) with Laravel. ","archived":false,"fork":false,"pushed_at":"2026-03-18T10:40:54.000Z","size":414,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-26T16:20:10.473Z","etag":null,"topics":["dash","hls","laravel","shaka","shaka-packager","shaka-streamer","transcode","vod"],"latest_commit_sha":null,"homepage":"","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/foxws.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"Foxws"}},"created_at":"2026-02-05T11:46:15.000Z","updated_at":"2026-03-18T10:31:09.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/foxws/laravel-streamer","commit_stats":null,"previous_names":["foxws/laravel-streamer"],"tags_count":16,"template":false,"template_full_name":"spatie/package-skeleton-laravel","purl":"pkg:github/foxws/laravel-streamer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foxws%2Flaravel-streamer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foxws%2Flaravel-streamer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foxws%2Flaravel-streamer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foxws%2Flaravel-streamer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/foxws","download_url":"https://codeload.github.com/foxws/laravel-streamer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foxws%2Flaravel-streamer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32301330,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T09:34:17.070Z","status":"ssl_error","status_checked_at":"2026-04-26T09:34:00.993Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["dash","hls","laravel","shaka","shaka-packager","shaka-streamer","transcode","vod"],"created_at":"2026-02-24T10:05:09.933Z","updated_at":"2026-04-26T15:01:29.172Z","avatar_url":"https://github.com/foxws.png","language":"PHP","readme":"# Laravel Shaka Streamer\n\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/foxws/laravel-streamer.svg?style=flat-square)](https://packagist.org/packages/foxws/laravel-streamer)\n[![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/foxws/laravel-streamer/run-tests.yml?branch=main\u0026label=tests\u0026style=flat-square)](https://github.com/foxws/laravel-streamer/actions?query=workflow%3Arun-tests+branch%3Amain)\n[![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/foxws/laravel-streamer/fix-php-code-style-issues.yml?branch=main\u0026label=code%20style\u0026style=flat-square)](https://github.com/foxws/laravel-streamer/actions?query=workflow%3A\"Fix+PHP+code+style+issues\"+branch%3Amain)\n[![Total Downloads](https://img.shields.io/packagist/dt/foxws/laravel-streamer.svg?style=flat-square)](https://packagist.org/packages/foxws/laravel-streamer)\n\nA Laravel integration for [Google's Shaka Streamer](https://github.com/shaka-project/shaka-streamer), enabling you to package adaptive streaming content (HLS, DASH) with a fluent, Laravel-style API.\n\n```php\nuse Foxws\\Streamer\\Facades\\Streamer;\n\nStreamer::fromDisk('s3')\n    -\u003eopen('videos/input.mp4')\n    -\u003eaddVideoStream('videos/input.mp4', 'video.mp4')\n    -\u003eaddAudioStream('videos/input.mp4', 'audio.mp4')\n    -\u003ewithHlsMasterPlaylist('master.m3u8')\n    -\u003ewithSegmentDuration(6)\n    -\u003eexport()\n    -\u003etoDisk('export')\n    -\u003esave();\n```\n\n## Features\n\n- 🎬 **Fluent API** — Laravel-style chainable methods for packaging media\n- 📁 **Filesystem Integration** — Read from and write to any Laravel disk (local, S3, etc.)\n- 🎯 **Adaptive Bitrate** — Create multi-quality HLS \u0026 DASH streams\n- 🔒 **AES Encryption** — Built-in content protection with optional key rotation\n- 📺 **Dynamic Manifests** — Rewrite HLS playlists and DASH MPDs with signed URLs at serve-time\n- 📡 **Events** — Hooks for `StreamingStarted`, `StreamingCompleted`, and `StreamingFailed`\n- 📝 **PHP 8.3+** — Strict types, readonly properties, and modern PHP throughout\n\n## Documentation\n\n- [Quick Reference](docs/QUICK_REFERENCE.md) — Complete API at a glance\n- [Configuration](docs/CONFIGURATION.md) — Environment variables and config options\n- [AES Encryption](docs/AES_ENCRYPTION.md) — Encryption with key rotation\n- [URL Resolvers](docs/URL_RESOLVERS.md) — Signed URLs for HLS \u0026 DASH\n- [Troubleshooting](docs/TROUBLESHOOTING.md) — Common issues and solutions\n\n## Requirements\n\n- PHP 8.3+\n- Laravel 12 or 13\n- [Shaka Streamer](https://github.com/shaka-project/shaka-streamer) binary (`pip install shaka-streamer`)\n\n## Installation\n\n```bash\ncomposer require foxws/laravel-streamer\n```\n\nPublish the configuration file:\n\n```bash\nphp artisan vendor:publish --tag=\"streamer-config\"\n```\n\nVerify the binary is accessible:\n\n```bash\nphp artisan streamer:info\n```\n\n## Quick Start\n\n### Basic Packaging\n\n```php\nuse Foxws\\Streamer\\Facades\\Streamer;\n\nStreamer::open('input.mp4')\n    -\u003eaddVideoStream('input.mp4', 'video.mp4')\n    -\u003eaddAudioStream('input.mp4', 'audio.mp4')\n    -\u003ewithHlsMasterPlaylist('master.m3u8')\n    -\u003eexport()\n    -\u003esave();\n```\n\n### Cross-Disk Workflows\n\nRead from one disk, write to another:\n\n```php\nStreamer::fromDisk('s3')\n    -\u003eopen('videos/input.mp4')\n    -\u003eaddVideoStream('videos/input.mp4', 'video.mp4')\n    -\u003eaddAudioStream('videos/input.mp4', 'audio.mp4')\n    -\u003ewithHlsMasterPlaylist('master.m3u8')\n    -\u003eexport()\n    -\u003etoDisk('export')\n    -\u003etoPath('streams/')\n    -\u003ewithVisibility('public')\n    -\u003esave();\n```\n\n### Encryption\n\n```php\n// AES-128 encryption with auto-generated key\nStreamer::open('input.mp4')\n    -\u003eaddVideoStream('input.mp4', 'video.mp4')\n    -\u003eaddAudioStream('input.mp4', 'audio.mp4')\n    -\u003ewithHlsMasterPlaylist('master.m3u8')\n    -\u003ewithAESEncryption()\n    -\u003eexport()\n    -\u003esave();\n\n// With key rotation (rotates every 60 seconds)\nStreamer::open('input.mp4')\n    -\u003eaddVideoStream('input.mp4', 'video.mp4')\n    -\u003eaddAudioStream('input.mp4', 'audio.mp4')\n    -\u003ewithHlsMasterPlaylist('master.m3u8')\n    -\u003ewithAESEncryption('key', 'cenc')\n    -\u003ewithKeyRotationDuration(60)\n    -\u003eexport()\n    -\u003etoDisk('s3')\n    -\u003esave();\n```\n\nSee the [AES Encryption Guide](docs/AES_ENCRYPTION.md) for protection schemes, codec-specific examples, and key management.\n\n### Dynamic URL Resolvers\n\nServe HLS and DASH content with signed URLs — useful for S3, CDNs, or multi-tenant apps.\n\n**HLS:**\n\n```php\nuse Foxws\\Streamer\\Http\\DynamicHLSPlaylist;\nuse Illuminate\\Support\\Facades\\Storage;\n\nreturn (new DynamicHLSPlaylist('s3'))\n    -\u003eopen(\"videos/{$video-\u003eid}/master.m3u8\")\n    -\u003esetKeyUrlResolver(fn (string $key) =\u003e Storage::disk('s3')-\u003etemporaryUrl(\n        \"videos/{$video-\u003eid}/{$key}\",\n        now()-\u003eaddHour(),\n    ))\n    -\u003esetMediaUrlResolver(fn (string $file) =\u003e Storage::disk('s3')-\u003etemporaryUrl(\n        \"videos/{$video-\u003eid}/{$file}\",\n        now()-\u003eaddHours(2),\n    ))\n    -\u003esetPlaylistUrlResolver(fn (string $playlist) =\u003e route('video.playlist', [\n        'video' =\u003e $video,\n        'playlist' =\u003e $playlist,\n    ]))\n    -\u003etoResponse(request());\n```\n\n**DASH:**\n\n```php\nuse Foxws\\Streamer\\Http\\DynamicDASHManifest;\nuse Illuminate\\Support\\Facades\\Storage;\n\nreturn (new DynamicDASHManifest('s3'))\n    -\u003eopen(\"videos/{$video-\u003eid}/manifest.mpd\")\n    -\u003esetMediaUrlResolver(fn (string $file) =\u003e Storage::disk('s3')-\u003etemporaryUrl(\n        \"videos/{$video-\u003eid}/{$file}\",\n        now()-\u003eaddHours(2),\n    ))\n    -\u003esetInitUrlResolver(fn (string $file) =\u003e Storage::disk('s3')-\u003etemporaryUrl(\n        \"videos/{$video-\u003eid}/{$file}\",\n        now()-\u003eaddHours(2),\n    ))\n    -\u003etoResponse(request());\n```\n\nSee [URL Resolvers](docs/URL_RESOLVERS.md) for more details.\n\n### Events\n\nListen to streaming lifecycle events:\n\n| Event                | Payload                                              |\n| -------------------- | ---------------------------------------------------- |\n| `StreamingStarted`   | `MediaCollection $mediaCollection`, `array $options` |\n| `StreamingCompleted` | `StreamerResult $result`, `float $executionTime`     |\n| `StreamingFailed`    | `Exception $exception`, `float $executionTime`       |\n\n### Post-Export Inspection\n\nAfter saving, you can inspect the result:\n\n```php\n$exporter = Streamer::open('input.mp4')\n    -\u003eaddVideoStream('input.mp4', 'video.mp4')\n    -\u003eaddAudioStream('input.mp4', 'audio.mp4')\n    -\u003ewithHlsMasterPlaylist('master.m3u8')\n    -\u003eexport();\n\n$exporter-\u003eafterSaving(function ($exporter, $result) {\n    $summary = $exporter-\u003egetCopySummary();\n    // ['total' =\u003e 12, 'copied' =\u003e 12, 'failed' =\u003e 0, 'totalSize' =\u003e 8421376]\n\n    $keys = $result-\u003egetUploadedEncryptionKeys();\n});\n\n$exporter-\u003etoDisk('s3')-\u003esave();\n```\n\n## API Reference\n\n### `Streamer` Facade → `MediaOpener`\n\n| Method                               | Description                                      |\n| ------------------------------------ | ------------------------------------------------ |\n| `fromDisk($disk)`                    | Set the source filesystem disk                   |\n| `open($paths)`                       | Open one or more media files                     |\n| `openFromDisk($disk, $paths)`        | Set disk and open files in one call              |\n| `get()`                              | Get the `MediaCollection`                        |\n| `export()`                           | Start the export chain (returns `MediaExporter`) |\n| `dynamicHLSPlaylist(?string $disk)`  | Create a `DynamicHLSPlaylist` instance           |\n| `dynamicDASHManifest(?string $disk)` | Create a `DynamicDASHManifest` instance          |\n| `cleanupTemporaryFiles()`            | Delete all temporary directories                 |\n\n### Stream Configuration (via `MediaOpener` → `Streamer`)\n\n| Method                                             | Description                                                     |\n| -------------------------------------------------- | --------------------------------------------------------------- |\n| `addVideoStream($input, $output, $options)`        | Add a video stream                                              |\n| `addAudioStream($input, $output, $options)`        | Add an audio stream                                             |\n| `addTextStream($input, $output, $options)`         | Add a text/subtitle stream                                      |\n| `addStream(array $stream)`                         | Add a raw Shaka stream descriptor (`in`, `stream`, `output`, …) |\n| `withHlsMasterPlaylist($path)`                     | Set HLS output                                                  |\n| `withMpdOutput($path)`                             | Set DASH/MPD output                                             |\n| `withSegmentDuration(int $seconds)`                | Set segment duration                                            |\n| `withManifestFormat(array $formats)`               | Set manifest formats (e.g. `['dash', 'hls']`)                   |\n| `withResolutions(array $resolutions)`              | Set encoding resolutions                                        |\n| `withVideoCodecs(array $codecs)`                   | Set video codecs (e.g. `['h264', 'hw:vp9']`)                    |\n| `withAudioCodecs(array $codecs)`                   | Set audio codecs (e.g. `['aac', 'opus']`)                       |\n| `withSegmentPerFile(bool $enabled)`                | Enable segment-per-file output                                  |\n| `withLowLatencyDashMode(bool $enabled)`            | Enable low-latency DASH                                         |\n| `withStreamingMode(string $mode)`                  | Set mode (`'vod'` or `'live'`)                                  |\n| `withEncryption(array $config)`                    | Set raw encryption config                                       |\n| `withAESEncryption($keyFilename, $scheme, $label)` | Auto-generate AES encryption key                                |\n| `withKeyRotationDuration(int $seconds)`            | Enable key rotation (requires `'cenc'` or `'cbcs'`)             |\n| `withOption($key, $value)`                         | Set a custom pipeline option                                    |\n| `withOptions(array $options)`                      | Set multiple custom pipeline options                            |\n| `getCommand()`                                     | Get the built config array (for debugging)                      |\n\n### `MediaExporter` (returned by `export()`)\n\n| Method                               | Description                                   |\n| ------------------------------------ | --------------------------------------------- |\n| `toDisk($disk)`                      | Set target disk for output                    |\n| `toPath(string $path)`               | Set target subdirectory                       |\n| `withVisibility(string $visibility)` | Set file visibility (`'public'`, `'private'`) |\n| `afterSaving(callable $callback)`    | Register post-save callback                   |\n| `save(?string $path)`                | Execute packaging and copy files to disk      |\n| `getCommand()`                       | Get the built config array                    |\n| `dd()`                               | Dump config and die                           |\n| `getCopySummary()`                   | Get `{total, copied, failed, totalSize}`      |\n| `getCopiedFiles()`                   | Get array of successfully copied files        |\n| `getFailedFiles()`                   | Get array of failed file copies               |\n| `hasCopyFailures()`                  | Check if any files failed to copy             |\n\n### `DynamicHLSPlaylist`\n\n| Method                             | Description                                        |\n| ---------------------------------- | -------------------------------------------------- |\n| `open(string $path)`               | Open a playlist file                               |\n| `setKeyUrlResolver(callable)`      | Resolve encryption key URLs                        |\n| `setMediaUrlResolver(callable)`    | Resolve media segment URLs                         |\n| `setPlaylistUrlResolver(callable)` | Resolve sub-playlist URLs                          |\n| `get()`                            | Get processed playlist content                     |\n| `all()`                            | Get all processed playlists (master + variants)    |\n| `toResponse($request)`             | Return as `application/vnd.apple.mpegurl` response |\n\n### `DynamicDASHManifest`\n\n| Method                          | Description                               |\n| ------------------------------- | ----------------------------------------- |\n| `open(string $path)`            | Open a manifest file                      |\n| `setMediaUrlResolver(callable)` | Resolve media segment URLs                |\n| `setInitUrlResolver(callable)`  | Resolve initialization segment URLs       |\n| `get()`                         | Get processed manifest content            |\n| `toResponse($request)`          | Return as `application/dash+xml` response |\n\n## Configuration\n\nKey options in `config/streamer.php`:\n\n| Option                     | Default                             | Description                                    |\n| -------------------------- | ----------------------------------- | ---------------------------------------------- |\n| `streamer.streamer_binary` | `'shaka-streamer'`                  | Path to the Shaka Streamer binary              |\n| `timeout`                  | `14400` (4h)                        | Process timeout in seconds                     |\n| `temporary_files_root`     | `storage_path('app/streamer/temp')` | Directory for temporary files                  |\n| `cache_files_root`         | `'/dev/shm'`                        | Fast storage for small files (keys, manifests) |\n| `log_channel`              | `null`                              | Log channel for streamer output                |\n\nSee [Configuration](docs/CONFIGURATION.md) for all options and environment variables.\n\n## Testing\n\n```bash\ncomposer test\n```\n\n## Contributing\n\nPlease see [CONTRIBUTING](CONTRIBUTING.md) for details.\n\n## Security\n\nIf you discover a security vulnerability, please report it via a private channel (e.g. email or GitHub Security Advisories) rather than publicly disclosing it.\n\n## Acknowledgments\n\nThis package was inspired by and learned from:\n\n- [Laravel FFmpeg](https://github.com/protonemedia/laravel-ffmpeg) — Architecture patterns and Laravel integration approach\n- [quasarstream/shaka-php](https://github.com/quasarstream/shaka-php) — Shaka Packager wrapper and command building patterns\n\n## License\n\nThe MIT License (MIT). Please see [License File](LICENSE.md) for more information.\n","funding_links":["https://github.com/sponsors/Foxws"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoxws%2Flaravel-streamer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffoxws%2Flaravel-streamer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoxws%2Flaravel-streamer/lists"}