@openclaw/whatsapp 2026.10.2 → 2026.10.5-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.setup/{action-runtime-CE3zGstN.mjs → action-runtime-DUSkWTiZ.mjs} +2 -2
- package/dist/.setup/{agent-tools-login-B7VEvJO7.mjs → agent-tools-login-CB7OQbli.mjs} +5 -15
- package/dist/.setup/{approval-handler.runtime-CKposl6w.mjs → approval-handler.runtime-BEaAKSoU.mjs} +3 -3
- package/dist/.setup/{approval-reactions-CD6CDF9k.mjs → approval-reactions-CWkZ_ham.mjs} +7 -16
- package/dist/.setup/audio-preflight.runtime-Dg8oZgre.mjs +2 -0
- package/dist/.setup/{auth-store-D2rN-hP5.mjs → auth-store-DOBi5BPe.mjs} +10 -11
- package/dist/.setup/{channel-DNgKHMCz.mjs → channel-DcHw3Up2.mjs} +136 -135
- package/dist/.setup/{channel-react-action-BaBV9X6M.mjs → channel-react-action-C5E8_iDk.mjs} +3 -3
- package/dist/.setup/{channel.runtime-BniF8Swm.mjs → channel.runtime-DTj-wkEP.mjs} +5 -11
- package/dist/.setup/channel.setup-BJWEyQlF.mjs +5 -0
- package/dist/.setup/{connection-controller-COkcq48K.mjs → connection-controller-CejM7bhn.mjs} +50 -84
- package/dist/.setup/{directory-config-RYQomHyB.mjs → directory-config-DPLTUAqy.mjs} +22 -29
- package/dist/.setup/{group-session-key-BV8Le9r8.mjs → group-session-key-BbTPosdy.mjs} +12 -18
- package/dist/.setup/{login-CV_4V021.mjs → login-DUx5JYuW.mjs} +3 -3
- package/dist/.setup/{login-qr-DFhGc5yH.mjs → login-qr-BAWbPonj.mjs} +24 -45
- package/dist/.setup/{monitor-B5DS4PDV.mjs → monitor-CmXEQad9.mjs} +218 -367
- package/dist/.setup/{normalize-target-BGra1ZnM.mjs → normalize-target-D67Kc3g6.mjs} +5 -8
- package/dist/.setup/{question-reactions-LMeijbaq.mjs → question-reactions-DywNaX8m.mjs} +3 -10
- package/dist/.setup/reaction-target-CSPO7gtu.mjs +11 -0
- package/dist/.setup/{resolve-outbound-target-CzyNKmrl.mjs → resolve-outbound-target-qikGL4r0.mjs} +3 -4
- package/dist/.setup/{send-CGUsUdoX.mjs → send-CLBfAzd6.mjs} +34 -42
- package/dist/.setup/{send-api-B03VDwZ1.mjs → send-api-COzRvqXx.mjs} +28 -60
- package/dist/.setup/{setup-finalize-GtBmrO8p.mjs → setup-finalize-DSiP_-wa.mjs} +53 -69
- package/dist/.setup/setup-plugin-api-8WdNCjRW.mjs +3 -0
- package/dist/.setup/{setup-surface-BuA39k6K.mjs → setup-surface-C_flQyHy.mjs} +2 -2
- package/dist/.setup/{shared-CP_zs2U7.mjs → shared-SqcOkt51.mjs} +4 -4
- package/dist/.setup/{socket-close-DU7eerAa.mjs → socket-close-C9OU9mVN.mjs} +67 -86
- package/dist/.setup/{targets-runtime-Dls-Xh4F.mjs → targets-runtime-D5ryyPxh.mjs} +16 -25
- package/dist/action-runtime-api.js +1 -1
- package/dist/action-runtime.runtime.js +1 -1
- package/dist/agent-tools-api.js +4 -8
- package/dist/api.js +13 -15
- package/dist/channel-plugin-api.js +1 -1
- package/dist/contract-api.js +1 -1
- package/dist/directory-contract-api.js +1 -1
- package/dist/doctor-contract-api.js +12 -32
- package/dist/light-runtime-api.js +2 -2
- package/dist/login-qr-runtime.js +2 -4
- package/dist/runtime-api.js +8 -8
- package/dist/setup-entry.js +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/node_modules/audio-decode/node_modules/@audio/decode/package.json +7 -7
- package/node_modules/audio-decode/node_modules/@audio/decode/readme.md +2 -1
- package/node_modules/audio-decode/node_modules/@audio/decode-aac/README.md +10 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-aac/decode-aac.d.ts +22 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-aac/decode-aac.js +142 -7
- package/node_modules/audio-decode/node_modules/@audio/decode-aac/package.json +1 -1
- package/node_modules/audio-decode/node_modules/@audio/decode-caf/README.md +2 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-caf/decode-caf.js +4 -1
- package/node_modules/audio-decode/node_modules/@audio/decode-caf/package.json +1 -1
- package/node_modules/audio-decode/node_modules/@audio/decode-flac/decode-flac.js +161 -29
- package/node_modules/audio-decode/node_modules/@audio/decode-flac/package.json +1 -1
- package/node_modules/audio-decode/node_modules/@audio/decode-mp4/README.md +1 -1
- package/node_modules/audio-decode/node_modules/@audio/decode-mp4/decode-mp4.js +127 -28
- package/node_modules/audio-decode/node_modules/@audio/decode-mp4/package.json +3 -3
- package/node_modules/audio-decode/node_modules/@audio/decode-opus/package.json +1 -1
- package/node_modules/audio-decode/node_modules/@audio/decode-opus/src/decode-opus.js +2 -2
- package/node_modules/audio-decode/node_modules/@audio/decode-qoa/README.md +1 -1
- package/node_modules/audio-decode/node_modules/@audio/decode-qoa/decode-qoa.js +79 -227
- package/node_modules/audio-decode/node_modules/@audio/decode-qoa/package.json +1 -1
- package/node_modules/audio-decode/node_modules/@audio/decode-vorbis/decode-vorbis.js +51 -10
- package/node_modules/audio-decode/node_modules/@audio/decode-vorbis/package.json +1 -1
- package/node_modules/audio-decode/node_modules/@audio/decode-wav/decode-wav.js +40 -18
- package/node_modules/audio-decode/node_modules/@audio/decode-wav/package.json +1 -1
- package/node_modules/audio-decode/node_modules/@audio/decode-wma/LICENSE.ffmpeg +502 -0
- package/node_modules/audio-decode/node_modules/@audio/decode-wma/README.md +5 -5
- package/node_modules/audio-decode/node_modules/@audio/decode-wma/decode-wma.js +15 -3
- package/node_modules/audio-decode/node_modules/@audio/decode-wma/package.json +5 -4
- package/node_modules/audio-decode/node_modules/@audio/decode-wma/src/wma.wasm.js +0 -0
- package/node_modules/audio-decode/node_modules/audio-type/audio-type.js +13 -0
- package/node_modules/audio-decode/node_modules/audio-type/package.json +1 -1
- package/node_modules/audio-decode/node_modules/audio-type/readme.md +1 -1
- package/node_modules/baileys/lib/Utils/messages-media.js +7 -11
- package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/diagnostics-channel-react-native.d.ts.map +1 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/diagnostics-channel-react-native.js.map +1 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/diagnostics-channel.d.ts +5 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/diagnostics-channel.js +7 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/index.d.ts +1400 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/index.d.ts.map +1 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/index.js +1733 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/index.js.map +1 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/perf.d.ts +12 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/perf.d.ts.map +1 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/perf.js +10 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/perf.js.map +1 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/diagnostics-channel-react-native.d.ts.map +1 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/diagnostics-channel-react-native.js.map +1 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/diagnostics-channel.d.ts +5 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/diagnostics-channel.js +4 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/index.d.ts +1400 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/index.d.ts.map +1 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/index.js +1729 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/index.js.map +1 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/perf.d.ts +12 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/perf.d.ts.map +1 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/perf.js +7 -0
- package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/perf.js.map +1 -0
- package/node_modules/baileys/node_modules/lru-cache/package.json +27 -1
- package/node_modules/baileys/node_modules/music-metadata/README.md +35 -32
- package/node_modules/baileys/node_modules/music-metadata/lib/ParserFactory.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ParserFactory.js +17 -13
- package/node_modules/baileys/node_modules/music-metadata/lib/aiff/AiffParser.js +19 -12
- package/node_modules/baileys/node_modules/music-metadata/lib/aiff/AiffToken.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/aiff/AiffToken.js +2 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2Parser.d.ts +4 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2Parser.js +59 -16
- package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2TagMapper.js +1 -0
- package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2Token.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2Token.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfGuid.js +56 -50
- package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfObject.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfObject.js +3 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfParser.js +15 -7
- package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfTagMapper.d.ts +3 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfTagMapper.js +21 -4
- package/node_modules/baileys/node_modules/music-metadata/lib/common/CaseInsensitiveTagMap.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/common/CombinedTagMapper.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/common/CombinedTagMapper.js +6 -6
- package/node_modules/baileys/node_modules/music-metadata/lib/common/FourCC.js +3 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/common/GenericTagMapper.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/common/GenericTagTypes.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/common/MetadataCollector.d.ts +3 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/common/MetadataCollector.js +28 -9
- package/node_modules/baileys/node_modules/music-metadata/lib/common/Util.js +25 -17
- package/node_modules/baileys/node_modules/music-metadata/lib/core.d.ts +4 -4
- package/node_modules/baileys/node_modules/music-metadata/lib/core.js +18 -11
- package/node_modules/baileys/node_modules/music-metadata/lib/dsdiff/DsdiffParser.js +29 -16
- package/node_modules/baileys/node_modules/music-metadata/lib/dsf/DsfChunk.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/dsf/DsfParser.js +3 -5
- package/node_modules/baileys/node_modules/music-metadata/lib/ebml/EbmlIterator.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ebml/EbmlIterator.js +35 -6
- package/node_modules/baileys/node_modules/music-metadata/lib/ebml/types.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ebml/types.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/flac/FlacParser.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/flac/FlacParser.js +6 -5
- package/node_modules/baileys/node_modules/music-metadata/lib/flac/FlacToken.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/flac/FlacToken.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v1/ID3v1Parser.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v1/ID3v1Parser.js +212 -42
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/AbstractID3Parser.js +5 -5
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/FrameHeader.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/FrameHeader.js +8 -5
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/FrameParser.d.ts +2 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/FrameParser.js +54 -23
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v22TagMapper.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v22TagMapper.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v24TagMapper.js +3 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2ChapterToken.js +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2Parser.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2Parser.js +32 -16
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2Token.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2Token.js +2 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/index.js +6 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/lrc/LyricsParser.js +3 -5
- package/node_modules/baileys/node_modules/music-metadata/lib/matroska/MatroskaDtd.js +7 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/matroska/MatroskaParser.js +22 -11
- package/node_modules/baileys/node_modules/music-metadata/lib/matroska/types.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/Atom.d.ts +4 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/Atom.js +44 -11
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/AtomToken.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/AtomToken.js +30 -8
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/MP4Parser.d.ts +2 -0
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/MP4Parser.js +79 -54
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/MP4TagMapper.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/MpegLoader.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/MpegParser.js +41 -19
- package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/ReplayGainDataFormat.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/ReplayGainDataFormat.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/XingTag.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/musepack/MusepackParser.js +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv7/BitReader.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv7/MpcSv7Parser.js +4 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv7/StreamVersion7.js +3 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv8/MpcSv8Parser.js +7 -5
- package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv8/StreamVersion8.js +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/OggParser.js +23 -13
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/OggToken.d.ts +2 -0
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/OggToken.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/flac/FlacStream.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/flac/FlacStream.js +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/opus/OpusStream.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/opus/OpusStream.js +8 -4
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/speex/SpeexStream.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/speex/SpeexStream.js +2 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/theora/TheoraStream.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/Vorbis.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/VorbisDecoder.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/VorbisStream.d.ts +4 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/VorbisStream.js +16 -9
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/VorbisTagMapper.js +4 -0
- package/node_modules/baileys/node_modules/music-metadata/lib/riff/RiffChunk.d.ts +3 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/riff/RiffChunk.js +3 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/riff/RiffInfoTagMap.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/type.d.ts +3 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/type.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/wav/WaveChunk.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/wav/WaveChunk.js +3 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/wav/WaveParser.d.ts +6 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/wav/WaveParser.js +75 -22
- package/node_modules/baileys/node_modules/music-metadata/lib/wavpack/WavPackParser.js +22 -13
- package/node_modules/baileys/node_modules/music-metadata/lib/wavpack/WavPackToken.js +3 -2
- package/node_modules/baileys/node_modules/music-metadata/package.json +3 -2
- package/node_modules/baileys/node_modules/uint8array-extras/index.d.ts +7 -7
- package/node_modules/baileys/node_modules/uint8array-extras/index.js +27 -13
- package/node_modules/baileys/node_modules/uint8array-extras/package.json +6 -6
- package/node_modules/baileys/node_modules/uint8array-extras/readme.md +7 -7
- package/node_modules/baileys/node_modules/ws/lib/websocket.js +17 -3
- package/node_modules/baileys/node_modules/ws/package.json +1 -1
- package/package.json +4 -4
- package/dist/.setup/audio-preflight.runtime-C_glQhZY.mjs +0 -7
- package/dist/.setup/channel.setup-CsS_NAKQ.mjs +0 -5
- package/dist/.setup/setup-plugin-api-Bsp7jI-r.mjs +0 -3
|
@@ -729,11 +729,11 @@ var experimentalFlag = "experimentalFlag";
|
|
|
729
729
|
var footerPresent = "footerPresent";
|
|
730
730
|
var ID3v2 = class _ID3v2 {
|
|
731
731
|
static *getID3v2Header(codecParser, headerCache, readOffset) {
|
|
732
|
-
const
|
|
732
|
+
const headerLength2 = 10;
|
|
733
733
|
const header2 = {};
|
|
734
734
|
let data3 = yield* codecParser[readRawData](3, readOffset);
|
|
735
735
|
if (data3[0] !== 73 || data3[1] !== 68 || data3[2] !== 51) return null;
|
|
736
|
-
data3 = yield* codecParser[readRawData](
|
|
736
|
+
data3 = yield* codecParser[readRawData](headerLength2, readOffset);
|
|
737
737
|
header2[version] = `id3v2.${data3[3]}.${data3[4]}`;
|
|
738
738
|
if (data3[5] & 15) return null;
|
|
739
739
|
header2[unsynchronizationFlag] = !!(data3[5] & 128);
|
|
@@ -743,7 +743,7 @@ var ID3v2 = class _ID3v2 {
|
|
|
743
743
|
if (data3[6] & 128 || data3[7] & 128 || data3[8] & 128 || data3[9] & 128)
|
|
744
744
|
return null;
|
|
745
745
|
const dataLength = data3[6] << 21 | data3[7] << 14 | data3[8] << 7 | data3[9];
|
|
746
|
-
header2[length] =
|
|
746
|
+
header2[length] = headerLength2 + dataLength;
|
|
747
747
|
return new _ID3v2(header2);
|
|
748
748
|
}
|
|
749
749
|
constructor(header2) {
|
|
@@ -974,7 +974,7 @@ var MPEGHeader = class _MPEGHeader extends CodecHeader {
|
|
|
974
974
|
if (header2[emphasis] === reserved) return null;
|
|
975
975
|
header2[bitDepth] = 16;
|
|
976
976
|
{
|
|
977
|
-
const { length: length2, frameLength: frameLength2, samples:
|
|
977
|
+
const { length: length2, frameLength: frameLength2, samples: samples2, ...codecUpdateFields } = header2;
|
|
978
978
|
headerCache[setHeader](key, header2, codecUpdateFields);
|
|
979
979
|
}
|
|
980
980
|
return new _MPEGHeader(header2);
|
|
@@ -1009,8 +1009,8 @@ var MPEGFrame = class _MPEGFrame extends CodecFrame {
|
|
|
1009
1009
|
readOffset
|
|
1010
1010
|
);
|
|
1011
1011
|
}
|
|
1012
|
-
constructor(header2, frame2,
|
|
1013
|
-
super(header2, frame2,
|
|
1012
|
+
constructor(header2, frame2, samples2) {
|
|
1013
|
+
super(header2, frame2, samples2);
|
|
1014
1014
|
}
|
|
1015
1015
|
};
|
|
1016
1016
|
|
|
@@ -1139,7 +1139,7 @@ var AACHeader = class _AACHeader extends CodecHeader {
|
|
|
1139
1139
|
profileBits: profileBits2,
|
|
1140
1140
|
sampleRateBits: sampleRateBits2,
|
|
1141
1141
|
frameLength: frameLength2,
|
|
1142
|
-
samples:
|
|
1142
|
+
samples: samples2,
|
|
1143
1143
|
numberAACFrames: numberAACFrames2,
|
|
1144
1144
|
...codecUpdateFields
|
|
1145
1145
|
} = header2;
|
|
@@ -1193,8 +1193,8 @@ var AACFrame = class _AACFrame extends CodecFrame {
|
|
|
1193
1193
|
readOffset
|
|
1194
1194
|
);
|
|
1195
1195
|
}
|
|
1196
|
-
constructor(header2, frame2,
|
|
1197
|
-
super(header2, frame2,
|
|
1196
|
+
constructor(header2, frame2, samples2) {
|
|
1197
|
+
super(header2, frame2, samples2);
|
|
1198
1198
|
}
|
|
1199
1199
|
};
|
|
1200
1200
|
|
|
@@ -1443,7 +1443,7 @@ var FLACHeader = class _FLACHeader extends CodecHeader {
|
|
|
1443
1443
|
blockingStrategyBits: blockingStrategyBits2,
|
|
1444
1444
|
frameNumber: frameNumber2,
|
|
1445
1445
|
sampleNumber: sampleNumber2,
|
|
1446
|
-
samples:
|
|
1446
|
+
samples: samples2,
|
|
1447
1447
|
sampleRateBits: sampleRateBits2,
|
|
1448
1448
|
blockSizeBits: blockSizeBits2,
|
|
1449
1449
|
crc: crc2,
|
|
@@ -1638,10 +1638,10 @@ var OggPage = class _OggPage extends Frame {
|
|
|
1638
1638
|
);
|
|
1639
1639
|
if (header2) {
|
|
1640
1640
|
const frameLengthValue = headerStore.get(header2)[frameLength];
|
|
1641
|
-
const
|
|
1642
|
-
const totalLength =
|
|
1641
|
+
const headerLength2 = headerStore.get(header2)[length];
|
|
1642
|
+
const totalLength = headerLength2 + frameLengthValue;
|
|
1643
1643
|
const rawDataValue = (yield* codecParser[readRawData](totalLength, 0))[subarray](0, totalLength);
|
|
1644
|
-
const frame2 = rawDataValue[subarray](
|
|
1644
|
+
const frame2 = rawDataValue[subarray](headerLength2, totalLength);
|
|
1645
1645
|
return new _OggPage(header2, frame2, rawDataValue);
|
|
1646
1646
|
} else {
|
|
1647
1647
|
return null;
|
|
@@ -1670,8 +1670,8 @@ init_text_decoder();
|
|
|
1670
1670
|
// ../../node_modules/codec-parser/src/codecs/opus/OpusFrame.js
|
|
1671
1671
|
init_text_decoder();
|
|
1672
1672
|
var OpusFrame = class extends CodecFrame {
|
|
1673
|
-
constructor(data3, header2,
|
|
1674
|
-
super(header2, data3,
|
|
1673
|
+
constructor(data3, header2, samples2) {
|
|
1674
|
+
super(header2, data3, samples2);
|
|
1675
1675
|
}
|
|
1676
1676
|
};
|
|
1677
1677
|
|
|
@@ -1859,12 +1859,12 @@ var OpusParser = class extends Parser {
|
|
|
1859
1859
|
if (header2) {
|
|
1860
1860
|
if (this._preSkipRemaining === null)
|
|
1861
1861
|
this._preSkipRemaining = header2[preSkip];
|
|
1862
|
-
let
|
|
1862
|
+
let samples2 = header2[frameSize] * header2[frameCount] / 1e3 * header2[sampleRate];
|
|
1863
1863
|
if (this._preSkipRemaining > 0) {
|
|
1864
|
-
this._preSkipRemaining -=
|
|
1865
|
-
|
|
1864
|
+
this._preSkipRemaining -= samples2;
|
|
1865
|
+
samples2 = this._preSkipRemaining < 0 ? -this._preSkipRemaining : 0;
|
|
1866
1866
|
}
|
|
1867
|
-
return new OpusFrame(segment, header2,
|
|
1867
|
+
return new OpusFrame(segment, header2, samples2);
|
|
1868
1868
|
}
|
|
1869
1869
|
this._codecParser[logError2](
|
|
1870
1870
|
"Failed to parse Ogg Opus Header",
|
|
@@ -1882,8 +1882,8 @@ init_text_decoder();
|
|
|
1882
1882
|
// ../../node_modules/codec-parser/src/codecs/vorbis/VorbisFrame.js
|
|
1883
1883
|
init_text_decoder();
|
|
1884
1884
|
var VorbisFrame = class extends CodecFrame {
|
|
1885
|
-
constructor(data3, header2,
|
|
1886
|
-
super(header2, data3,
|
|
1885
|
+
constructor(data3, header2, samples2) {
|
|
1886
|
+
super(header2, data3, samples2);
|
|
1887
1887
|
}
|
|
1888
1888
|
};
|
|
1889
1889
|
|
|
@@ -2421,7 +2421,6 @@ var codec_parser_default = CodecParser;
|
|
|
2421
2421
|
var codecFrames2 = codecFrames;
|
|
2422
2422
|
var data2 = data;
|
|
2423
2423
|
var isLastPage2 = isLastPage;
|
|
2424
|
-
var samples2 = samples;
|
|
2425
2424
|
var totalSamples2 = totalSamples;
|
|
2426
2425
|
|
|
2427
2426
|
// ../../node_modules/@wasm-audio-decoders/flac/src/EmscriptenWasm.js
|
|
@@ -2880,10 +2879,10 @@ var FLACDecoder = class {
|
|
|
2880
2879
|
[decodeFlac](flacFrames) {
|
|
2881
2880
|
return this._decoder.decodeFrames(flacFrames.map((f) => f[data2] || f));
|
|
2882
2881
|
}
|
|
2883
|
-
[decodeOggFlac](
|
|
2884
|
-
const frames =
|
|
2882
|
+
[decodeOggFlac](oggPages2) {
|
|
2883
|
+
const frames = oggPages2.map((page2) => page2[codecFrames2].map((f) => f[data2])).flat();
|
|
2885
2884
|
const decoded = this._decoder.decodeFrames(frames);
|
|
2886
|
-
const oggPage =
|
|
2885
|
+
const oggPage = oggPages2[oggPages2.length - 1];
|
|
2887
2886
|
if (oggPage && oggPage[isLastPage2]) {
|
|
2888
2887
|
const samplesToTrim = this[totalSamplesDecoded] - oggPage[totalSamples2];
|
|
2889
2888
|
if (samplesToTrim > 0) {
|
|
@@ -2936,6 +2935,44 @@ var FLACDecoder = class {
|
|
|
2936
2935
|
}
|
|
2937
2936
|
};
|
|
2938
2937
|
|
|
2938
|
+
// ../_build/ogg.js
|
|
2939
|
+
init_text_decoder();
|
|
2940
|
+
var isPage = (b, o) => b[o] === 79 && b[o + 1] === 103 && b[o + 2] === 103 && b[o + 3] === 83;
|
|
2941
|
+
function whole(buf) {
|
|
2942
|
+
let o = 0;
|
|
2943
|
+
while (o + 27 <= buf.length) {
|
|
2944
|
+
if (!isPage(buf, o)) {
|
|
2945
|
+
let k = o + 1;
|
|
2946
|
+
while (k + 4 <= buf.length && !isPage(buf, k)) k++;
|
|
2947
|
+
if (k + 4 > buf.length) return Math.max(o, buf.length - 3);
|
|
2948
|
+
o = k;
|
|
2949
|
+
continue;
|
|
2950
|
+
}
|
|
2951
|
+
let body = o + 27 + buf[o + 26], end = body;
|
|
2952
|
+
if (body > buf.length) break;
|
|
2953
|
+
for (let i = o + 27; i < body; i++) end += buf[i];
|
|
2954
|
+
if (end > buf.length) break;
|
|
2955
|
+
o = end;
|
|
2956
|
+
}
|
|
2957
|
+
return o;
|
|
2958
|
+
}
|
|
2959
|
+
function oggPages() {
|
|
2960
|
+
let tail = null;
|
|
2961
|
+
return {
|
|
2962
|
+
push(chunk) {
|
|
2963
|
+
let buf = tail ? concat(tail, chunk) : chunk, n = whole(buf);
|
|
2964
|
+
tail = n < buf.length ? buf.slice(n) : null;
|
|
2965
|
+
return buf.subarray(0, n);
|
|
2966
|
+
}
|
|
2967
|
+
};
|
|
2968
|
+
}
|
|
2969
|
+
function concat(a, b) {
|
|
2970
|
+
let out = new Uint8Array(a.length + b.length);
|
|
2971
|
+
out.set(a);
|
|
2972
|
+
out.set(b, a.length);
|
|
2973
|
+
return out;
|
|
2974
|
+
}
|
|
2975
|
+
|
|
2939
2976
|
// src/decode-flac.src.js
|
|
2940
2977
|
var EMPTY = Object.freeze({ channelData: Object.freeze([]), sampleRate: 0 });
|
|
2941
2978
|
async function decode(src) {
|
|
@@ -2967,7 +3004,7 @@ async function decoder() {
|
|
|
2967
3004
|
upstream.free();
|
|
2968
3005
|
throw Error("Unsupported @wasm-audio-decoders/flac internals");
|
|
2969
3006
|
}
|
|
2970
|
-
let parser = null, prefix = null, lookahead = null, ogg = false, total2 = 0, fresh = true;
|
|
3007
|
+
let parser = null, prefix = null, lookahead = null, ogg = false, pages = oggPages(), total2 = 0, fresh = true;
|
|
2971
3008
|
let pendingRaw = false, duplicateFrames = 0, ended = false, freed = false;
|
|
2972
3009
|
let resetStream = () => {
|
|
2973
3010
|
wasm.destroy_decoder(codec2._decoder);
|
|
@@ -2979,6 +3016,7 @@ async function decoder() {
|
|
|
2979
3016
|
prefix = null;
|
|
2980
3017
|
lookahead = null;
|
|
2981
3018
|
ogg = false;
|
|
3019
|
+
pages = oggPages();
|
|
2982
3020
|
total2 = 0;
|
|
2983
3021
|
fresh = true;
|
|
2984
3022
|
pendingRaw = false;
|
|
@@ -3059,7 +3097,7 @@ async function decoder() {
|
|
|
3059
3097
|
}
|
|
3060
3098
|
}
|
|
3061
3099
|
}
|
|
3062
|
-
let r = decodeItems([...parser.parseChunk(buf)]);
|
|
3100
|
+
let r = decodeItems([...parser.parseChunk(ogg ? pages.push(buf) : buf)]);
|
|
3063
3101
|
return hasAudio(r) ? r : EMPTY;
|
|
3064
3102
|
};
|
|
3065
3103
|
upstream.flush = () => {
|
|
@@ -3090,20 +3128,114 @@ async function decoder() {
|
|
|
3090
3128
|
return upstream;
|
|
3091
3129
|
}
|
|
3092
3130
|
function createParser(ogg) {
|
|
3093
|
-
|
|
3131
|
+
if (!ogg) return rawParser();
|
|
3132
|
+
return new codec_parser_default("audio/ogg", {
|
|
3094
3133
|
onCodec: (codec2) => {
|
|
3095
3134
|
if (codec2 !== "flac") throw Error("@audio/decode-flac does not support this codec " + codec2);
|
|
3096
3135
|
},
|
|
3097
3136
|
enableFrameCRC32: false
|
|
3098
3137
|
});
|
|
3099
3138
|
}
|
|
3139
|
+
function rawParser() {
|
|
3140
|
+
let buf = new Uint8Array(0), meta = true, start = -1, scan = 0, crc2 = 0;
|
|
3141
|
+
function* frames(end) {
|
|
3142
|
+
if (meta) {
|
|
3143
|
+
if (buf.length < 4) return;
|
|
3144
|
+
let o = 0;
|
|
3145
|
+
if (buf[0] === 102 && buf[1] === 76 && buf[2] === 97 && buf[3] === 67) {
|
|
3146
|
+
o = 4;
|
|
3147
|
+
for (; ; ) {
|
|
3148
|
+
if (o + 4 > buf.length) return;
|
|
3149
|
+
let last = buf[o] & 128, len = buf[o + 1] << 16 | buf[o + 2] << 8 | buf[o + 3];
|
|
3150
|
+
o += 4 + len;
|
|
3151
|
+
if (o > buf.length) return;
|
|
3152
|
+
if (last) break;
|
|
3153
|
+
}
|
|
3154
|
+
}
|
|
3155
|
+
meta = false;
|
|
3156
|
+
buf = buf.subarray(o);
|
|
3157
|
+
}
|
|
3158
|
+
if (start < 0) {
|
|
3159
|
+
let p = 0;
|
|
3160
|
+
while (p + 1 < buf.length && headerLength(buf, p) < 0) p++;
|
|
3161
|
+
if (headerLength(buf, p) < 0) {
|
|
3162
|
+
buf = buf.subarray(p);
|
|
3163
|
+
return;
|
|
3164
|
+
}
|
|
3165
|
+
start = p;
|
|
3166
|
+
scan = p;
|
|
3167
|
+
crc2 = 0;
|
|
3168
|
+
}
|
|
3169
|
+
for (; ; ) {
|
|
3170
|
+
let next = -1;
|
|
3171
|
+
for (; scan < buf.length; scan++) {
|
|
3172
|
+
if (scan > start + 3 && crc2 === 0 && buf[scan] === 255 && (buf[scan + 1] & 254) === 248 && headerLength(buf, scan) > 0) {
|
|
3173
|
+
next = scan;
|
|
3174
|
+
break;
|
|
3175
|
+
}
|
|
3176
|
+
crc2 = CRC16[crc2 >> 8 ^ buf[scan]] ^ crc2 << 8 & 65535;
|
|
3177
|
+
}
|
|
3178
|
+
if (next < 0) {
|
|
3179
|
+
if (end && start < buf.length && crc2 === 0) {
|
|
3180
|
+
yield buf.subarray(start);
|
|
3181
|
+
start = scan = buf.length;
|
|
3182
|
+
}
|
|
3183
|
+
break;
|
|
3184
|
+
}
|
|
3185
|
+
yield buf.subarray(start, next);
|
|
3186
|
+
start = next;
|
|
3187
|
+
crc2 = 0;
|
|
3188
|
+
scan = next;
|
|
3189
|
+
}
|
|
3190
|
+
buf = buf.subarray(start);
|
|
3191
|
+
scan -= start;
|
|
3192
|
+
start = 0;
|
|
3193
|
+
}
|
|
3194
|
+
return {
|
|
3195
|
+
parseChunk(chunk) {
|
|
3196
|
+
buf = buf.length ? concatBytes(buf, chunk) : chunk;
|
|
3197
|
+
return [...frames(false)];
|
|
3198
|
+
},
|
|
3199
|
+
parseAll(all) {
|
|
3200
|
+
buf = all;
|
|
3201
|
+
return [...frames(true)];
|
|
3202
|
+
},
|
|
3203
|
+
flush() {
|
|
3204
|
+
return [...frames(true)];
|
|
3205
|
+
}
|
|
3206
|
+
};
|
|
3207
|
+
}
|
|
3208
|
+
var CRC16 = Uint16Array.from({ length: 256 }, (_, i) => {
|
|
3209
|
+
let c = i << 8;
|
|
3210
|
+
for (let k = 0; k < 8; k++) c = c & 32768 ? c << 1 ^ 32773 : c << 1;
|
|
3211
|
+
return c & 65535;
|
|
3212
|
+
});
|
|
3213
|
+
function headerLength(b, p) {
|
|
3214
|
+
if (p + 5 > b.length || b[p] !== 255 || (b[p + 1] & 254) !== 248) return -1;
|
|
3215
|
+
let bs = b[p + 2] >> 4, sr = b[p + 2] & 15;
|
|
3216
|
+
if (!bs || sr === 15 || b[p + 3] >> 4 > 10 || b[p + 3] & 1) return -1;
|
|
3217
|
+
let q = p + 4, c = b[q], n = c < 128 ? 0 : c < 224 ? 1 : c < 240 ? 2 : c < 248 ? 3 : c < 252 ? 4 : c < 254 ? 5 : 6;
|
|
3218
|
+
q += 1 + n + (bs === 6 ? 1 : bs === 7 ? 2 : 0) + (sr === 12 ? 1 : sr === 13 || sr === 14 ? 2 : 0);
|
|
3219
|
+
if (q >= b.length) return -1;
|
|
3220
|
+
let crc2 = 0;
|
|
3221
|
+
for (let i = p; i < q; i++) {
|
|
3222
|
+
crc2 ^= b[i];
|
|
3223
|
+
for (let k = 0; k < 8; k++) crc2 = crc2 & 128 ? (crc2 << 1 ^ 7) & 255 : crc2 << 1 & 255;
|
|
3224
|
+
}
|
|
3225
|
+
return crc2 === b[q] ? q - p + 1 : -1;
|
|
3226
|
+
}
|
|
3227
|
+
function frameSamples(b) {
|
|
3228
|
+
let bs = b[2] >> 4, c = b[4], n = c < 128 ? 0 : c < 224 ? 1 : c < 240 ? 2 : c < 248 ? 3 : c < 252 ? 4 : c < 254 ? 5 : 6;
|
|
3229
|
+
let q = 5 + n;
|
|
3230
|
+
return bs === 1 ? 192 : bs <= 5 ? 576 << bs - 2 : bs === 6 ? b[q] + 1 : bs === 7 ? (b[q] << 8 | b[q + 1]) + 1 : 256 << bs - 8;
|
|
3231
|
+
}
|
|
3100
3232
|
function parseInitialFlac(buf) {
|
|
3101
3233
|
let info = flacInfo(buf);
|
|
3102
3234
|
if (!info) return null;
|
|
3103
3235
|
try {
|
|
3104
3236
|
let frames = [...createParser(false).parseAll(buf)];
|
|
3105
3237
|
if (!frames.length) return null;
|
|
3106
|
-
let parsed = frames.reduce((total2, frame2) => total2 + (frame2
|
|
3238
|
+
let parsed = frames.reduce((total2, frame2) => total2 + frameSamples(frame2), 0);
|
|
3107
3239
|
return !info.total || parsed === info.total ? { frames, total: info.total } : null;
|
|
3108
3240
|
} catch {
|
|
3109
3241
|
return null;
|
|
@@ -33,7 +33,7 @@ dec.free()
|
|
|
33
33
|
| `dtsc`, `dtsh`, `dtsl`, `dtse`, `mp4a` (0xA9) | DTS (core) | [@audio/decode-dts](../decode-dts) |
|
|
34
34
|
| `ec-3`, `mp4a` (0xA6) | E-AC-3 (Dolby Digital Plus) | [@audio/decode-eac3](../decode-eac3) |
|
|
35
35
|
|
|
36
|
-
TrueHD tracks throw an error naming the codec. Fragmented MP4 (`moof`)
|
|
36
|
+
TrueHD tracks throw an error naming the codec. Fragmented MP4 (ISO/IEC 14496-12 §8.8, `moof`+`mdat` after an empty-table `moov`) streams fragment by fragment, holding only the bytes not yet read. QuickTime sound descriptions v0, v1 and v2 are handled, including `wave`-wrapped configs and `enda` endianness flags. When `moov` follows `mdat` (typical of camera and QuickTime output) the file is buffered until the header arrives.
|
|
37
37
|
|
|
38
38
|
Codec packages are imported dynamically, which is unavailable inside an AudioWorklet — decode in the main thread or a Worker.
|
|
39
39
|
|
|
@@ -41,6 +41,7 @@ class MP4Decoder {
|
|
|
41
41
|
this.pending = null // codec load in flight
|
|
42
42
|
this.codec = null // { feed(frames), flush(), free() }
|
|
43
43
|
this.st = null // sample-table walker: { sizes, stco, stsc, idx, ci, sInC, spc, nextOff }
|
|
44
|
+
this.fr = null // fragment walker (fragmented file): { id, trex, pos, queue, qi }
|
|
44
45
|
this.left = null // unconsumed bytes
|
|
45
46
|
this.fileOff = 0 // absolute file offset of left[0]
|
|
46
47
|
this.skip = 0 // bytes to discard before the next sample
|
|
@@ -52,7 +53,7 @@ class MP4Decoder {
|
|
|
52
53
|
if (!data || !data.byteLength) return EMPTY
|
|
53
54
|
let buf = data instanceof Uint8Array ? data : new Uint8Array(data)
|
|
54
55
|
if (this.pending) return this.pending.then(() => this.decode(buf))
|
|
55
|
-
if (this.st) return this.feed(buf)
|
|
56
|
+
if (this.st || this.fr) return this.feed(buf)
|
|
56
57
|
|
|
57
58
|
this.accum.push(buf); this.accumLen += buf.length
|
|
58
59
|
let all = this.accum.length === 1 ? this.accum[0] : concat(this.accum, this.accumLen)
|
|
@@ -64,8 +65,10 @@ class MP4Decoder {
|
|
|
64
65
|
if (this.freed) { codec.free(); return EMPTY }
|
|
65
66
|
this.codec = codec
|
|
66
67
|
let { sizes, stco, stsc } = track
|
|
67
|
-
this.st = { sizes, stco, stsc, idx: 0, ci: 0, sInC: 0, spc: spcAt(0, stsc), nextOff: stco[0] }
|
|
68
68
|
this.left = all; this.fileOff = 0; this.skip = 0
|
|
69
|
+
// fragmented (ISO/IEC 14496-12 §8.8): samples come in moof+mdat pairs after the moov
|
|
70
|
+
if (track.fragmented) { this.fr = { id: track.id, trex: track.trex, pos: 0, queue: [], qi: 0 }; return this.fragments() }
|
|
71
|
+
this.st = { sizes, stco, stsc, idx: 0, ci: 0, sInC: 0, spc: spcAt(0, stsc), nextOff: stco[0] }
|
|
69
72
|
return this.extract()
|
|
70
73
|
})
|
|
71
74
|
}
|
|
@@ -78,7 +81,37 @@ class MP4Decoder {
|
|
|
78
81
|
if (!buf.length) return EMPTY
|
|
79
82
|
}
|
|
80
83
|
this.left = append(this.left, buf)
|
|
81
|
-
return this.extract()
|
|
84
|
+
return this.fr ? this.fragments() : this.extract()
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Top-level boxes in order: each complete moof queues its samples (absolute offsets), which are
|
|
88
|
+
// read out of the following mdat as its bytes arrive; bytes nobody needs any more are dropped.
|
|
89
|
+
fragments() {
|
|
90
|
+
let fr = this.fr, frames = []
|
|
91
|
+
for (;;) {
|
|
92
|
+
let q = fr.queue
|
|
93
|
+
for (; fr.qi < q.length; fr.qi++) {
|
|
94
|
+
let [off, sz] = q[fr.qi], b = off - this.fileOff
|
|
95
|
+
if (!this.left || b + sz > this.left.length) break
|
|
96
|
+
frames.push(this.left.subarray(b, b + sz))
|
|
97
|
+
}
|
|
98
|
+
if (fr.qi === q.length) { q.length = 0; fr.qi = 0 }
|
|
99
|
+
let b = fr.pos - this.fileOff, left = this.left
|
|
100
|
+
if (fr.pos === Infinity || !left || b < 0 || b + 8 > left.length) break
|
|
101
|
+
let size = r32(left, b), type = str4(left, b + 4)
|
|
102
|
+
if (size === 1) { if (b + 16 > left.length) break; size = r32(left, b + 8) * 0x100000000 + r32(left, b + 12) }
|
|
103
|
+
else if (size === 0) size = Infinity // to the end of the file
|
|
104
|
+
if (type === 'moof') {
|
|
105
|
+
if (b + size > left.length) break // wait for the whole moof
|
|
106
|
+
moofSamples(left, b, size, fr.pos, fr)
|
|
107
|
+
}
|
|
108
|
+
fr.pos += size
|
|
109
|
+
}
|
|
110
|
+
// keep bytes from the next queued sample or the next box, whichever comes first
|
|
111
|
+
let keep = Math.min(fr.pos, fr.qi < fr.queue.length ? fr.queue[fr.qi][0] : Infinity), end = this.fileOff + (this.left?.length || 0)
|
|
112
|
+
if (keep >= end && keep !== Infinity) { this.skip = keep - end; this.fileOff = end; this.left = null }
|
|
113
|
+
else if (keep > this.fileOff && keep !== Infinity) { this.left = this.left.subarray(keep - this.fileOff).slice(); this.fileOff = keep }
|
|
114
|
+
return frames.length ? this.codec.feed(frames) : EMPTY
|
|
82
115
|
}
|
|
83
116
|
|
|
84
117
|
// Walk sample tables by absolute file offset so chunk boundaries are irrelevant.
|
|
@@ -104,7 +137,6 @@ class MP4Decoder {
|
|
|
104
137
|
if (this.pending) return this.pending.then(() => this.flush())
|
|
105
138
|
this.freed = true
|
|
106
139
|
if (!this.codec) {
|
|
107
|
-
if (this.accumLen && findBox(concat(this.accum, this.accumLen), 'moof')) throw Error('Fragmented MP4 is not supported')
|
|
108
140
|
throw Error(this.accumLen ? 'No audio track found in MP4' : 'Not an MP4 file')
|
|
109
141
|
}
|
|
110
142
|
try { return this.codec.flush() } finally { this.codec.free(); this.codec = null; this.left = null }
|
|
@@ -114,14 +146,14 @@ class MP4Decoder {
|
|
|
114
146
|
if (this.freed) return
|
|
115
147
|
this.freed = true
|
|
116
148
|
this.codec?.free(); this.codec = null
|
|
117
|
-
this.accum = []; this.left = null; this.st = null
|
|
149
|
+
this.accum = []; this.left = null; this.st = null; this.fr = null
|
|
118
150
|
}
|
|
119
151
|
}
|
|
120
152
|
|
|
121
153
|
|
|
122
154
|
// ===== ISO BMFF demuxer =====
|
|
123
155
|
|
|
124
|
-
const CONTAINERS = new Set(['moov', 'trak', 'mdia', 'minf', 'stbl', 'udta', 'edts', 'sinf', 'wave'])
|
|
156
|
+
const CONTAINERS = new Set(['moov', 'trak', 'mdia', 'minf', 'stbl', 'udta', 'edts', 'sinf', 'wave', 'mvex', 'traf'])
|
|
125
157
|
|
|
126
158
|
/** Walk boxes in [start, end), calling cb(type, body, bodyOff) for leaves and cb(type, null) at container boundaries. */
|
|
127
159
|
function walk(buf, start, end, cb) {
|
|
@@ -144,10 +176,37 @@ function walk(buf, start, end, cb) {
|
|
|
144
176
|
return true
|
|
145
177
|
}
|
|
146
178
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
179
|
+
/** Queue the samples a moof's track fragments place (ISO/IEC 14496-12 §8.8.7 tfhd, §8.8.8 trun):
|
|
180
|
+
* absolute [offset, size] pairs, sizes from trun, else tfhd's default, else trex's. */
|
|
181
|
+
function moofSamples(buf, start, size, abs, fr) {
|
|
182
|
+
let traf = null
|
|
183
|
+
walk(buf, start + 8, start + size, (type, d) => {
|
|
184
|
+
if (type === 'traf') traf = { base: abs, size: fr.trex.size || 0, mine: false, next: null }
|
|
185
|
+
else if (type === 'tfhd') {
|
|
186
|
+
let flags = (d[1] << 16) | (d[2] << 8) | d[3], p = 8
|
|
187
|
+
traf.mine = r32(d, 4) === fr.id
|
|
188
|
+
if (flags & 1) { traf.base = r32(d, p) * 0x100000000 + r32(d, p + 4); p += 8 } // else: default-base-is-moof, or the first traf
|
|
189
|
+
if (flags & 2) p += 4
|
|
190
|
+
if (flags & 8) p += 4
|
|
191
|
+
if (flags & 0x10) traf.size = r32(d, p)
|
|
192
|
+
}
|
|
193
|
+
else if (type === 'trun' && traf?.mine) {
|
|
194
|
+
let flags = (d[1] << 16) | (d[2] << 8) | d[3], n = r32(d, 4), p = 8
|
|
195
|
+
let off = traf.next ?? traf.base
|
|
196
|
+
if (flags & 1) { off = traf.base + (r32(d, p) | 0); p += 4 }
|
|
197
|
+
if (flags & 4) p += 4
|
|
198
|
+
for (let i = 0; i < n; i++) {
|
|
199
|
+
if (flags & 0x100) p += 4
|
|
200
|
+
let sz = traf.size
|
|
201
|
+
if (flags & 0x200) { sz = r32(d, p); p += 4 }
|
|
202
|
+
if (flags & 0x400) p += 4
|
|
203
|
+
if (flags & 0x800) p += 4
|
|
204
|
+
fr.queue.push([off, sz])
|
|
205
|
+
off += sz
|
|
206
|
+
}
|
|
207
|
+
traf.next = off
|
|
208
|
+
}
|
|
209
|
+
})
|
|
151
210
|
}
|
|
152
211
|
|
|
153
212
|
// QuickTime sound sample description: v0 = 36-byte header, v1 adds 16 bytes, v2 declares its own size.
|
|
@@ -179,13 +238,17 @@ function parseStsd(buf, off, end, cb) {
|
|
|
179
238
|
|
|
180
239
|
/** Parse the first audio track out of a complete moov. Returns null while moov is incomplete or absent. */
|
|
181
240
|
function parseTrack(buf) {
|
|
182
|
-
let traks = [], t = null, moov = false
|
|
241
|
+
let traks = [], t = null, moov = false, trex = new Map(), movie = {}
|
|
183
242
|
walk(buf, 0, buf.length, (type, data, off) => {
|
|
184
243
|
if (type === 'moov') moov = true
|
|
244
|
+
else if (type === 'mvhd' || type === 'ilst' && !t) movie[type] = data // movie timescale; iTunes tags
|
|
185
245
|
else if (type === 'trak') traks.push(t = { children: {} })
|
|
246
|
+
else if (type === '/trak') t = null
|
|
247
|
+
else if (type === 'trex') trex.set(r32(data, 4), { size: r32(data, 16) })
|
|
186
248
|
else if (!t) return
|
|
249
|
+
else if (type === 'tkhd') t.id = r32(data, data[0] === 1 ? 20 : 12)
|
|
187
250
|
else if (type === 'hdlr') t.handler = str4(data, 8)
|
|
188
|
-
else if (type === 'mdhd') t.timescale = r32(data, data[0] === 1 ? 20 : 12)
|
|
251
|
+
else if (type === 'mdhd') { t.timescale = r32(data, data[0] === 1 ? 20 : 12); t.children.mdhd = data }
|
|
189
252
|
else if (type === 'entry') t.entry ??= data
|
|
190
253
|
else if (type === 'stsz') t.sizes = parseStsz(data)
|
|
191
254
|
else if (type === 'stco') t.stco = parseStco(data)
|
|
@@ -196,8 +259,11 @@ function parseTrack(buf) {
|
|
|
196
259
|
if (!moov) return null
|
|
197
260
|
let track = traks.find(t => t.handler === 'soun' && t.entry) ?? traks.find(t => t.entry && AUDIO_TYPES.has(t.entry.type))
|
|
198
261
|
if (!track) throw Error('No audio track found in MP4')
|
|
199
|
-
|
|
262
|
+
// movie fragments carry the samples when mvex is there and the tables are empty
|
|
263
|
+
if (trex.size && !track.sizes?.length) { track.fragmented = true; track.trex = trex.get(track.id) || {} }
|
|
264
|
+
else if (!track.sizes || !track.stco?.length) throw Error('Audio track has no sample tables')
|
|
200
265
|
if (!track.entry.sampleRate && track.timescale) track.entry.sampleRate = track.timescale
|
|
266
|
+
track.movie = movie
|
|
201
267
|
return track
|
|
202
268
|
}
|
|
203
269
|
|
|
@@ -252,32 +318,34 @@ const MP3_OTI = new Set([0x69, 0x6B]), AAC_OTI = new Set([0x40, 0x66, 0x67, 0x68
|
|
|
252
318
|
const UNSUPPORTED = { 0xE1: 'QCELP' }
|
|
253
319
|
const DTS_TYPES = new Set(['dtsc', 'dtsh', 'dtsl', 'dtse']) // DTS-HD variants carry a decodable core
|
|
254
320
|
|
|
255
|
-
async function createCodec({ entry, children }) {
|
|
321
|
+
async function createCodec({ entry, children, movie }) {
|
|
256
322
|
let { type } = entry
|
|
323
|
+
// AAC and ALAC trim the encoder's priming and padding by the track's edit list or iTunSMPB, MP3 and Opus by the edit list (gapless)
|
|
324
|
+
let boxes = { elst: children.elst, mdhd: children.mdhd, stts: children.stts, mvhd: movie?.mvhd, ilst: movie?.ilst ?? children.ilst }
|
|
257
325
|
if (type === 'mp4a') {
|
|
258
326
|
let { oti, dsi } = children.esds ? parseEsds(children.esds) : {}
|
|
259
|
-
if (MP3_OTI.has(oti)) return
|
|
327
|
+
if (MP3_OTI.has(oti)) return mp3(boxes)
|
|
260
328
|
if (oti === 0xA5) return frames(import('@audio/decode-ac3'))
|
|
261
329
|
if (oti === 0xA9) return frames(import('@audio/decode-dts'))
|
|
262
330
|
if (oti === 0xA6) return frames(import('@audio/decode-eac3'))
|
|
263
331
|
if (!oti || AAC_OTI.has(oti)) {
|
|
264
332
|
if (!dsi) throw Error('MP4 AAC track has no AudioSpecificConfig')
|
|
265
|
-
return aac({ asc: dsi })
|
|
333
|
+
return aac({ asc: dsi }, boxes)
|
|
266
334
|
}
|
|
267
335
|
throw unsupported(UNSUPPORTED[oti] || 'esds object type 0x' + oti.toString(16))
|
|
268
336
|
}
|
|
269
337
|
if (type === 'alac') {
|
|
270
338
|
if (!children.alac) throw Error('MP4 ALAC track has no magic cookie')
|
|
271
|
-
return aac({ alac: children.alac })
|
|
339
|
+
return aac({ alac: children.alac }, boxes)
|
|
272
340
|
}
|
|
273
|
-
if (type === '.mp3') return
|
|
341
|
+
if (type === '.mp3') return mp3(boxes)
|
|
274
342
|
if (type === 'fLaC') {
|
|
275
343
|
if (!children.dfLa) throw Error('MP4 FLAC track has no dfLa box')
|
|
276
344
|
return flac(children.dfLa.subarray(4))
|
|
277
345
|
}
|
|
278
346
|
if (type === 'Opus') {
|
|
279
347
|
if (!children.dOps) throw Error('MP4 Opus track has no dOps box')
|
|
280
|
-
return opus(children.dOps)
|
|
348
|
+
return opus(children.dOps, boxes)
|
|
281
349
|
}
|
|
282
350
|
if (type === 'samr' || type === 'sawb') return amr(type === 'sawb')
|
|
283
351
|
if (type === 'ac-3') return frames(import('@audio/decode-ac3'))
|
|
@@ -319,8 +387,9 @@ function pcmFormat(e, ch) {
|
|
|
319
387
|
|
|
320
388
|
// --- adapters: { feed(frames: Uint8Array[]), flush(), free() } ---
|
|
321
389
|
|
|
322
|
-
async function aac(opts) {
|
|
323
|
-
let
|
|
390
|
+
async function aac(opts, boxes) {
|
|
391
|
+
let { decoder, gapless } = await import('@audio/decode-aac')
|
|
392
|
+
let dec = await decoder({ ...opts, gapless: gapless?.({ ...boxes, ...opts }) })
|
|
324
393
|
return { feed: frames => dec.decode(frames), flush: () => dec.flush(), free: () => dec.free() }
|
|
325
394
|
}
|
|
326
395
|
|
|
@@ -330,6 +399,28 @@ async function frames(load) {
|
|
|
330
399
|
return { feed: frames => dec.decode(concat(frames)), flush: () => dec.flush?.() ?? EMPTY, free: () => dec.free() }
|
|
331
400
|
}
|
|
332
401
|
|
|
402
|
+
// MP3 samples carry no LAME tag, so mpg123 decodes from the media's first sample: the edit list's window drops the
|
|
403
|
+
// encoder and decoder delay (1105 for LAME, as ffmpeg writes it) and the padding. decode-aac reads the window.
|
|
404
|
+
async function mp3(boxes) {
|
|
405
|
+
let [codec, { gapless }] = await Promise.all([frames(import('@audio/decode-mp3')), import('@audio/decode-aac')])
|
|
406
|
+
return windowed(codec, gapless?.(boxes))
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// the edit list's window { start, duration } (seconds) over a codec that decodes from the media's first sample
|
|
410
|
+
function windowed(codec, g) {
|
|
411
|
+
if (!g) return codec
|
|
412
|
+
let skip = null, left = null
|
|
413
|
+
let cut = r => {
|
|
414
|
+
let n = r.channelData?.[0]?.length
|
|
415
|
+
if (!n) return r
|
|
416
|
+
skip ??= Math.round(g.start * r.sampleRate); left ??= g.duration == null ? Infinity : Math.round(g.duration * r.sampleRate)
|
|
417
|
+
let a = Math.min(n, skip), b = Math.min(n, a + left)
|
|
418
|
+
skip -= a; left -= b - a
|
|
419
|
+
return b <= a ? EMPTY : a || b < n ? { ...r, channelData: r.channelData.map(c => c.subarray(a, b)) } : r
|
|
420
|
+
}
|
|
421
|
+
return { feed: frames => cut(codec.feed(frames)), flush: () => cut(codec.flush()), free: codec.free }
|
|
422
|
+
}
|
|
423
|
+
|
|
333
424
|
async function flac(blocks) {
|
|
334
425
|
let dec = await (await import('@audio/decode-flac')).decoder()
|
|
335
426
|
let head = concat([new Uint8Array([0x66, 0x4C, 0x61, 0x43]), blocks]) // "fLaC" + METADATA_BLOCKs
|
|
@@ -341,16 +432,24 @@ async function flac(blocks) {
|
|
|
341
432
|
}
|
|
342
433
|
}
|
|
343
434
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
435
|
+
// Mapping family 1 orders 3–8 channels as Vorbis does (RFC 7845 §5.1.1.2): out in SMPTE/WAV order (L R C LFE Ls Rs …)
|
|
436
|
+
// as decode-opus reorders Ogg Opus: output channel j takes the coded channel of Vorbis position OPUS_ORDER[n][j]
|
|
437
|
+
const OPUS_ORDER = { 3: [0, 2, 1], 5: [0, 2, 1, 3, 4], 6: [0, 2, 1, 5, 3, 4], 7: [0, 2, 1, 6, 5, 3, 4], 8: [0, 2, 1, 7, 5, 6, 3, 4] }
|
|
438
|
+
|
|
439
|
+
// Opus in ISOBMFF: the edit list's media_time covers PreSkip and its duration is the real length, so with an edit
|
|
440
|
+
// list the window trims both ends from the media's first sample; without one, dOps' PreSkip trims the start
|
|
441
|
+
async function opus(dOps, boxes) {
|
|
442
|
+
let [{ createOpusDecoder }, { gapless }] = await Promise.all([import('@audio/decode-opus/core'), import('@audio/decode-aac')])
|
|
443
|
+
let g = gapless?.(boxes), channels = dOps[1]
|
|
444
|
+
let opts = { channels, sampleRate: 48000, preSkip: g ? 0 : r16(dOps, 2), outputGain: (r16(dOps, 8) << 16) >> 16 }
|
|
347
445
|
if (dOps[10] > 0) {
|
|
348
446
|
opts.streamCount = dOps[11]; opts.coupledStreamCount = dOps[12]
|
|
349
|
-
|
|
447
|
+
let table = Array.from(dOps.subarray(13, 13 + channels))
|
|
448
|
+
opts.channelMappingTable = dOps[10] === 1 && OPUS_ORDER[channels] ? OPUS_ORDER[channels].map(i => table[i]) : table
|
|
350
449
|
}
|
|
351
|
-
let dec = await
|
|
450
|
+
let dec = await createOpusDecoder()
|
|
352
451
|
dec.configure(opts)
|
|
353
|
-
return {
|
|
452
|
+
return windowed({
|
|
354
453
|
feed: frames => {
|
|
355
454
|
let r = dec.decodeFrames(frames)
|
|
356
455
|
if (!r.samplesDecoded) return EMPTY
|
|
@@ -358,7 +457,7 @@ async function opus(dOps) {
|
|
|
358
457
|
},
|
|
359
458
|
flush: () => EMPTY,
|
|
360
459
|
free: () => dec.free()
|
|
361
|
-
}
|
|
460
|
+
}, g)
|
|
362
461
|
}
|
|
363
462
|
|
|
364
463
|
async function amr(wb) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@audio/decode-mp4",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Decode the audio track of MP4, MOV, M4A, M4V and 3GP files (AAC, ALAC, MP3, FLAC, Opus, AMR, PCM) to PCM samples",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "decode-mp4.js",
|
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
"LICENSE"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@audio/decode-aac": "^1.
|
|
30
|
+
"@audio/decode-aac": "^1.6.0",
|
|
31
31
|
"@audio/decode-ac3": "^1.0.0",
|
|
32
32
|
"@audio/decode-amr": "^1.3.0",
|
|
33
33
|
"@audio/decode-dts": "^1.0.0",
|
|
34
34
|
"@audio/decode-flac": "^1.3.0",
|
|
35
35
|
"@audio/decode-mp3": "^1.3.0",
|
|
36
|
-
"@audio/decode-opus": "^1.3.
|
|
36
|
+
"@audio/decode-opus": "^1.3.3",
|
|
37
37
|
"@audio/decode-eac3": "^1.0.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|