Common issues you might run into with Laravel Shaka Packager, and how to fix them.
Error:
RuntimeException: Command execution failed - the underlying `Process` call
could not find or execute /usr/local/bin/packager
A missing or non-executable binary surfaces as a RuntimeException from the underlying Process call, the first time the packager binary is actually invoked — see Architecture for more detail.
Solutions:
Install Shaka Packager:
# Linux
wget https://github.com/shaka-project/shaka-packager/releases/download/v3.4.2/packager-linux-x64
sudo mv packager-linux-x64 /usr/local/bin/packager
sudo chmod +x /usr/local/bin/packager
# macOS
brew install shaka-packager
Update the config path:
# .env
PACKAGER_PATH=/path/to/packager
Verify the installation:
php artisan shaka:info
Error:
Binary is not executable
Solution:
chmod +x /usr/local/bin/packager
Error:
Temporary directory is not writable
Solutions:
Create the directory:
mkdir -p storage/app/packager/temp
chmod 755 storage/app/packager/temp
Update the config:
// config/laravel-shaka.php
'temporary_files_root' => storage_path('app/packager/temp'),
Error:
InsufficientStorageException: Insufficient storage space in [/cache/temp/packager]: 314572800 bytes free, 1610612736 bytes required.
This comes from a deliberate pre-flight check (see Storage Space Guards), not a filesystem error — the job never actually started, so there's nothing to clean up.
Solutions:
temporary_files_root or cache_files_root points at a size-limited mount (like a tmpfs), free up space or increase its size.maxProcesses) so workers x largest expected job footprint fits comfortably.PACKAGER_TEMPORARY_MIN_FREE / PACKAGER_CACHE_MIN_FREE (in bytes), and PACKAGER_TEMPORARY_SIZE_MULTIPLIER for the job-size-aware check.0.Error:
RuntimeException: Process timeout exceeded
Solutions:
Increase the timeout in the config:
// config/laravel-shaka.php
'timeout' => 60 * 60 * 8, // 8 hours
Or set it dynamically:
$packager = app(ShakaPackager::class);
$packager->setTimeout(28800); // 8 hours
Error:
Unknown field in stream descriptor: filename_with,comma.mp4
Solutions:
Enable generic input (recommended):
# .env
PACKAGER_FORCE_GENERIC_INPUT=true
Or sanitize the filename manually:
use Foxws\Shaka\Support\MediaHelper;
$sanitized = MediaHelper::sanitizeFilename($filename);
Error:
InvalidArgumentException: MediaCollection cannot be empty
Solution:
// Make sure you call open() before adding streams
Shaka::open('input.mp4') // ← Must call open first
->addVideoStream('input.mp4', 'output.mp4')
->export()
->save();
Error:
RuntimeException: No streams configured. Use addVideoStream() or addAudioStream() first.
Solution:
// Add at least one stream before exporting
Shaka::open('input.mp4')
->addVideoStream('input.mp4', 'video.mp4') // ← Add streams
->export()
->save();
Problem: Encrypted HLS doesn't play in web browsers.
Solution: Use the cbc1 protection scheme instead, for browser compatibility:
Shaka::open('input.mp4')
->addVideoStream('input.mp4', 'video.ts') // Use .ts not .mp4
->withHlsMasterPlaylist('master.m3u8')
->withEncryption([
'keys' => 'label=:key_id=abc:key=def',
'protection_scheme' => 'cbc1', // Browser-compatible
'clear_lead' => 0,
])
->export()
->save();
See AES Encryption for the full list of protection schemes and which devices support each one.
Error:
Cannot load key from URI
Solutions:
Make sure the key file is reachable:
// Make sure the key URL is publicly accessible
->setKeyUrlResolver(fn ($key) => Storage::disk('public')->url($key))
Check your CORS settings for cross-origin requests.
Error:
S3Exception: Access Denied
Solutions:
Check your IAM permissions:
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::your-bucket/*"
}
Verify your credentials in .env:
AWS_ACCESS_KEY_ID=your-key
AWS_SECRET_ACCESS_KEY=your-secret
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=your-bucket
Error:
RuntimeException: Cannot copy files: temporary directory not set
Solution: This happens when calling packageWithBuilder() directly. Use the full fluent API instead:
// ✗ Wrong
$builder = CommandBuilder::make()->addVideoStream(...);
$packager->packageWithBuilder($builder)->toDisk('s3');
// ✓ Correct
Shaka::open('input.mp4')
->addVideoStream('input.mp4', 'output.mp4')
->export()
->toDisk('s3')
->save();
Solutions:
Use a local, fast disk for temporary files:
'temporary_files_root' => '/dev/shm/packager', // RAM disk
Reduce quality/bitrate settings.
Use fewer adaptive-bitrate variants.
Move processing to a background queue:
ProcessMediaJob::dispatch($inputPath);
See Queue Integration for a full example.
Solutions:
Increase the PHP memory limit:
memory_limit = 512M
Process smaller chunks at a time.
Run queue workers with a memory limit:
php artisan queue:work --memory=512
# .env
PACKAGER_LOG_CHANNEL=stack
// Check the logs
tail -f storage/logs/laravel.log
$command = Shaka::open('input.mp4')
->addVideoStream('input.mp4', 'output.mp4')
->export()
->getCommand();
dd($command);
/usr/local/bin/packager --version
/usr/local/bin/packager in=input.mp4,stream=video,output=output.mp4
If you're still stuck:
php artisan shaka:infostorage/logs/laravel.logopen() before adding streams..mp4 vs .ts).filesystems.php.