Skip to main content

Usage

Basic usage

use Foxws\Shaka\Facades\Shaka;

$result = Shaka::open('input.mp4')
->addVideoStream('input.mp4', 'video.mp4')
->addAudioStream('input.mp4', 'audio.mp4')
->withHlsMasterPlaylist('master.m3u8')
->export()
->save();

Adaptive bitrate streaming

Add multiple video streams with different bandwidths to produce a multi-quality adaptive stream:

$result = Shaka::open('input.mp4')
->addVideoStream('input.mp4', 'video_1080p.mp4', ['bandwidth' => '5000000'])
->addVideoStream('input.mp4', 'video_720p.mp4', ['bandwidth' => '3000000'])
->addVideoStream('input.mp4', 'video_480p.mp4', ['bandwidth' => '1500000'])
->addAudioStream('input.mp4', 'audio.mp4')
->withHlsMasterPlaylist('master.m3u8')
->withSegmentDuration(6)
->export()
->save();

Working with different disks

fromDisk() sets the source disk, and toDisk()/toPath() control where the packaged output is saved. Each can be a different Laravel filesystem disk (local, S3, or any custom disk):

$result = Shaka::fromDisk('s3')
->open('videos/input.mp4')
->addVideoStream('videos/input.mp4', 'video.mp4')
->addAudioStream('videos/input.mp4', 'audio.mp4')
->withHlsMasterPlaylist('master.m3u8')
->export()
->toDisk('export') // Save output to a different disk (e.g., local, s3, etc.)
->toPath('exports/') // (Optional) Save to a subdirectory on the target disk
->save();

HLS with encryption

withAESEncryption() returns an EncryptionKey value object (not $this), so it breaks the fluent chain — call it on its own line:

// Basic encryption with auto-generated AES-128 key
$streamer = Shaka::open('input.mp4')
->addVideoStream('input.mp4', 'video.mp4')
->addAudioStream('input.mp4', 'audio.mp4')
->withHlsMasterPlaylist('master.m3u8');

$encryptionKey = $streamer->withAESEncryption(); // Auto-generates key with 'cbc1' scheme

$streamer->export()->save();

// With key rotation (generates key_0.key, key_1.key, etc.)
$streamer = Shaka::open('input.mp4')
->addVideoStream('input.mp4', 'video.mp4')
->addAudioStream('input.mp4', 'audio.mp4')
->withHlsMasterPlaylist('master.m3u8');

$encryptionKey = $streamer->withAESEncryption();
$streamer->withKeyRotationDuration(60); // Rotate every 60 seconds

$streamer->export()->toDisk('s3')->save();

See the AES Encryption guide for complete documentation, including codec-specific examples and key storage details.

Dynamic URL resolvers (HLS & DASH)

Serve encrypted streaming content with S3 signed URLs by resolving key, media, and playlist/manifest URLs on demand:

HLS example:

use Foxws\Shaka\Http\DynamicHLSPlaylist;
use Illuminate\Support\Facades\Storage;

public function playlist(Video $video)
{
return (new DynamicHLSPlaylist('s3'))
->open("videos/{$video->id}/master.m3u8")
->setKeyUrlResolver(fn ($key) => Storage::disk('s3')->temporaryUrl(
"videos/{$video->id}/{$key}",
now()->addHour()
))
->setMediaUrlResolver(fn ($file) => Storage::disk('s3')->temporaryUrl(
"videos/{$video->id}/{$file}",
now()->addHours(2)
))
->toResponse(request());
}

DASH example:

use Foxws\Shaka\Http\DynamicDASHManifest;
use Illuminate\Support\Facades\Storage;

public function manifest(Video $video)
{
return (new DynamicDASHManifest('s3'))
->open("videos/{$video->id}/manifest.mpd")
->setKeyUrlResolver(fn ($key) => Storage::disk('s3')->temporaryUrl(
"videos/{$video->id}/{$key}",
now()->addHour()
))
->setMediaUrlResolver(fn ($file) => Storage::disk('s3')->temporaryUrl(
"videos/{$video->id}/{$file}",
now()->addHours(2)
))
->setInitUrlResolver(fn ($file) => Storage::disk('s3')->temporaryUrl(
"videos/{$video->id}/{$file}",
now()->addHours(2)
))
->toResponse(request());
}

See the URL Resolvers guide for the full API and more use cases (CDN integration, multi-tenant applications, dynamic key rotation).

Next steps