WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
NEW
327697
decodeAudioData refuses Opus WebM in every mapping family but 0, WebCodecs refuses above 2 channels, decodingInfo() says supported
https://bugs.webkit.org/show_bug.cgi?id=327697
Summary
decodeAudioData refuses Opus WebM in every mapping family but 0, WebCodecs re...
mormegil6
Reported
2026-10-15 07:20:22 PDT
Created
attachment 481841
[details]
Test page: 17 Opus WebM streams, decodeAudioData, WebCodecs and MediaCapabilities results. Serve with python3 -m http.server and open /matrix/ in Safari. WebKit 229325, "Decoding webm file with more than 2 channels will fail", landed as
308749@main
on 2026-03-05, and the Safari Technology Preview 240 release notes list it as "Fixed an issue where decoding WebM audio files with more than two channels would fail." The commit message says it adds multichannel decoding "whenever AudioToolbox decoder supports multi-channels audio", and reorders channels "for codec with an Ogg channel layout" (family 1). In 2022 (
comment 7
) the same engineer had said the platform decoder "lacks the ability to decode more than 2 channels". The tested Safari should contain the fix:
308749@main
is an ancestor of both safari-7625-branch and safari-7625.1.29.18-branch on GitHub, and the tested build (20625.1.29.18.28 by safaridriver --version) is on the 7625.1.29.18 line. The behaviour below is not what the fix describes. Seventeen valid Opus streams, 2 or 3 seconds at 48 kHz with a different sine on each channel, were decoded through decodeAudioData (WebM) and WebCodecs AudioDecoder (same packets), and queried through MediaCapabilities.decodingInfo(): | Mapping family | Streams | | 0 (RFC 7845) | stereo (control) | | 1 (RFC 7845, Vorbis order) | stereo, 3.0, quad, 5.1, 7.1 | | 2 (RFC 8486, Ambisonics) | 4 and 16 channels | | 255 (independent streams) | 1, 2, 3, 4, 6, 8, 10, 12 and 16 channels | Result on Safari 27.0, macOS 15.8, for the 16 streams other than the control: - decodeAudioData refuses all 16. The error callback is invoked with null (no error object, no message). That includes mono in family 255 and stereo in family 1, which carry the same audio as a stereo stream it does decode, so the rule it applies is the mapping family byte, not the channel count. Only the family 0 control decodes. - WebCodecs isConfigSupported() returns false for all 13 streams of 3 to 16 channels, in every family, and true for mono and stereo in every family (those decode correctly through WebCodecs, 101 frames each). Its rule is the channel count. - MediaCapabilities.decodingInfo() reports every one of the 16 as supported, for both type: 'file' and type: 'media-source', queried with audio: { contentType: 'audio/webm; codecs="opus"', channels: '<n>', samplerate: 48000, bitrate: 24000 * n } at channels 1, 2, 3, 4, 6, 8, 10, 12 and 16. - Chrome 154.0.8037.58 decodes all 17 streams on both surfaces, so the streams are valid. So inside one engine, two decoders apply different rules to the same file, and the capability API agrees with neither. (canPlayType and isTypeSupported take only a MIME type with a codec string and cannot express a channel count, so the complaint is aimed at decodingInfo(), which takes one. 229325
comment 6
, from 2022, records the same pattern for canPlayType: it passes, then playback fails, so no fallback source is tried.) The use case is third-order Ambisonics, 16 channels. A WebAssembly libopus build (opus-decoder 0.7.12,
https://github.com/eshaz/wasm-audio-decoders
) decodes the same 16-channel packets in the same Safari, all channels in the right order (checked per channel with a Goertzel test) and audible on playback, so this is not a CPU or memory limit. If the limit is AudioToolbox's, and it holds on every macOS release tested here including the current one, it would help for decodeAudioData to say so rather than invoke its error callback with null, for MediaCapabilities to report supported: false, and to know whether any OS release exists where multichannel Opus decodes at all. It would also help to know why decodeAudioData refuses mono and stereo streams in families 1 and 255 that WebCodecs decodes. On macOS 26 the same 17-stream matrix was run twice more, by a different tester on a different machine: stable Safari 26.6, and Safari Technology Preview reporting version 27.0. Both gave the identical row-by-row result above, summary fields included (decodeAudioDataRefusesOnlyNonZeroFamily, webCodecsRefusesOnlyAbove2Channels, all 16 non-control streams refused, MediaCapabilities true for all 16). Apple's own release notes confirm Safari 26.6 ships on macOS 26.x and that macOS 27 (Golden Gate) shipped 2026-09-14, so this is not an older OS: it is the current one, and the bleeding edge past it. The iOS 18.7.7 run (iPhone Xs, 12 September) predates the matrix page and used the earlier two-stream page: the 16-channel stream and a family 0 stereo control. The 16-channel stream was refused on decodeAudioData and WebCodecs, as on macOS. The stereo control decoded from WebM, but the same control in fragmented MP4 was refused by decodeAudioData on iOS 18 and decoded on macOS Safari 27. That is 307632 (fixed as
309140@main
, 2026-03-12, also in the STP 240 release notes): the commit is an ancestor of safari-7625.1.29.18-branch and of neither safari-7620.2.4.14-branch nor safari-7620.2.4.111-branch, the Safari 18 branches checked, which fits the split and is not a separate bug. In fragmented MP4, Safari 27 also answers canPlayType with an empty string and isTypeSupported with false for Opus, so on that container the string surfaces and the decoders agree; the disagreement above is specific to WebM. STEPS TO REPRODUCE ------------------ 1. Open
https://mormegil6.github.io/safari-multichannel-opus-repro/matrix/
in Safari. 2. It decodes all seventeen streams and prints one row each: decodeAudioData, WebCodecs and MediaCapabilities. Press Copy JSON for the raw result, whose summary states the two rules above. 3. For the 16-channel stream alone, with a WebAssembly reference decode and a Play button to hear it, open
https://mormegil6.github.io/safari-multichannel-opus-repro/
4. Without the network: unzip the attached safari-multichannel-opus-matrix-testcase.zip, run python3 -m http.server 8000 in the unzipped folder and open
http://localhost:8000/matrix/
in Safari. Both pages need only their own static files. EXPECTED RESULTS ---------------- decodeAudioData and WebCodecs decode the streams as Chrome and Firefox do, or, where the OS decoder cannot, MediaCapabilities.decodingInfo() reports supported: false, matching what AudioDecoder.isConfigSupported() already reports, and decodeAudioData applies the same rule as WebCodecs. ACTUAL RESULTS -------------- - decodeAudioData: error callback invoked with null for 16 of 16 non-control streams. - WebCodecs: isConfigSupported() false for the 13 streams above 2 channels; decode never attempted for them. - MediaCapabilities.decodingInfo(): supported: true for all of them. - WebAssembly libopus decodes the 16-channel stream correctly in the same browser. ENVIRONMENT / MEASURED VERSIONS ------------------------------- Measured 2026-09-25 (macOS 15.8) and 2026-09-30 (macOS 26). Raw JSON is attached as safari-multichannel-opus-matrix-results.zip (2026-09-25-matrix-macos15.8-safari27.0.json, 2026-09-25-matrix-macos15.8-chrome154.0.8037.58.json, 2026-09-30-matrix-macos26-safari26.6.json, 2026-09-30-matrix-macos26-safari27.0stp.json), and is also in the repository
https://github.com/mormegil6/safari-multichannel-opus-repro
under results/. | Surface | Safari 27.0, macOS 15.8 | Safari 26.6, macOS 26 | Safari STP 27.0, macOS 26 | Chrome 154.0.8037.58 | | decodeAudioData, family 0 stereo control | decodes | decodes | decodes | decodes | | decodeAudioData, the other 16 streams | refused, 16 of 16 | refused, 16 of 16 | refused, 16 of 16 | decodes, 16 of 16 | | WebCodecs, mono and stereo, any family (3 streams) | supported, decodes | supported, decodes | supported, decodes | supported, decodes | | WebCodecs, 3 to 16 ch (13 streams) | isConfigSupported false, 13 of 13 | false, 13 of 13 | false, 13 of 13 | supported, decodes, 13 of 13 | | MediaCapabilities, 1 to 16 ch, WebM | supported: true at every count | true at every count | true at every count | true at every count | The 16-channel stream alone, measured 2026-09-12 (results/2026-09-12-*.json): macOS Safari 27.0 on macOS 15.7.9 and Safari 18.7.7 on iOS 18.7 refuse it on decodeAudioData and WebCodecs, in WebM and fragmented MP4; Chrome 152 and Firefox 155 decode it on every surface. The macOS 15.8 re-run (results/2026-09-25-macos15.8-safari27.0.json) gave identical machine verdicts to 15.7.9. In all of those runs the WebAssembly libopus decode passed the per-channel frequency check, and a listener heard the 16 tones on macOS Safari 27.0 (15.7.9) and on the iPhone. WHAT WAS NOT TESTED ------------------- - iOS 26 or iPadOS 26. macOS 26 is confirmed; no iOS device on the current major version has been run yet. Not a deciding gap any more, since 307632 already establishes the macOS/iOS split behaves consistently release-to-release, but worth a mention if anyone asks. - WebKit trunk. Only shipping Safari and its Technology Preview were tested. - Family 3, channel counts 5, 7, 9, 11 and 13 to 15, and fragmented MP4 for anything but the 16-channel stream and a family 0 stereo control. (Family 0 allows only 1 or 2 channels, so nothing above stereo exists in it.) - iOS for the matrix. Only the earlier two-stream page was run there, and only on iOS 18.7. TEST FILES ---------- The whole test page is attached as safari-multichannel-opus-matrix-testcase.zip (unzip it, run python3 -m http.server 8000 in the folder and open
http://localhost:8000/matrix/
in Safari; file:// URLs do not work because the page fetches its streams). It is also at
https://github.com/mormegil6/safari-multichannel-opus-repro
: matrix/files/ holds the seventeen WebM streams and their packet lists, and make-matrix.sh regenerates them. Family 2 files are the uncoupled family 255 files with one header byte changed. That is a valid family 2 stream: RFC 8486 3.3 allows 4 and 16 channels, and libopus's own family 2 encoder produces exactly this layout for them (validate_ambisonics in opus_multistream_encoder.c sets the stream count to the number of Ambisonic channels and the coupled count to 0 when there is no non-diegetic stereo pair). make-matrix.sh says so at the point it does it. RELATED WEBKIT BUGS ------------------- - 229325, fixed
308749@main
(2026-03-05, in STP 240): multichannel decoding "whenever AudioToolbox decoder supports multi-channels audio".
Comment 6
there (Wikimedia, 2022) describes canPlayType answering yes while decode fails;
comment 7
says the framework decoder "lacks the ability to decode more than 2 channels". - 307632, fixed
309140@main
(2026-03-12, in STP 240): Opus in MP4 through decodeAudioData (AudioFileReader rewritten on AVAssetReader, because AudioFile does not support Opus in MP4). - 323104: unrelated (an iOS tab whose audio output dies while every API reports success).
Attachments
Test page: 17 Opus WebM streams, decodeAudioData, WebCodecs and MediaCapabilities results. Serve with python3 -m http.server and open /matrix/ in Safari.
(669.67 KB, application/zip)
2026-10-15 07:20 PDT
,
mormegil6
no flags
Details
Raw JSON results: Safari 27.0 and Chrome 154 on macOS 15.8, Safari 26.6 and Safari Technology Preview on macOS 26.
(3.98 KB, application/zip)
2026-10-15 07:21 PDT
,
mormegil6
no flags
Details
View All
Add attachment
proposed patch, testcase, etc.
mormegil6
Comment 1
2026-10-15 07:21:06 PDT
Created
attachment 481842
[details]
Raw JSON results: Safari 27.0 and Chrome 154 on macOS 15.8, Safari 26.6 and Safari Technology Preview on macOS 26.
Alexey Proskuryakov
Comment 2
2026-10-15 14:29:25 PDT
Thank you for the report! The LLM rewriting made it very confusing, I don't understand what signifies passing and what signifies failing. Could you please elaborate how to tell if the problem reproduces? What I did was open
https://mormegil6.github.io/safari-multichannel-opus-repro/matrix/
in Safari 26.6.2 and in Safari Technology Preview 254, both on macOS 26.x. The copied JSONs were identical, aside from timestamp.
mormegil6
Comment 3
2026-10-15 14:33:30 PDT
Thanks for looking, and sorry about the confusing text. The short version: The page decodes 17 Opus WebM streams (2 to 16 channels) and prints one row per stream. If the problem reproduces, the line at the top reads "Of the 16 streams other than the family 0 stereo control, decodeAudioData refuses 16 and WebCodecs refuses 13; MediaCapabilities reports 16 of the refused ones as supported", and most cells are red. In Chrome the same page says "Every stream decoded here." In the copied JSON the same thing is under "summary": decodeAudioDataRefuses 16, webCodecsRefuses 13 and mediaCapabilitiesSaysSupportedForAStreamADecoderRefuses 16 mean it reproduces. 0, 0 and 0 would mean it does not. What I think is wrong: decodeAudioData refuses every stream except the family 0 stereo one, WebCodecs isConfigSupported() is false above 2 channels, and MediaCapabilities.decodingInfo() says supported for all of them. I would expect either the streams decode, or decodingInfo() says supported: false. Which numbers does your JSON show on Safari 26.6.2 and on STP 254? On my side it is the numbers above on Safari 27.0 (macOS 15.8) and on macOS 26.
Alexey Proskuryakov
Comment 4
2026-10-15 18:03:18 PDT
I am getting "Of the 16 streams other than the family 0 stereo control, decodeAudioData refuses 16 and WebCodecs refuses 13; MediaCapabilities reports 16 of the refused ones as supported". So looks like the problem reproduces the older version too. Or maybe there is some other aspect at play, like a different hardware model (mine is a M3 Max MacBook Pro). Anyway, CC'ing some people who would have insight, I'm very much not an expert on WebCodecs. JSON summary in 26.6.2: "summary": { "controlDecoded": true, "otherStreams": 16, "decodeAudioDataRefuses": 16, "webCodecsRefuses": 13, "mediaCapabilitiesSaysSupportedForAStreamADecoderRefuses": 16, "webCodecsRefusesOnlyAbove2Channels": true, "decodeAudioDataRefusesOnlyNonZeroFamily": true }
Radar WebKit Bug Importer
Comment 5
2026-10-22 07:21:16 PDT
<
rdar://problem/190723601
>
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug