mux.js: utilities for inspecting and rewriting video container formats
Lightweight utilities for inspecting and manipulating video container formats.
At a glance
- What is it?
- mux.js is a small JavaScript library of stream tools that transmuxes MPEG2-TS into fragmented MP4 for Media Source Extensions, parses captions and metadata, and ships as both an npm package and a browser bundle, with its FLV transmuxer explicitly frozen.
- Who is it for?
- Use mux.js when your player has to turn an MPEG2-TS stream into fragmented MP4 in the browser, or when you need a parser for captions and timestamps inside those segments, because writing that box level work yourself is a large job with no upside. Leave it alone if you already have fMP4 from your CDN, since the transmuxer is then unnecessary, and do not build new work on the FLV path, which the project puts into maintenance mode.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly JavaScript, 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
Four modules, one exported muxjs object
The exported `muxjs` object is organised into four modules. `codecs` handles audio and video elementary streams, with an Adts module for AAC audio that parses ADTS frames and passes them to the next stream component in a pipeline, and an h264 module that parses NAL units in the same streaming style. `mp4` handles ISOBMFF boxes, and it is the largest part of the library. `flv` handles Flash content. `mp2t` contains the MPEG2 transport stream pieces, such as the ElementaryStream and TransportPacketStream, and it is what the MP4 module is built on. The package exposes itself in three shapes, with a CommonJS entry at `./cjs/index.js`, an ES module entry at `es/index.js`, and a browser bundle at `dist/mux.js`, plus a command line binary named `muxjs-transmux`.
The MP4 transmuxer is the piece most projects want
`muxjs.mp4.Transmuxer` takes MPEG2-TS segments and transmuxes them into fragmented MP4 segments, and it is the component everything else supports. You create one, then push data into it and listen for the segments it produces.
// Create your transmuxer:
// initOptions is optional and can be omitted at this time.
var transmuxer = new muxjs.mp4.Transmuxer(initOptions);
// Create an event listener which will be triggered after the transmuxer processes data:
// 'data' events signal a new fMP4 segment is ready
transmuxer.on('data', function (segment) {It has three documented options. `baseMediaDecodeTime` is a number defaulting to `0`, and it sets the base media decode time of the first segment passed in. `remux` is a boolean defaulting to `true`, and setting it to `true` remuxes audio and video into a single MP4 segment. `keepOriginalTimestamps` is a boolean defaulting to `false`, and it is the one with a consequence, because the default behaviour rewrites timestamps so that media segments begin at `0` on the MSE media timeline, and setting the option to `true` avoids that rewrite. There is also an MP4 generator module for producing fMP4s for MSE, an MP4 probe for reading metadata such as `timescale` and the base media decode time of a fragment in seconds, and tools that parse an MP4 into a plain JavaScript object for debugging.
Keeping original timestamps shifts the cost onto captions
The documentation attaches a warning to `keepOriginalTimestamps` that is worth reading before you flip it. Preserving the source timestamps affects the behaviour of captions and metadata, and these may not align with audio and video without additional manipulation of timing metadata. In other words, the option removes a rewrite from the transmuxer but hands the same problem to whatever consumes the timed text. For a player that needs subtitle cues to line up with the picture, the default of rewriting to a zero base is usually simpler, and the option is for cases where a downstream system already expects the original clock. The mp2t tools exist for the same reason, providing utilities to parse basic timing information out of MPEG2-TS segments.
Caption parsing comes in both transport stream and MP4 flavours
Captions are handled in two places, because the captions can arrive in either container. `muxjs.mp2t.CaptionStream` does the bulk of parsing CEA-608 captions out of MPEG2-TS segments. `muxjs.mp4.CaptionParser` reads CEA-608 captions out of fMP4 segments, and `muxjs.mp4.WebVTTParser` reads WebVTT text out of fMP4 segments. So a pipeline that starts as transport stream and ends as fragmented MP4 has a parser on each side of the transmux, and the library covers both rather than forcing you to convert captions yourself. The transcoding of the caption data itself is not the job of these modules; they extract it and hand it on.
The FLV transmuxer is frozen and says so
`muxjs.flv.Transmuxer` takes MPEG2-TS segments and transmuxes them into FLV segments, and the documentation attaches one sentence to it: this module is in maintenance mode and will not have further major development. That is a clean boundary rather than a silent deprecation. FLV is the legacy Flash path, and the module exists for pipelines that still have to produce it, but nothing new will be built there. The `flv.tools` module, which parses FLV tags into an equivalent JavaScript object for debugging, is in the same family. Anyone planning a new integration should build on the mp4 or mp2t modules and treat the FLV branch as something to finish and retire.
You have to know the box layout before the transmuxer helps
The documentation spends a section on the structure of a fragmented MP4 before it shows a line of code, and the reason is that the transmuxer's output only makes sense once you know the boxes. An fMP4 is structured in boxes as described in the ISOBMFF specification, and a valid one needs ftyp, moov, moof and mdat. Every fMP4 stream starts with an ftyp and moov box, followed by many moof and mdat pairs. The first segment you append to Media Source Extensions has to be an init segment carrying ftyp and moov, followed by a moof and mdat, and the segments carrying the media itself are the moof and mdat pairs. If you want to see that structure directly, the `muxjs.mp4.tools.inspect()` method renders it.
A stable library whose last tagged release is old
The project labels its own maintenance status as Stable, the licence is Apache-2.0, and the repository is not archived. The last push was on 2026-08-12, so the code is still being touched, but the release history has a different rhythm: v7.1.0 was published on 2024-10-11, before that v7.0.3 on 2024-03-12 and v7.0.2 on 2023-11-27. A library used inside a player therefore ships whichever of those the ecosystem has pinned. The install is a single package command, and a packaged distribution is produced with the build script.
npm install --save mux.jsThe browser support list in the package manifest still names ie 11 alongside the defaults, which says how old the compatibility target is.
Editorial conclusion
Use mux.js when your player has to turn an MPEG2-TS stream into fragmented MP4 in the browser, or when you need a parser for captions and timestamps inside those segments, because writing that box level work yourself is a large job with no upside. Leave it alone if you already have fMP4 from your CDN, since the transmuxer is then unnecessary, and do not build new work on the FLV path, which the project puts into maintenance mode. Before you upgrade, read the keepOriginalTimestamps note, because turning it on moves caption and metadata timing out of step with audio and video unless you manipulate the timing metadata yourself.
Frequently asked questions
What does mux.js do?
It provides lightweight utilities for inspecting and manipulating video container formats, including a transmuxer that turns MPEG2-TS segments into fragmented MP4 segments for Media Source Extensions, and parsers for captions and timing information.
How do I install mux.js?
Run `npm install --save mux.js`. If you want a packaged distribution instead, clone the repository and run `npm run build`, and in a node-like environment you can require the parts you need directly.
What does keepOriginalTimestamps change in the MP4 transmuxer?
By default the transmuxer rewrites timestamps so media segments start at zero on the MSE timeline. Setting keepOriginalTimestamps to true avoids that rewrite, but the documentation warns that captions and metadata may then not align with audio and video without extra manipulation of timing metadata.
Is the FLV support in mux.js still being developed?
No. The documentation states that the FLV transmuxer is in maintenance mode and will not have further major development, so new work belongs on the mp4 or mp2t modules.
Official sources
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.
[](https://hysenlabs.com/projects/videojs-mux-js)Was this useful?