zhitoo / laravel-hls-converter
Laravel package for converting videos to HLS format using the HLS Converter microservice
v0.1.0
2026-06-23 07:08 UTC
Requires
- php: ^8.1
- guzzlehttp/guzzle: ^7.0
- illuminate/http: ^10.0|^11.0
- illuminate/support: ^10.0|^11.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0
- phpunit/phpunit: ^10.0
README
A Laravel package for converting videos to HLS (HTTP Live Streaming) format via the HLS Converter microservice.
Requirements
- PHP 8.1+
- Laravel 10 or 11
- PHP
zipextension (for extraction features)
Installation
composer require zhitoo/laravel-hls-converter
Publish the config file:
php artisan vendor:publish --tag=hls-converter-config
Configuration
Add the following to your .env:
HLS_CONVERTER_BASE_URL=https://hls.yourdomain.com HLS_CONVERTER_API_KEY=your-secret-api-key HLS_CONVERTER_TIMEOUT=30 HLS_CONVERTER_DOWNLOAD_TIMEOUT=120 # Optional: temp directory for ZIP download/extract (default: storage/app/hls-temp) HLS_CONVERTER_TEMP_PATH=/tmp/hls-temp
Usage
Submit a conversion job
use Zhitoo\HlsConverter\Facades\HlsConverter; $taskId = HlsConverter::convert( videoUrl: 'https://example.com/video.mp4', resolutions: [1080, 720, 480], // omit for original quality only chunkDuration: 10, audioChannels: 2, );
Check status
$status = HlsConverter::status($taskId); echo $status->status; // Pending | Processing | Completed | Failed echo $status->progress; // 0–100 if ($status->isCompleted()) { echo $status->masterPlaylist; // "master.m3u8" foreach ($status->qualities as $q) { echo $q['label'] . ' → ' . $q['playlist']; // 720p → 720p/output.m3u8 } }
Download ZIP
// Save to an explicit path HlsConverter::downloadToFile($taskId, storage_path("hls/{$taskId}.zip")); // Or get a PSR-7 stream $stream = HlsConverter::download($taskId); file_put_contents(storage_path("hls/{$taskId}.zip"), $stream);
Extract ZIP to a local directory
Downloads the ZIP, extracts it, deletes the ZIP, and returns the list of extracted file paths.
$files = HlsConverter::extractTo($taskId, storage_path("hls/{$taskId}")); // $files is an array of absolute paths: // [ // '/var/www/storage/app/hls/<taskId>/master.m3u8', // '/var/www/storage/app/hls/<taskId>/720p/output.m3u8', // '/var/www/storage/app/hls/<taskId>/720p/segment_000.ts', // ... // ]
Transfer HLS files to a Laravel storage disk
Downloads the ZIP, extracts it, uploads every file to the chosen storage disk, and cleans up all temp files automatically.
// Transfer to a specific disk (local, s3, ftp, etc.) $result = HlsConverter::transferToStorage( taskId: $taskId, storagePath: "videos/hls/{$taskId}", disk: 's3', ); // Or use the default filesystem disk $result = HlsConverter::transferToDefaultStorage( taskId: $taskId, storagePath: "videos/hls/{$taskId}", ); echo $result->disk; // "s3" echo $result->basePath; // "videos/hls/<taskId>" echo $result->masterPlaylistPath(); // "videos/hls/<taskId>/master.m3u8" foreach ($result->files as $path) { echo Storage::disk($result->disk)->url($path); } // Get as array $array = $result->toArray(); // [ // 'disk' => 's3', // 'base_path' => 'videos/hls/<taskId>', // 'master_playlist' => 'videos/hls/<taskId>/master.m3u8', // 'files' => [...], // ]
Polling until done then transferring
use Zhitoo\HlsConverter\Facades\HlsConverter; use Zhitoo\HlsConverter\Exceptions\HlsConverterException; $taskId = HlsConverter::convert('https://example.com/video.mp4', [720, 480]); do { sleep(5); $status = HlsConverter::status($taskId); } while ($status->isPending() || $status->isProcessing()); if ($status->isFailed()) { $log = HlsConverter::logs($taskId); throw new \RuntimeException("Conversion failed.\n{$log}"); } $result = HlsConverter::transferToStorage($taskId, "videos/hls/{$taskId}", 's3');
Dependency injection
use Zhitoo\HlsConverter\HlsConverter; use Zhitoo\HlsConverter\DTOs\TransferResult; class VideoService { public function __construct(private HlsConverter $hls) {} public function process(string $url, string $taskId): TransferResult { return $this->hls->transferToStorage($taskId, "hls/{$taskId}", 's3'); } }
Exception Handling
All methods throw Zhitoo\HlsConverter\Exceptions\HlsConverterException on failure.
use Zhitoo\HlsConverter\Exceptions\HlsConverterException; try { $result = HlsConverter::transferToStorage($taskId, 'videos/hls', 's3'); } catch (HlsConverterException $e) { logger()->error('HLS transfer failed', ['error' => $e->getMessage()]); }
API Reference
| Method | Description | Returns |
|---|---|---|
convert($url, $resolutions, $chunkDuration, $audioChannels) |
Submit a conversion job | string task_id |
status($taskId) |
Get task status | TaskStatus |
logs($taskId) |
Get raw FFmpeg log | string |
download($taskId) |
Get ZIP as a PSR-7 stream | StreamInterface |
downloadToFile($taskId, $path) |
Save ZIP to a local file | void |
extractTo($taskId, $destination) |
Download + extract ZIP to a local dir | string[] file paths |
transferToStorage($taskId, $storagePath, $disk) |
Download + extract + upload to storage disk | TransferResult |
transferToDefaultStorage($taskId, $storagePath) |
Same, using filesystems.default disk |
TransferResult |
TaskStatus DTO
| Property | Type | Description |
|---|---|---|
taskId |
string | Task UUID |
status |
string | Pending, Processing, Completed, Failed |
progress |
int | 0–100 |
currentStep |
string | Current processing step |
retryCount |
int | Number of retries so far |
createdAt |
string | ISO 8601 |
updatedAt |
string | ISO 8601 |
masterPlaylist |
string|null | master.m3u8 — only when Completed |
qualities |
array | [{height, label, playlist}] — only when Completed |
Helper methods: isPending(), isProcessing(), isCompleted(), isFailed()
TransferResult DTO
| Property | Type | Description |
|---|---|---|
disk |
string | Storage disk name |
basePath |
string | Base path inside the disk |
masterPlaylist |
string|null | master.m3u8 relative name, or null |
files |
string[] | Full storage paths of all uploaded files |
Methods: masterPlaylistPath() — full path including basePath, toArray()
License
MIT