Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Mux Php Laravel Package

muxinc/mux-php

The official Mux PHP SDK provides generated, typed access to the Mux Video API for Laravel and other PHP applications. Create and manage assets, live streams, playback IDs, direct uploads, and related video resources, with clear methods for building Mux-powered video workflows.

Deep Wiki
Context7

Getting Started

Install and configure in five minutes:

composer require muxinc/mux-php guzzlehttp/guzzle

Grab a Token ID and Token Secret from the Mux dashboard (Settings → Access Tokens). Store them in .env as MUX_TOKEN_ID and MUX_TOKEN_SECRET, then add a config entry:

// config/services.php
'mux' => [
    'token_id'     => env('MUX_TOKEN_ID'),
    'token_secret' => env('MUX_TOKEN_SECRET'),
    'signing_key_id'  => env('MUX_SIGNING_KEY_ID'),
    'signing_private_key' => env('MUX_SIGNING_PRIVATE_KEY'),
    'webhook_secret' => env('MUX_WEBHOOK_SECRET'),
],

Bind a single Configuration as a singleton in AppServiceProvider:

$this->app->singleton(\MuxPhp\Configuration::class, function () {
    return \MuxPhp\Configuration::getDefaultConfiguration()
        ->setUsername(config('services.mux.token_id'))
        ->setPassword(config('services.mux.token_secret'));
});

First use case: create a Direct Upload so a browser can PUT a file directly to Mux without touching your server.

$api = new \MuxPhp\Api\DirectUploadsApi(new \GuzzleHttp\Client(), app(Configuration::class));
$request = new \MuxPhp\Models\CreateDirectUploadRequest([
    'new_asset_settings' => ['playback_policy' => ['public']],
    'cors_origin'        => config('app.url'),
]);
$uploadUrl = $api->createDirectUpload($request)->getData()->getUrl();

Where to look first:

  • MuxPhp\Api\* — one class per resource (AssetsApi, LiveStreamsApi, DirectUploadsApi, PlaybackIDsApi, URLSigningKeysApi, ErrorsApi, VideoViewsApi, …).
  • MuxPhp\Models\* — request/response DTOs, all ArrayAccess; most request models accept an associative array in the constructor.
  • The Mux developer docs and the OpenAPI spec generator output are more useful than the PHP source itself.

Implementation Patterns

Wrap the SDK in a thin service class. The generated API classes are verbose and stateless; don't let controllers or jobs call them directly. A MuxService that exposes createDirectUpload(), getAsset(), createLiveStream() etc. keeps you insulated from SDK quirks and makes testing with mocks trivial.

Queue asset creation, never do it inline. A CreateAsset or CreateDirectUpload call hits the Mux API and can be slow; a full pipeline (upload → ingest → encode → ready) takes seconds-to-minutes. Use dispatch() for the API call and rely on webhooks for the rest.

Webhooks are the source of truth, not polling. Register one endpoint (e.g. POST /webhooks/mux) and map events to Laravel events:

match ($payload['type']) {
    'video.asset.ready'         => AssetReady::dispatch($payload['data']),
    'video.asset.errored'       => AssetErrored::dispatch($payload['data']),
    'video.live_stream.active'  => LiveStreamActive::dispatch($payload['data']),
    'video.upload.asset_created'=> UploadLinked::dispatch($payload['data']),
    default                     => null,
};

Keep the raw payload; you'll want data.id (asset ID) and data.playback_ids[0].id.

Signed playback requires JWT yourself. The SDK does not ship a signer for PHP (unlike Node). Install firebase/php-jwt and sign with your Mux signing key (RS256, aud: "v", sub: <playback_id>, short exp).

Live streaming flow:

  1. LiveStreamsApi->createLiveStream() — persist stream_key and playback_ids[0].id.
  2. Hand stream_key + RTMP URL (rtmps://global-live.mux.com:443/app) to the broadcaster.
  3. Listen for video.live_stream.active and video.live_stream.idle to flip UI state.
  4. Optionally resetStreamKey() when rotating keys.

Data / Analytics: use VideoViewsApi and ErrorsApi with filters (dimension, timeframe[], filters[]). These are read-only and cache-friendly — wrap in Cache::remember() with a few minutes of TTL to avoid hammering the API during dashboards.

Pagination: generated endpoints accept limit and page; response objects expose ->getData() for the array and ->getTotalRowCount() where applicable. Iterate manually rather than expecting a Laravel-style paginator.

Testing: bind a fake Configuration (or better, mock your MuxService) so Http::fake()/Guzzle doesn't hit the real API. Webhook receivers can be tested by computing a valid Mux-Signature for a fixture payload.

Gotchas and Tips

The package is 100% OpenAPI-generated — no framework sugar, no helpers. Everything is new FooRequest([...]) and ->setBar(). It's fine, but expect verbose call sites and no built-in webhook signature verification, no JWT signing, no upload helper. Plan to write those yourself (or use mux-php alongside a small internal SDK).

Webhook signature verification must be hand-rolled. Mux sends Mux-Signature: t=<unix>,v1=<hex>. Compute hash_hmac('sha256', "$timestamp.$rawBody", $secret), compare with hash_equals, and reject if abs(now() - $timestamp) > 300. Use $request->getContent() — not $request->all() — because re-serializing the body breaks the signature.

Don't block on video.asset.ready. Assets return with status: "preparing" immediately. Polling loops in a controller will time out. Either trust the webhook or use a queued job with backoff; even then, treat ready as the only "usable" signal and store duration, max_resolution, and playback_ids on your local model.

Signed playback traps: the signing key must be a private key (RSA, PKCS#8), and JWT sub is the playback ID, not the asset ID. Signing URLs also require the playback_policy: ['signed'] to have been set at asset creation — you can't retroactively make an existing public asset signed without a new playback ID.

playback_policy is an array, not a string. Passing 'public' fails; pass ['public'] (or Policies::PUBLIC).

Nulls vs empty arrays: generated models will send null fields differently than []. When updating or setting nested config (e.g. new_asset_settings), start from the model's set* methods rather than mutating arrays mid-request — a stray empty array has caused Mux to reject otherwise valid payloads.

HTTP client is a shared GuzzleHttp\Client. In long-running workers (horizon, queue:work) reuse it or you'll leak connections. If you see flaky timeouts, inject a client with timeout => 30, connect_timeout => 5 and let Guzzle retry on 5xx via middleware — Mux's API is reliable but not perfect.

Version pinning matters. Because this is generated from the OpenAPI spec, method signatures and model names do change between minor versions (e.g. renames around MetricsApi). Pin with ~4.0-style constraints and check the changelog before any bump; run your Mux integration test suite immediately after.

Errors are thrown, not returned. MuxPhp\ApiException wraps HTTP errors. Catch it and inspect $e->getResponseBody() for Mux's structured { "error": { "type", "messages" } } — the message field often explains why (bad playback policy, unsupported codec).

CORS origin must be explicit. cors_origin: '*' works for dev, but browsers reject it for credentialed requests. Set it to your real domain and remember to include subdomains if you allow them.

Extension points to lean on: bind the Configuration singleton and the GuzzleHttp\Client in the container so you can swap base URL (for recorded/mock servers), inject auth headers, or add a LogMiddleware in local environments. That's your only seam without forking the generated code.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core