Agent skill
mux-video
Upload, manage, and embed videos via Mux. Covers direct uploads, API asset management, webhook event flow, playback embedding, and the Mux CLI. Use when uploading video, creating assets, checking encoding status, embedding playback, or handling Mux webhook events.
Install this agent skill to your Project
npx add-skill https://github.com/joelhooks/joelclaw/tree/main/skills/mux-video
SKILL.md
Mux Video
Upload, manage, and embed videos through Mux's API and CLI. Integrates with joelclaw's webhook infrastructure and Inngest event pipeline.
When to Use
Triggers on: "upload video to mux", "create mux asset", "embed mux video", "check video status", "mux playback", "direct upload", "video encoding", "mux webhook", or any task involving video hosting via Mux.
Credentials
Stored in agent-secrets:
mux_token_id— API token IDmux_token_secret— API token secretmux_signing_key_id— URL signing key IDmux_signing_secret— webhook signing secret (per-endpoint, HMAC)
Lease credentials:
secrets lease mux_token_id
secrets lease mux_token_secret
Or use env vars MUX_TOKEN_ID and MUX_TOKEN_SECRET.
Core Operations
Create Asset from URL
Ingest a video from a public URL:
curl https://api.mux.com/video/v1/assets \
-X POST \
-H "Content-Type: application/json" \
-u ${MUX_TOKEN_ID}:${MUX_TOKEN_SECRET} \
-d '{
"input": [{"url": "https://example.com/video.mp4"}],
"playback_policy": ["public"],
"video_quality": "plus"
}'
Video quality tiers: basic (fastest/cheapest), plus (default, good quality), premium (highest).
Direct Upload (browser/client-side)
Two-step process:
Step 1: Create authenticated upload URL (server-side)
curl https://api.mux.com/video/v1/uploads \
-X POST \
-H "Content-Type: application/json" \
-u ${MUX_TOKEN_ID}:${MUX_TOKEN_SECRET} \
-d '{
"new_asset_settings": {
"playback_policies": ["public"],
"video_quality": "plus"
},
"cors_origin": "*"
}'
Response includes data.url (resumable upload endpoint) and data.id (upload ID).
Step 2: PUT the file to the URL (client-side)
curl -X PUT "${UPLOAD_URL}" \
-H "Content-Type: video/mp4" \
--data-binary @video.mp4
The URL is resumable — large files can be uploaded in chunks. Use UpChunk for browser uploads.
List Assets
curl https://api.mux.com/video/v1/assets \
-u ${MUX_TOKEN_ID}:${MUX_TOKEN_SECRET}
Get Asset Details
curl https://api.mux.com/video/v1/assets/${ASSET_ID} \
-u ${MUX_TOKEN_ID}:${MUX_TOKEN_SECRET}
Delete Asset
curl -X DELETE https://api.mux.com/video/v1/assets/${ASSET_ID} \
-u ${MUX_TOKEN_ID}:${MUX_TOKEN_SECRET}
Auto-Generated Captions
curl https://api.mux.com/video/v1/assets \
-X POST \
-H "Content-Type: application/json" \
-u ${MUX_TOKEN_ID}:${MUX_TOKEN_SECRET} \
-d '{
"input": [{"url": "https://example.com/video.mp4"}],
"playback_policy": ["public"],
"auto_generated_captions": [{"language": "en"}]
}'
Playback
Embed URL
Once an asset is ready and has a playback ID:
https://stream.mux.com/${PLAYBACK_ID}.m3u8
Thumbnail/Poster
https://image.mux.com/${PLAYBACK_ID}/thumbnail.jpg
https://image.mux.com/${PLAYBACK_ID}/thumbnail.jpg?time=10
https://image.mux.com/${PLAYBACK_ID}/animated.gif?start=5&end=10
Mux Player (Web Component)
<mux-player
playback-id="${PLAYBACK_ID}"
metadata-video-title="My Video"
accent-color="#FF0000"
></mux-player>
Install: npm install @mux/mux-player-react for React, or use the web component directly.
React Component
import MuxPlayer from "@mux/mux-player-react";
<MuxPlayer
playbackId={playbackId}
metadata={{ video_title: "My Video" }}
accentColor="#FF0000"
/>
Webhook Events
Mux webhooks are registered at: https://panda.tail7af24.ts.net/webhooks/mux
The webhook provider (packages/system-bus/src/webhooks/providers/mux.ts) handles HMAC-SHA256 verification and normalizes events into the Inngest pipeline.
Key Events
| Mux Event | Inngest Event | When |
|---|---|---|
video.asset.created |
mux/asset.created |
Asset record created |
video.asset.ready |
mux/asset.ready |
Encoding complete, playable |
video.asset.errored |
mux/asset.errored |
Encoding failed |
video.upload.created |
mux/upload.created |
Direct upload URL created |
video.upload.asset_created |
mux/upload.asset_created |
Upload completed, asset created |
video.upload.cancelled |
mux/upload.cancelled |
Upload cancelled or timed out |
video.asset.live_stream_completed |
mux/asset.live_stream_completed |
Live stream recording ready |
Event Payload Structure
{
"type": "video.asset.ready",
"data": {
"id": "asset_id",
"playback_ids": [{"id": "playback_id", "policy": "public"}],
"status": "ready",
"duration": 120.5,
"passthrough": "your_custom_id",
"tracks": [...]
}
}
The passthrough field carries your custom identifier through the entire pipeline — use it to correlate uploads with your application records.
Building Inngest Functions for Mux Events
// Example: Notify when video is ready
const onVideoReady = inngest.createFunction(
{ id: "mux-video-ready", name: "Mux Video Ready" },
{ event: "mux/asset.ready" },
async ({ event, step }) => {
const { data } = event;
const playbackId = data.playback_ids?.[0]?.id;
const duration = data.duration;
// Your logic here — update DB, notify user, etc.
await step.run("notify", async () => {
// ...
});
}
);
passthrough Pattern
Always set passthrough when creating assets or uploads. This is your correlation ID that flows through all webhook events:
curl https://api.mux.com/video/v1/assets \
-X POST \
-H "Content-Type: application/json" \
-u ${MUX_TOKEN_ID}:${MUX_TOKEN_SECRET} \
-d '{
"input": [{"url": "https://example.com/video.mp4"}],
"playback_policy": ["public"],
"passthrough": "my-unique-correlation-id"
}'
Rules
- Always use
passthroughfor tracking — it's your only way to correlate webhooks back to your records. - Don't poll for status in production — use webhooks. Mux has rate limits.
- Webhook signing secret is per-endpoint — it's the secret you get when registering the webhook URL in the Mux dashboard, NOT the API token secret or signing key.
- Video quality tiers affect cost —
basicfor drafts/previews,plusfor production,premiumonly when needed. - Direct upload URLs expire — default 1 hour timeout. Create them on-demand, not ahead of time.
- Playback IDs are stable — once an asset is ready, the playback ID doesn't change. Safe to cache/store.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
skill-review
Audit and maintain the joelclaw skill inventory. Use when checking skill health, fixing broken symlinks, finding stale skills, or running the skill garden. Triggers: 'skill audit', 'check skills', 'stale skills', 'skill health', 'skill garden', 'broken skill', 'skill review', 'fix skills', 'garden skills', or any task involving skill inventory maintenance.
cli-design
Design and build agent-first CLIs with HATEOAS JSON responses, context-protecting output, and self-documenting command trees. Use when creating new CLI tools, adding commands to existing CLIs (joelclaw, slog), or reviewing CLI design for agent-friendliness. Triggers on 'build a CLI', 'add a command', 'CLI design', 'agent-friendly output', or any task involving command-line tool creation.
daily-summary
Generate a daily system activity summary across all joelclaw subsystems. Triggers on 'daily summary', 'what happened today', 'system report', 'today's tally', 'activity summary', 'what did we do', 'daily report'.
inngest-durable-functions
Create and configure Inngest durable functions. Covers triggers (events, cron, invoke), step execution and memoization, idempotency, cancellation, error handling, retries, logging, and observability.
recall
Fan-out search across all memory sources when context is unclear or vaguely referenced. Triggers on: 'from earlier', 'remember when', 'what we discussed', 'that thing with', 'the conversation about', 'did we ever', 'what happened with', 'you mentioned', 'we talked about', 'earlier today', 'last session', 'the other day', or any vague reference to past context that needs resolution before the agent can act.
inngest-local
Set up self-hosted Inngest on macOS as a durable background task manager for AI agents. Interactive Q&A to match intent — from Docker one-liner to full k8s deployment with persistent state. Use when: 'set up inngest', 'background tasks', 'durable workflows', 'self-host inngest', 'event-driven functions', 'cron jobs', or any request for a local workflow engine.
Didn't find tool you were looking for?