Laravel Shaka
Architecture
How It Works
One job, step by step
- Open.
Shaka::fromDisk('media')->open($path)creates aMediaOpenerwith a freshPackager. Each opened path becomes aMediaobject. - Resolve inputs. Shaka Packager needs local files. By default, an input on a local disk is linked into a temporary folder as
input.<ext>. An input on a remote disk, such as S3, is downloaded there once. - Build the command. Each
add*Stream()andwith*()call adds to aCommandBuilder. Output names are placed in a new temporary folder undertemporary_files_root. - Run.
save()runs thepackagerbinary through Laravel'sProcess, with the configured timeout. - Upload. The output folder and the key folder are copied to the target disk. That's in parallel for S3, a
rename()for local disks, and a stream copy for anything else. - Clean up. The temporary folders are deleted after the upload.
cleanupTemporaryFiles()removes whatever is still left, for example after a failure.
Classes
| Class | Role |
|---|---|
Shaka facade / MediaOpenerFactory |
Makes a new MediaOpener for every call, so jobs don't share state. |
MediaOpener |
Holds the opened media, and passes stream and option calls on to the Packager. |
Packager |
Turns disk paths into local paths, fills the CommandBuilder and runs the job. |
CommandBuilder |
Collects streams and options, and builds the argument list. |
ShakaPackager |
Runs the binary and throws when it fails. |
MediaExporter |
Returned by export(). Holds the target disk and path, and runs everything on save(). |
PackagerResult |
The finished run. Its toDisk() uploads the output. |
TemporaryDirectories |
Creates, and later deletes, the temporary folders. Runs the storage guards. |
DynamicHLSPlaylist, DynamicDASHManifest |
Rewrite playlists when they're served. They don't run the binary. |
Container bindings
| Binding | Lifetime |
|---|---|
ShakaPackager |
Singleton, shared by every job in a process. |
TemporaryDirectories |
Singleton. Tracks every folder so cleanupTemporaryFiles() can remove them. |
Packager |
Scoped, and the facade calls fresh() for each opener. |
Because ShakaPackager is shared, don't change it inside a job. Settings you change there stay for every later job in a queue worker or Octane process.
Testing your code
You don't need the binary in unit tests:
- Build the job and assert on
->getCommand()instead of callingsave(). - Use
Storage::fake()for the input and target disks. - Test the code that runs after packaging, such as
afterSaving()callbacks, separately.
