@mux/convex
v0.2.0
Published
Convex Component for syncing Mux video data and app metadata.
Downloads
287
Readme
Mux Convex Component
A reusable Convex component for apps that use Mux for video. Sync your Mux video data with Convex and build video apps with a real-time database backing your catalog.
This package gives you:
- Convex tables for Mux
assets,uploads,liveStreams, andevents - Mutations to upsert/delete synced Mux objects
- App-level
videoMetadatastorage (userId, title, visibility, tags, custom fields) - Query helpers for catalog and user-facing video data
- Built-in CLI to scaffold app-level Convex wrappers (
npx @mux/convex init)
Quickstart
1) Install packages
npm i @mux/convex @mux/mux-node2) Generate app-level Convex files
npx @mux/convex init --component-name muxThis creates:
convex/convex.config.tsconvex/migrations.tsconvex/muxWebhook.tsconvex/http.ts
If files already exist, the CLI skips them unless you pass --force.
3) Set Mux API env vars in Convex
npx convex env set MUX_TOKEN_ID <your_mux_token_id>
npx convex env set MUX_TOKEN_SECRET <your_mux_token_secret>4) Start Convex and run backfill
npx convex dev
npx convex run migrations:backfillMux '{}'5) Configure Mux webhook endpoint
In the Mux dashboard, create a webhook endpoint:
- URL for deployed app:
https://<your-deployment>.convex.site/mux/webhook - URL for local development: use a tunnel (e.g. ngrok or cloudflared) to
/mux/webhook
Copy the webhook signing secret and set it in Convex:
npx convex env set MUX_WEBHOOK_SECRET <your_mux_webhook_secret>6) Verify data in Convex dashboard
Tables to check:
assetsuploadsliveStreamseventsvideoMetadata
Why both backfill and webhook?
- Backfill is a one-time catch-up for existing Mux objects.
- Webhooks keep your Convex tables updated in near real time as Mux state changes.
Without webhooks, data will drift over time.
Runtime model
This follows Convex component best practices:
@mux/convexis component-only (schema, queries, mutations)- Node runtime integration (Mux SDK, webhook verification, backfill) lives in app-level code in your project
npx @mux/convex initscaffolds those app-level files for you
Using a different component name
If you mount with a different name, for example:
app.use(mux, { name: "videoInfra" });Then regenerate wrappers with the matching name:
npx @mux/convex init --component-name videoInfra --forceCommon commands
# regenerate wrappers
npx @mux/convex init --component-name mux --force
# run backfill with options
npx convex run migrations:backfillMux '{"maxAssets":500,"defaultUserId":"dev-user-1","includeVideoMetadata":true}'
# run against prod deployment
npx convex run --prod migrations:backfillMux '{"maxAssets":500}'Troubleshooting
Could not find function for 'migrations:backfillMux': Ensureconvex/migrations.tsexists and exportsbackfillMux, then runnpx convex dev.InvalidReference ... does not export [mux_node.backfillAssets]: Do not callcomponents.<name>.mux_node.*directly. Use the app-level wrappers generated bynpx @mux/convex init.- TypeScript
webhooks.unwrap ... Record<string, unknown>: Regenerate wrappers withnpx @mux/convex init --force. - TypeScript
request.headers.entries is not a function/property: Build headers withrequest.headers.forEach(...)inconvex/http.ts. - Webhooks route compiles but never updates tables: If
ingestMuxWebhookis generated asinternalAction, call it viainternal.muxWebhook.ingestMuxWebhook(notanyApi.*). Node APIs without "use node": Ensure Node runtime files start with"use node";.
