Open-source project
muxinc/stream.new avatar
muxinc/stream.new

stream.new: Mux's reference app for recording and uploading video

The repo for https://stream.new

615 stars86 forksTypeScriptLicense varies

At a glance

What is it?
stream.new is an open-source Next.js example application from Mux that lets users record in the browser and upload the result through Mux direct uploads, then play it back with HLS and track quality with Mux Data. It is a teaching codebase for the Mux API, not a product to deploy as is.
Who is it for?
stream.new is worth reading and forking when you are building a record-and-upload feature on Mux and want the client, webhook and playback wiring in one place. It is the wrong starting point if you need multi-user accounts, a media library or durable storage, since it ships as an example without those.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 15 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What stream.new is and what it is for

stream.new is an open-source example application from Mux that allows users to record and upload videos using Mux. The README calls it an example application and links to a live demo, which sets the expectation correctly: this is a demonstration of an API and its surrounding integration patterns, published so that other developers can copy the wiring.

The codebase started life as the Next.js with-mux-video example and was built on top of it, so the structure follows the standard Next.js App Router layout with an app directory, components, lib, util, types, test and vendor directories. The package manifest names the project with-mux-video at version 0.1.0 and requires Node 22 or newer through its engines field.

The audience is a developer who already has or is about to have a Mux account and wants to see a complete upload path in one repository: capture in the browser, hand the bytes to Mux, get a webhook back, play the result and watch the quality metrics. Nothing here is a user management system, a content library or a video editor, and reading the example as if it were a deployable product is the most common way to misjudge it.

How the record, upload and playback path is wired

The Mux side of the application uses four pieces, listed in the README. Direct uploads are the API for uploading video files from a client to create Mux Assets, and that is what keeps the file bytes out of the application server. Webhook signature verification exists so that Mux webhooks can be confirmed as coming from a trusted source. HLS.js handles playback, and Mux Data is used for tracking video quality metrics.

The Next.js side is where the interesting decisions sit. The app uses SWR with a refreshInterval that changes dynamically depending on whether the client should be polling for updates, which is how the UI follows an asset from pending to ready without hammering the API. There are a couple of API routes under pages/api that exist to make authenticated requests to the Mux API, so the browser never holds the access token. Dynamic routes use getStaticPaths with fallback set to true, alongside dynamic API routes, which is how a route per video can be served without generating every page at build time.

The dependency list shows how much of the player stack is in play: mux-player-react and mux-video-react for the player, mux-uploader-react and upchunk for chunked uploads, blurup for the Mux blur-up preview effect, mux-embed for sharing, hls.js pinned around 1.6, media-chrome and plyr for player controls, plus @videojs/mux-data and @videojs/mux-video. The presence of a workflow package and the Sentry packages shows the example has been hardened beyond a bare demo, with instrumentation files and separate Sentry edge and server configurations in the repository root.

The Slackbot moderator and the optional @mux/ai step

Two optional features are documented as numbered steps in the getting started guide, and both are the kind of integration that tends to be skipped in tutorials.

The Slackbot moderator configures a SLACK_WEBHOOK_ASSET_READY value. When a new Mux asset reaches the ready state, an Incoming Webhook for Slack is sent, and the README describes this as an example of how you might integrate a Slack channel that can be used to moderate content. The Slack message carries the asset ID, the playback ID and a storyboard of thumbnails from the video, so a moderator can approve or reject a recording without leaving the channel. Actions taken from the bot are protected by a SLACK_MODERATOR_PASSWORD, which is the practical guard on a shared moderation surface.

Step 6 covers adding AI-powered content moderation and summarization using @mux/ai, which the README marks as optional. Both features are examples of reacting to the same asset-ready event rather than separate subsystems, which is the useful lesson for anyone extending the app: one webhook, several consumers.

The moderation path is also where the webhook signing secret matters. MUX_WEBHOOK_SIGNATURE_SECRET is listed as optional in the environment variable list, and the README links to the webhook security documentation. Leaving it unset in a deployed app means accepting asset events from anyone who knows the endpoint, which is a decision worth making deliberately rather than by omission.

Setting up credentials and running the app locally

Getting started requires a Mux account, and the README is unusually clear about the billing shape: there are no upfront charges and billing is monthly and pay-as-you-go. The catch is the test mode. Without a credit card on the account, all videos are in test mode, which means they are watermarked and clipped to ten seconds. Entering a card lifts those limitations and adds 20 dollars of free credit, which the README suggests is enough to try everything before being charged.

The environment file is copied from the example that ships with the repository, and the copy is ignored by Git.

bash
cp .env.local.example .env.local

