Skip to content

feat(web): convert Dolby and DTS audio while playing offline - #237

Open
mia-riezebos wants to merge 1 commit into
feat/177-offline-text-subsfrom
feat/176-offline-audio
Open

mia-riezebos wants to merge 1 commit into
feat/177-offline-text-subsfrom
feat/176-offline-audio

Conversation

@mia-riezebos

Copy link
Copy Markdown
Member

Offline playback (#225) refused a download whose only audio the browser can't play: AC-3 and E-AC-3 in Chrome and Firefox, DTS everywhere. That is about a third of the demo library. This converts that audio in the browser while it plays.

How. When the audio Stream to play isn't native but is AC-3, E-AC-3, DTS or PCM, the remux decodes it with Mediabunny (@mediabunny/ac3 and @mediabunny/dts register software decoders, loaded only for those tracks) and encodes it through Mediabunny's AudioSampleSource, muxed with the untouched video. Each run starts the audio at the video's keyframe with the source's own timestamps, so a seek restarts both at the same point.

What it becomes. AAC, else Opus, whichever this browser's Media Source plays and an encoder takes. The source's channels are kept where the encoder takes them and downmixed to stereo only where none does, so 5.1 stays 5.1. Chrome on Linux has no native AAC encoder and its Opus encoder takes only stereo, so there @mediabunny/aac-encoder (WebAssembly) stands in and keeps 5.1. Safari and Edge, which play AC-3 and E-AC-3 natively, keep playing them as they are.

Choice. With no track chosen, the first native audio Stream wins, else the first convertible one. Any track can be picked from the audio menu; picking one reopens the session and converts it if needed. TrueHD has no decoder anywhere and still shows "Needs a server copy", as does any other audio no browser plays. The Downloads caption "Needs audio conversion" is gone: those downloads now get Play.

Closes #176

New dependencies

@mediabunny/ac3, @mediabunny/dts and @mediabunny/aac-encoder 1.62.0 (MPL-2.0), Mediabunny's own codec extensions, the ones the PRD names. Same maintainer and release train as mediabunny; each is a lazy chunk (0.7 to 1.1 MB) loaded only when a download needs it, and the service worker caches them with the shell for offline use.

Screenshot

An AC-3 5.1 download now offers Play; a TrueHD one still says why it can't:

downloads

Tests

  • apps/server/src/api/offline-browser.test.ts (headless Chromium, server stopped). 11 pass, twice in a row:
    • A 4-minute AC-3 5.1 download, silent until a 440 Hz tone at 200 s, is seeked to 198.5 s, past the buffer. The tone is heard within 0.3 s of the video's 200 s. Native AAC measures the same 0.12 s early here, so the conversion adds no offset.
    • A DTS 5.1 download plays with sound.
    • A TrueHD download shows "Needs a server copy."
  • playable.test.ts: proves the plan converts Dolby and DTS (asked or by default), still prefers a native track, and the encoding choice keeps 5.1 in AAC or Opus (Opus at 48 kHz) and downmixes to stereo only when no encoder takes six channels.
  • Throughput in headless Chromium here, AC-3 5.1 to AAC 5.1 through the WebAssembly encoder: 98 s buffered in 14.6 s from page load, about 6.7× real time.
  • Web bun test: 296 pass. bun run lint: 0 errors. bun run check (all packages): 0 errors.

Not covered automatically: the "mid-range laptop for a 2-hour film" check and the Safari/Edge native path. Those are in the manual checks.


Made with claude-opus-5.5 using Claude Code in T3 Code.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 6c7786b1-6f08-4f26-9db8-096a9eb746d1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes across offline playback planning, audio conversion, seek handling, codec packaging, and regression coverage.

  • Audio selection: Prefers native audio, otherwise converts Dolby, DTS, or PCM while retaining the server-copy notice for unsupported codecs.
  • Conversion and seeking: Lazily loads software codecs, selects AAC or Opus with channel preservation where supported, and muxes converted audio with unchanged video using source timestamps.
  • Offline coverage: Adds AC-3 seek/synchronization and DTS sound checks with the server stopped, plus unit coverage for codec and channel selection.
  • Verification: All 296 web unit tests and 11 offline browser tests passed; the web build and Svelte/type checks passed. Safari/Edge native playback and the long-film performance check remain unverified here.

Pullfrog  | View workflow run | Using gpt-6.1-sol | 𝕏

A download whose audio the browser can't play is no longer refused when
the audio is AC-3, E-AC-3, DTS or PCM: Mediabunny decodes it in
software (@mediabunny/ac3, @mediabunny/dts) and encodes AAC or Opus as
it plays, muxed with the untouched video. 5.1 stays 5.1 where an
encoder takes six channels and downmixes to stereo otherwise; without a
native AAC encoder the WebAssembly one stands in. Native tracks still
play as they are, and TrueHD still needs a server copy.

Closes #176

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mia-riezebos
mia-riezebos force-pushed the feat/176-offline-audio branch from 865e704 to e8ceeba Compare October 21, 2026 10:58
@pullfrog

pullfrog Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

The failed checks job timed out in access-browser.test.ts:316 while selecting the “Shows” Library on a Group’s Access rules page: Timed out waiting for document.querySelectorAll('[data-slot=select-item],[data-slot=combobox-item]').length === 0. That test and the affected Access rules UI are unchanged by this PR, so no unrelated fix was committed or pushed; the working tree is clean. A CI rerun was already in progress when inspected.

Task list (1/3 completed)
  • Inspect PR and failed CI logs; confirm the failure is introduced by this PR
  • Reproduce and fix the CI failure with a minimal change
  • Run affected checks, review the diff, and push a signed fix commit

Pullfrog  | View workflow run | via Pullfrog | Using gpt-6.1-sol | 𝕏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant