Technical architecture

How the whole downloader works, from URL resolution to MP4.

A transparent look at the network path, HLS parsing, concurrent downloads, progress calculation, transmuxing, and browser file creation.

The architecture at a glance

The downloader separates a small server-side discovery task from the large video transfer. That distinction is the core of the architecture. The Cloudflare Pages Worker reads an approved public Kommodo share page because the share page itself does not expose browser-readable CORS headers. It extracts a signed HLS playlist URL and returns limited metadata. The visitor's browser then requests the playlist and media segments directly from approved Kommodo delivery hosts.

This approach keeps the application simple and reduces server bandwidth. It also makes the transfer path more transparent: the resolver handles page discovery, while the browser handles the recording bytes. Cloudflare's advanced Pages mode allows a module Worker to handle the API route and forward all other requests to the static asset binding, matching the architecture described in the Cloudflare Pages documentation.

1. Validate and resolve the share page

The browser sends the pasted URL to /api/resolve. Before making any outbound request, the Worker checks the scheme, hostname, port, credentials, path shape, and total URL length. Only secure kommodo.ai recording URLs pass. The resolver is rate limited per visible visitor IP on a best-effort Worker-isolate basis and refuses unexpectedly large page responses.

The Worker parses the page's structured application data, searches for the first HLS URL, and validates the result again. The playlist must use HTTPS and an approved komododecks.com host. The response contains the recording identifier, a length-limited title, optional duration, and the signed playlist URL. It never returns the full page HTML to the browser.

This restricted allowlist is important. A general URL fetcher could become a server-side request forgery tool. Limiting both the input host and the output media host narrows the Worker to its intended purpose.

2. Read the HLS playlists

HTTP Live Streaming represents a recording with text playlists and smaller media resources. Apple describes HLS as HTTP delivery that can support prerecorded content, multiple bit rates, encryption, and adaptive selection. The browser first fetches the resolved .m3u8 playlist. If it is a master playlist containing several variants, the downloader follows the highest-bandwidth listed stream. It limits nesting depth so a malformed playlist cannot cause unbounded recursion.

The media playlist contains #EXTINF duration entries followed by segment URLs. The parser resolves relative URLs against the playlist URL, records each duration, and calculates the estimated total. Encrypted playlists are rejected because this tool does not request keys or bypass access controls. A maximum segment count also protects the browser from accidentally attempting an unreasonable in-memory job.

Read HLS to MP4 explained for a closer look at master playlists, media playlists, transport streams, codecs, and containers.

3. Download segments in the visitor's browser

The browser creates up to eight asynchronous workers. Each worker takes the next segment, requests it with the Fetch API, reads the response stream in chunks, and stores the completed segment in its original playlist position. Chunk reads update the received byte count without waiting for the whole segment. Completed segments update the progress percentage, segment count, average speed, and estimated time remaining.

Cross-origin requests only work when the media host permits them. As the MDN CORS guide explains, browsers enforce the same-origin policy unless the remote server returns appropriate access-control headers. The downloader cannot override a media host that declines browser access. Segment requests retry a limited number of times to recover from brief network errors, but repeated failures stop the job rather than creating a silently incomplete file.

Because these requests originate in the visitor's browser, the Kommodo delivery host sees the visitor's network connection for the video transfer. The application server is not a video proxy.

4. Transmux compatible media into MP4

After all segments arrive, the browser passes them to the locally bundled mux.js transmuxer. Transmuxing changes the container structure while preserving compatible encoded audio and video tracks. It is different from transcoding, which decodes and re-encodes the media and can change quality, file size, and CPU cost.

The transmuxer emits an MP4 initialization segment followed by media fragments. The application collects these parts in order and creates a Blob with the video/mp4 MIME type. It then calls URL.createObjectURL() to create a temporary browser URL for the Save MP4 link. MDN documents Blob URLs as local identifiers that allow a browser to reference in-memory binary data.

The implementation revokes the previous object URL before another job and when the page closes. This avoids keeping obsolete browser objects alive longer than necessary.

Security, privacy, and practical boundaries

The public code uses a restrictive Content Security Policy, serves mux.js from the same origin, rejects unrelated resolver hosts, checks playlist hosts, limits response size and segment count, uses text-only DOM updates for remote titles, and returns generic network errors that do not expose internal details. No API key is required by the project.

Browser-side processing also has limits. The current implementation keeps the segment arrays and resulting MP4 in memory, so very large recordings may exceed device or browser capacity. It supports compatible unencrypted HLS transport streams; encrypted media, unusual codecs, discontinuities, separate audio arrangements, or fragmented MP4 inputs may require a different pipeline. A successful playlist fetch does not guarantee that every media combination can be transmuxed.

For operational details, see Browser-side processing and privacy, Recording formats and compatibility, and the troubleshooting guide. The source is available for inspection in the GitHub repository.