daun/statamic-mux
A Statamic addon that integrates Mux video: upload and manage assets, generate playback IDs and thumbnails, and embed responsive Mux players in your content via a dedicated fieldtype and Antlers tags.
Install the addon and give it Mux credentials. The package is small; reading src/ end-to-end takes under an hour and is the fastest way to understand exactly what it does and does not handle.
composer require daun/statamic-mux
php artisan vendor:publish --tag=statamic-mux-config # confirm tag name in README
Add the Mux token pair to .env (create an Access Token in the Mux dashboard, scoped to the environment you want):
MUX_TOKEN_ID=...
MUX_TOKEN_SECRET=...
Then add the addon's fieldtype to a blueprint — typically a video or mux field on a pages or posts collection. In the control panel the field gives you an upload control that pushes the file directly to Mux and stores the resulting playback ID (and usually the asset ID) on the entry.
Render it in Antlers with the addon's tag, or drop to the raw playback ID:
{{ if video }}
{{ mux }} {{# addon-provided player tag — verify name in README #}}
{{ /if }}
{{# or roll your own #}}
<video controls playsinline poster="https://image.mux.com/{{ video:playback_id }}/thumbnail.jpg">
<source src="https://stream.mux.com/{{ video:playback_id }}.m3u8" type="application/x-mpegURL">
</video>
First use case: a hero background loop or a "watch the demo" block on a marketing page. Upload once in the CP, reference the entry's playback ID in the template, done. Mux handles transcoding and adaptive bitrate, so you skip the ffmpeg/HLS plumbing entirely.
Field-per-video, not a media library. The fieldtype stores one asset per field. For a page with a hero video plus a testimonial video, add two fields. For a reusable library, point multiple entries at a shared global or a "videos" collection and reference by relationship — playback IDs are portable strings, so cross-entry reuse is trivial.
Treat the playback ID as the contract. Everything downstream — <video>, Mux Player, thumbnails, captions — keys off playback_id. If you later swap the addon's player tag for <mux-player> or Video.js, the field data doesn't change. Wrap rendering in a partial so there's one place to change:
{{# partials/video.antlers.html #}}
{{ if video }}
<mux-player
playback-id="{{ video:playback_id }}"
metadata-video-title="{{ title }}"
accent-color="#1a1a1a"
></mux-player>
{{ /if }}
Bard and Replicator sets. The field works inside sets, which is usually what you want for article bodies: one set type video, one field, and a {{ if type == 'video' }} branch in the set loop. Keep the player markup in that branch.
Draft/preview safety. An entry saved before the Mux asset finishes processing can have a null or half-written playback ID. Always guard:
{{ if video:playback_id }}
...
{{ /if }}
Static caching. Playback IDs are immutable per asset, so fully cached HTML works well. The player script loads client-side and doesn't need a server round-trip. This is the main reason the addon pairs nicely with Statamic's static cache — no per-request API call to Mux.
Pair it with the Mux PHP SDK for anything advanced. The addon covers upload + embed; signing, direct uploads from your own forms, asset deletion, and webhook handling are SDK territory:
use MuxPhp\Api\AssetsApi;
$api = new AssetsApi(app(\MuxPhp\Configuration::class));
$asset = $api->getAsset($assetId);
Keep a small service class for this rather than scattering SDK calls in controllers.
Video metadata for SEO. Mux exposes duration and thumbnails. Store title/description on the Statamic entry (not on Mux) and use the playback ID for the thumbnailUrl/contentUrl in a VideoObject JSON-LD block. You can also emit a <track> for captions if you upload them to Mux:
<track kind="captions" src="https://stream.mux.com/{{ video:playback_id }}/text/en.vtt" srclang="en">
Webhooks. Mux emits video.asset.ready when processing completes. If the addon doesn't poll asset state automatically (check its service provider/jobs), add a webhook route that updates the entry's field when ready — otherwise editors see an empty player for a few minutes and file bugs.
stream.mux.com. Dump the field's raw value once with {{ video | dump }} before writing templates.signed requires minting a JWT server-side with the Mux signing key. Don't cache signed tokens in the static cache — they expire. Use public playback for marketing video and signed only where DRM-ish behavior is required.deleteAsset, or you'll accumulate storage charges silently.MUX_TOKEN_ID/MUX_TOKEN_SECRET must be present when php artisan config:cache runs on deploy. On Forge/Cloud, set them as environment variables before the deploy script, not just in the local .env.media-src, connect-src for stream.mux.com and image.mux.com) can still break playback. Check the browser console first when "the video won't load."composer.json, read the source when something is odd, and be prepared to fork — it's a thin wrapper, so forking is cheap..m3u8 MIME/CORS issue, not the addon.How can I help you explore Laravel packages today?