The variables themselves come from a Mux access token with Full Access against Mux Video. The token ID and token secret map to MUX_TOKEN_ID and MUX_TOKEN_SECRET. The optional ones are MUX_WEBHOOK_SIGNATURE_SECRET for webhook verification, SLACK_WEBHOOK_ASSET_READY for the moderator webhook, SLACK_MODERATOR_PASSWORD for the moderator actions, and NEXT_PUBLIC_MUX_ENV_KEY, the Mux environment key used for the Mux Data integration. That last one carries the NEXT_PUBLIC prefix, which means it is embedded in the client bundle, so it is an identifier for the analytics environment rather than a secret.

Once the file is in place, the app starts with the standard Next.js commands.

bash
npm install
npm run dev

The app then answers on the local development port, and the README points at that address. The manifest also defines build, start, lint, format, test and tsc scripts, with lint running ESLint across the JavaScript and TypeScript sources and the build script running lint before next build, so a style failure stops the production build rather than shipping.

Deploying to Vercel and the scaffolding around the example

Deployment is the standard Next.js path on Vercel, and the README notes that environment variables have to be set through the Vercel CLI, which means an account, a login and one command per secret rather than a dashboard copy-and-paste. The documented procedure is to install the CLI, log in from it and run the commands that add the variables, with the values taken from the local .env.local file.

The repository is broader than a single example app, and that breadth is useful for a reader who wants to see how a video product is put together. Beyond the app itself there are a test directory with jest configuration and testing-library packages in the dev dependencies, a vendor directory, a workflows directory that matches the workflow dependency, an instrumentation pair for the client and the server, separate Sentry edge and server configurations, and proxy.ts at the root. There are also two environment templates, .env.local.example and .env.test, which is a hint that the test path uses its own configuration.

The tooling tells you what the maintainers expected. ESLint is configured with the react, react-hooks, jsx-a11y and TypeScript plugins, Prettier has its own configuration file, jest and the testing-library packages are set up, and the toolchain versions are pinned in .nvmrc and .tool-versions. The repository was last pushed on 2026-10-08 and is not archived. The package manifest declares the MIT licence, while the top-level listing of the repository does not include a LICENSE file, so the licence statement lives in the manifest rather than in a separate file.

What this example does not give you

The first limitation is that test mode and paid mode are different products. Watermarked, ten-second clips will not exercise the upload sizes, encoding choices or playback behaviour your users will meet, and the only way past that is to add a card and spend the free credit.

The second is the absence of the parts of a real product. There is no user model, no persistence of your own beyond Mux assets, no library view, no title or description editing, no retention policy, and no way to revoke a playback ID. The Mux Data integration gives you quality metrics, not business metrics, so retention and engagement analytics have to be built on top of it.

The third limitation is the one implied by the architecture. Because uploads go straight from the browser to Mux through direct uploads, the application server never handles the bytes, which is exactly what you want for a serverless deployment, and it also means you need the webhook path to be correct and reachable. A webhook endpoint that silently drops events leaves assets stuck in the pending state and the moderator bot silent, with no error surface in the app itself.

The alternative worth naming is the opposite trade: a self-hosted upload path where the file passes through your own storage and your own encoding pipeline. That approach gives you control over the media pipeline, the storage layout and the retention rules, and it costs you the bandwidth, the encoding work and the operational burden that Mux handles. stream.new is the faster route to a working capture-and-upload flow on Mux, and the choice between them is a question of whether you want to own the pipeline or rent it.

Editorial conclusion

stream.new is worth reading and forking when you are building a record-and-upload feature on Mux and want the client, webhook and playback wiring in one place. It is the wrong starting point if you need multi-user accounts, a media library or durable storage, since it ships as an example without those. Verify first that your Mux account is out of test mode, because without a card the recordings stay watermarked and cut to ten seconds, and set MUX_WEBHOOK_SIGNATURE_SECRET before exposing any webhook endpoint.

Frequently asked questions

What does the stream.new example application do?

It is an open-source example application from Mux that allows users to record and upload videos using Mux, using direct uploads, HLS.js for playback, webhook signature verification and Mux Data for quality metrics.

How do I run stream.new locally?

Copy `.env.local.example` to `.env.local`, fill in the Mux access token values, then run `npm install` and `npm run dev`. The app is then available at http://localhost:3000, and the manifest requires Node 22 or newer.

Why are my videos watermarked and only ten seconds long?

That is Mux test mode. Without a credit card on the Mux account all videos are watermarked and clipped to ten seconds. Adding a card lifts the limitations and gives 20 dollars of free credit.

What is the Slackbot moderator in stream.new?

It is an optional integration configured with SLACK_WEBHOOK_ASSET_READY. When a Mux asset becomes ready, a Slack Incoming Webhook message is sent containing the asset ID, the playback ID and a storyboard of thumbnails, so a channel can be used to moderate content.

Does stream.new include user accounts or a video library?

No. The README describes it as an example application for recording and uploading videos, built on the Next.js with-mux-video example, without accounts, a library or retention handling.

Official sources

  1. Issues
  2. muxinc/stream.new on GitHub
  3. Project website
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/muxinc-stream-new.svg)](https://hysenlabs.com/projects/muxinc-stream-new)

Was this useful?