@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.
Files changed (212) hide show
  1. package/dist/.setup/{action-runtime-CE3zGstN.mjs → action-runtime-DUSkWTiZ.mjs} +2 -2
  2. package/dist/.setup/{agent-tools-login-B7VEvJO7.mjs → agent-tools-login-CB7OQbli.mjs} +5 -15
  3. package/dist/.setup/{approval-handler.runtime-CKposl6w.mjs → approval-handler.runtime-BEaAKSoU.mjs} +3 -3
  4. package/dist/.setup/{approval-reactions-CD6CDF9k.mjs → approval-reactions-CWkZ_ham.mjs} +7 -16
  5. package/dist/.setup/audio-preflight.runtime-Dg8oZgre.mjs +2 -0
  6. package/dist/.setup/{auth-store-D2rN-hP5.mjs → auth-store-DOBi5BPe.mjs} +10 -11
  7. package/dist/.setup/{channel-DNgKHMCz.mjs → channel-DcHw3Up2.mjs} +136 -135
  8. package/dist/.setup/{channel-react-action-BaBV9X6M.mjs → channel-react-action-C5E8_iDk.mjs} +3 -3
  9. package/dist/.setup/{channel.runtime-BniF8Swm.mjs → channel.runtime-DTj-wkEP.mjs} +5 -11
  10. package/dist/.setup/channel.setup-BJWEyQlF.mjs +5 -0
  11. package/dist/.setup/{connection-controller-COkcq48K.mjs → connection-controller-CejM7bhn.mjs} +50 -84
  12. package/dist/.setup/{directory-config-RYQomHyB.mjs → directory-config-DPLTUAqy.mjs} +22 -29
  13. package/dist/.setup/{group-session-key-BV8Le9r8.mjs → group-session-key-BbTPosdy.mjs} +12 -18
  14. package/dist/.setup/{login-CV_4V021.mjs → login-DUx5JYuW.mjs} +3 -3
  15. package/dist/.setup/{login-qr-DFhGc5yH.mjs → login-qr-BAWbPonj.mjs} +24 -45
  16. package/dist/.setup/{monitor-B5DS4PDV.mjs → monitor-CmXEQad9.mjs} +218 -367
  17. package/dist/.setup/{normalize-target-BGra1ZnM.mjs → normalize-target-D67Kc3g6.mjs} +5 -8
  18. package/dist/.setup/{question-reactions-LMeijbaq.mjs → question-reactions-DywNaX8m.mjs} +3 -10
  19. package/dist/.setup/reaction-target-CSPO7gtu.mjs +11 -0
  20. package/dist/.setup/{resolve-outbound-target-CzyNKmrl.mjs → resolve-outbound-target-qikGL4r0.mjs} +3 -4
  21. package/dist/.setup/{send-CGUsUdoX.mjs → send-CLBfAzd6.mjs} +34 -42
  22. package/dist/.setup/{send-api-B03VDwZ1.mjs → send-api-COzRvqXx.mjs} +28 -60
  23. package/dist/.setup/{setup-finalize-GtBmrO8p.mjs → setup-finalize-DSiP_-wa.mjs} +53 -69
  24. package/dist/.setup/setup-plugin-api-8WdNCjRW.mjs +3 -0
  25. package/dist/.setup/{setup-surface-BuA39k6K.mjs → setup-surface-C_flQyHy.mjs} +2 -2
  26. package/dist/.setup/{shared-CP_zs2U7.mjs → shared-SqcOkt51.mjs} +4 -4
  27. package/dist/.setup/{socket-close-DU7eerAa.mjs → socket-close-C9OU9mVN.mjs} +67 -86
  28. package/dist/.setup/{targets-runtime-Dls-Xh4F.mjs → targets-runtime-D5ryyPxh.mjs} +16 -25
  29. package/dist/action-runtime-api.js +1 -1
  30. package/dist/action-runtime.runtime.js +1 -1
  31. package/dist/agent-tools-api.js +4 -8
  32. package/dist/api.js +13 -15
  33. package/dist/channel-plugin-api.js +1 -1
  34. package/dist/contract-api.js +1 -1
  35. package/dist/directory-contract-api.js +1 -1
  36. package/dist/doctor-contract-api.js +12 -32
  37. package/dist/light-runtime-api.js +2 -2
  38. package/dist/login-qr-runtime.js +2 -4
  39. package/dist/runtime-api.js +8 -8
  40. package/dist/setup-entry.js +1 -1
  41. package/dist/setup-plugin-api.js +1 -1
  42. package/node_modules/audio-decode/node_modules/@audio/decode/package.json +7 -7
  43. package/node_modules/audio-decode/node_modules/@audio/decode/readme.md +2 -1
  44. package/node_modules/audio-decode/node_modules/@audio/decode-aac/README.md +10 -0
  45. package/node_modules/audio-decode/node_modules/@audio/decode-aac/decode-aac.d.ts +22 -0
  46. package/node_modules/audio-decode/node_modules/@audio/decode-aac/decode-aac.js +142 -7
  47. package/node_modules/audio-decode/node_modules/@audio/decode-aac/package.json +1 -1
  48. package/node_modules/audio-decode/node_modules/@audio/decode-caf/README.md +2 -0
  49. package/node_modules/audio-decode/node_modules/@audio/decode-caf/decode-caf.js +4 -1
  50. package/node_modules/audio-decode/node_modules/@audio/decode-caf/package.json +1 -1
  51. package/node_modules/audio-decode/node_modules/@audio/decode-flac/decode-flac.js +161 -29
  52. package/node_modules/audio-decode/node_modules/@audio/decode-flac/package.json +1 -1
  53. package/node_modules/audio-decode/node_modules/@audio/decode-mp4/README.md +1 -1
  54. package/node_modules/audio-decode/node_modules/@audio/decode-mp4/decode-mp4.js +127 -28
  55. package/node_modules/audio-decode/node_modules/@audio/decode-mp4/package.json +3 -3
  56. package/node_modules/audio-decode/node_modules/@audio/decode-opus/package.json +1 -1
  57. package/node_modules/audio-decode/node_modules/@audio/decode-opus/src/decode-opus.js +2 -2
  58. package/node_modules/audio-decode/node_modules/@audio/decode-qoa/README.md +1 -1
  59. package/node_modules/audio-decode/node_modules/@audio/decode-qoa/decode-qoa.js +79 -227
  60. package/node_modules/audio-decode/node_modules/@audio/decode-qoa/package.json +1 -1
  61. package/node_modules/audio-decode/node_modules/@audio/decode-vorbis/decode-vorbis.js +51 -10
  62. package/node_modules/audio-decode/node_modules/@audio/decode-vorbis/package.json +1 -1
  63. package/node_modules/audio-decode/node_modules/@audio/decode-wav/decode-wav.js +40 -18
  64. package/node_modules/audio-decode/node_modules/@audio/decode-wav/package.json +1 -1
  65. package/node_modules/audio-decode/node_modules/@audio/decode-wma/LICENSE.ffmpeg +502 -0
  66. package/node_modules/audio-decode/node_modules/@audio/decode-wma/README.md +5 -5
  67. package/node_modules/audio-decode/node_modules/@audio/decode-wma/decode-wma.js +15 -3
  68. package/node_modules/audio-decode/node_modules/@audio/decode-wma/package.json +5 -4
  69. package/node_modules/audio-decode/node_modules/@audio/decode-wma/src/wma.wasm.js +0 -0
  70. package/node_modules/audio-decode/node_modules/audio-type/audio-type.js +13 -0
  71. package/node_modules/audio-decode/node_modules/audio-type/package.json +1 -1
  72. package/node_modules/audio-decode/node_modules/audio-type/readme.md +1 -1
  73. package/node_modules/baileys/lib/Utils/messages-media.js +7 -11
  74. package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/diagnostics-channel-react-native.d.ts.map +1 -0
  75. package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/diagnostics-channel-react-native.js.map +1 -0
  76. package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/diagnostics-channel.d.ts +5 -0
  77. package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/diagnostics-channel.js +7 -0
  78. package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/index.d.ts +1400 -0
  79. package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/index.d.ts.map +1 -0
  80. package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/index.js +1733 -0
  81. package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/index.js.map +1 -0
  82. package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/perf.d.ts +12 -0
  83. package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/perf.d.ts.map +1 -0
  84. package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/perf.js +10 -0
  85. package/node_modules/baileys/node_modules/lru-cache/dist/commonjs/react-native/perf.js.map +1 -0
  86. package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/diagnostics-channel-react-native.d.ts.map +1 -0
  87. package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/diagnostics-channel-react-native.js.map +1 -0
  88. package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/diagnostics-channel.d.ts +5 -0
  89. package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/diagnostics-channel.js +4 -0
  90. package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/index.d.ts +1400 -0
  91. package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/index.d.ts.map +1 -0
  92. package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/index.js +1729 -0
  93. package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/index.js.map +1 -0
  94. package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/perf.d.ts +12 -0
  95. package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/perf.d.ts.map +1 -0
  96. package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/perf.js +7 -0
  97. package/node_modules/baileys/node_modules/lru-cache/dist/esm/react-native/perf.js.map +1 -0
  98. package/node_modules/baileys/node_modules/lru-cache/package.json +27 -1
  99. package/node_modules/baileys/node_modules/music-metadata/README.md +35 -32
  100. package/node_modules/baileys/node_modules/music-metadata/lib/ParserFactory.d.ts +1 -1
  101. package/node_modules/baileys/node_modules/music-metadata/lib/ParserFactory.js +17 -13
  102. package/node_modules/baileys/node_modules/music-metadata/lib/aiff/AiffParser.js +19 -12
  103. package/node_modules/baileys/node_modules/music-metadata/lib/aiff/AiffToken.d.ts +1 -1
  104. package/node_modules/baileys/node_modules/music-metadata/lib/aiff/AiffToken.js +2 -1
  105. package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2Parser.d.ts +4 -3
  106. package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2Parser.js +59 -16
  107. package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2TagMapper.js +1 -0
  108. package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2Token.d.ts +1 -1
  109. package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2Token.js +1 -1
  110. package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfGuid.js +56 -50
  111. package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfObject.d.ts +1 -1
  112. package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfObject.js +3 -2
  113. package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfParser.js +15 -7
  114. package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfTagMapper.d.ts +3 -2
  115. package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfTagMapper.js +21 -4
  116. package/node_modules/baileys/node_modules/music-metadata/lib/common/CaseInsensitiveTagMap.d.ts +1 -1
  117. package/node_modules/baileys/node_modules/music-metadata/lib/common/CombinedTagMapper.d.ts +2 -2
  118. package/node_modules/baileys/node_modules/music-metadata/lib/common/CombinedTagMapper.js +6 -6
  119. package/node_modules/baileys/node_modules/music-metadata/lib/common/FourCC.js +3 -2
  120. package/node_modules/baileys/node_modules/music-metadata/lib/common/GenericTagMapper.d.ts +1 -1
  121. package/node_modules/baileys/node_modules/music-metadata/lib/common/GenericTagTypes.js +1 -1
  122. package/node_modules/baileys/node_modules/music-metadata/lib/common/MetadataCollector.d.ts +3 -1
  123. package/node_modules/baileys/node_modules/music-metadata/lib/common/MetadataCollector.js +28 -9
  124. package/node_modules/baileys/node_modules/music-metadata/lib/common/Util.js +25 -17
  125. package/node_modules/baileys/node_modules/music-metadata/lib/core.d.ts +4 -4
  126. package/node_modules/baileys/node_modules/music-metadata/lib/core.js +18 -11
  127. package/node_modules/baileys/node_modules/music-metadata/lib/dsdiff/DsdiffParser.js +29 -16
  128. package/node_modules/baileys/node_modules/music-metadata/lib/dsf/DsfChunk.d.ts +1 -1
  129. package/node_modules/baileys/node_modules/music-metadata/lib/dsf/DsfParser.js +3 -5
  130. package/node_modules/baileys/node_modules/music-metadata/lib/ebml/EbmlIterator.d.ts +1 -1
  131. package/node_modules/baileys/node_modules/music-metadata/lib/ebml/EbmlIterator.js +35 -6
  132. package/node_modules/baileys/node_modules/music-metadata/lib/ebml/types.d.ts +1 -1
  133. package/node_modules/baileys/node_modules/music-metadata/lib/ebml/types.js +1 -1
  134. package/node_modules/baileys/node_modules/music-metadata/lib/flac/FlacParser.d.ts +1 -1
  135. package/node_modules/baileys/node_modules/music-metadata/lib/flac/FlacParser.js +6 -5
  136. package/node_modules/baileys/node_modules/music-metadata/lib/flac/FlacToken.d.ts +1 -1
  137. package/node_modules/baileys/node_modules/music-metadata/lib/flac/FlacToken.js +1 -1
  138. package/node_modules/baileys/node_modules/music-metadata/lib/id3v1/ID3v1Parser.d.ts +1 -1
  139. package/node_modules/baileys/node_modules/music-metadata/lib/id3v1/ID3v1Parser.js +212 -42
  140. package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/AbstractID3Parser.js +5 -5
  141. package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/FrameHeader.d.ts +1 -1
  142. package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/FrameHeader.js +8 -5
  143. package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/FrameParser.d.ts +2 -1
  144. package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/FrameParser.js +54 -23
  145. package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v22TagMapper.d.ts +1 -1
  146. package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v22TagMapper.js +1 -1
  147. package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v24TagMapper.js +3 -3
  148. package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2ChapterToken.js +2 -2
  149. package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2Parser.d.ts +1 -1
  150. package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2Parser.js +32 -16
  151. package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2Token.d.ts +2 -2
  152. package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2Token.js +2 -3
  153. package/node_modules/baileys/node_modules/music-metadata/lib/index.js +6 -3
  154. package/node_modules/baileys/node_modules/music-metadata/lib/lrc/LyricsParser.js +3 -5
  155. package/node_modules/baileys/node_modules/music-metadata/lib/matroska/MatroskaDtd.js +7 -3
  156. package/node_modules/baileys/node_modules/music-metadata/lib/matroska/MatroskaParser.js +22 -11
  157. package/node_modules/baileys/node_modules/music-metadata/lib/matroska/types.d.ts +2 -2
  158. package/node_modules/baileys/node_modules/music-metadata/lib/mp4/Atom.d.ts +4 -3
  159. package/node_modules/baileys/node_modules/music-metadata/lib/mp4/Atom.js +44 -11
  160. package/node_modules/baileys/node_modules/music-metadata/lib/mp4/AtomToken.d.ts +1 -1
  161. package/node_modules/baileys/node_modules/music-metadata/lib/mp4/AtomToken.js +30 -8
  162. package/node_modules/baileys/node_modules/music-metadata/lib/mp4/MP4Parser.d.ts +2 -0
  163. package/node_modules/baileys/node_modules/music-metadata/lib/mp4/MP4Parser.js +79 -54
  164. package/node_modules/baileys/node_modules/music-metadata/lib/mp4/MP4TagMapper.d.ts +2 -2
  165. package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/MpegLoader.js +1 -1
  166. package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/MpegParser.js +41 -19
  167. package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/ReplayGainDataFormat.d.ts +2 -2
  168. package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/ReplayGainDataFormat.js +1 -1
  169. package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/XingTag.d.ts +1 -1
  170. package/node_modules/baileys/node_modules/music-metadata/lib/musepack/MusepackParser.js +2 -2
  171. package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv7/BitReader.js +1 -1
  172. package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv7/MpcSv7Parser.js +4 -3
  173. package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv7/StreamVersion7.js +3 -3
  174. package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv8/MpcSv8Parser.js +7 -5
  175. package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv8/StreamVersion8.js +2 -2
  176. package/node_modules/baileys/node_modules/music-metadata/lib/ogg/OggParser.js +23 -13
  177. package/node_modules/baileys/node_modules/music-metadata/lib/ogg/OggToken.d.ts +2 -0
  178. package/node_modules/baileys/node_modules/music-metadata/lib/ogg/OggToken.js +1 -1
  179. package/node_modules/baileys/node_modules/music-metadata/lib/ogg/flac/FlacStream.d.ts +2 -2
  180. package/node_modules/baileys/node_modules/music-metadata/lib/ogg/flac/FlacStream.js +2 -2
  181. package/node_modules/baileys/node_modules/music-metadata/lib/ogg/opus/OpusStream.d.ts +2 -2
  182. package/node_modules/baileys/node_modules/music-metadata/lib/ogg/opus/OpusStream.js +8 -4
  183. package/node_modules/baileys/node_modules/music-metadata/lib/ogg/speex/SpeexStream.d.ts +2 -2
  184. package/node_modules/baileys/node_modules/music-metadata/lib/ogg/speex/SpeexStream.js +2 -1
  185. package/node_modules/baileys/node_modules/music-metadata/lib/ogg/theora/TheoraStream.d.ts +2 -2
  186. package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/Vorbis.d.ts +1 -1
  187. package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/VorbisDecoder.js +1 -1
  188. package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/VorbisStream.d.ts +4 -3
  189. package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/VorbisStream.js +16 -9
  190. package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/VorbisTagMapper.js +4 -0
  191. package/node_modules/baileys/node_modules/music-metadata/lib/riff/RiffChunk.d.ts +3 -1
  192. package/node_modules/baileys/node_modules/music-metadata/lib/riff/RiffChunk.js +3 -2
  193. package/node_modules/baileys/node_modules/music-metadata/lib/riff/RiffInfoTagMap.d.ts +1 -1
  194. package/node_modules/baileys/node_modules/music-metadata/lib/type.d.ts +3 -3
  195. package/node_modules/baileys/node_modules/music-metadata/lib/type.js +1 -1
  196. package/node_modules/baileys/node_modules/music-metadata/lib/wav/WaveChunk.d.ts +1 -1
  197. package/node_modules/baileys/node_modules/music-metadata/lib/wav/WaveChunk.js +3 -2
  198. package/node_modules/baileys/node_modules/music-metadata/lib/wav/WaveParser.d.ts +6 -2
  199. package/node_modules/baileys/node_modules/music-metadata/lib/wav/WaveParser.js +75 -22
  200. package/node_modules/baileys/node_modules/music-metadata/lib/wavpack/WavPackParser.js +22 -13
  201. package/node_modules/baileys/node_modules/music-metadata/lib/wavpack/WavPackToken.js +3 -2
  202. package/node_modules/baileys/node_modules/music-metadata/package.json +3 -2
  203. package/node_modules/baileys/node_modules/uint8array-extras/index.d.ts +7 -7
  204. package/node_modules/baileys/node_modules/uint8array-extras/index.js +27 -13
  205. package/node_modules/baileys/node_modules/uint8array-extras/package.json +6 -6
  206. package/node_modules/baileys/node_modules/uint8array-extras/readme.md +7 -7
  207. package/node_modules/baileys/node_modules/ws/lib/websocket.js +17 -3
  208. package/node_modules/baileys/node_modules/ws/package.json +1 -1
  209. package/package.json +4 -4
  210. package/dist/.setup/audio-preflight.runtime-C_glQhZY.mjs +0 -7
  211. package/dist/.setup/channel.setup-CsS_NAKQ.mjs +0 -5
  212. 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 headerLength = 10;
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](headerLength, readOffset);
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] = headerLength + dataLength;
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: samples3, ...codecUpdateFields } = header2;
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, samples3) {
1013
- super(header2, frame2, samples3);
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: samples3,
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, samples3) {
1197
- super(header2, frame2, samples3);
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: samples3,
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 headerLength = headerStore.get(header2)[length];
1642
- const totalLength = headerLength + frameLengthValue;
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](headerLength, totalLength);
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, samples3) {
1674
- super(header2, data3, samples3);
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 samples3 = header2[frameSize] * header2[frameCount] / 1e3 * header2[sampleRate];
1862
+ let samples2 = header2[frameSize] * header2[frameCount] / 1e3 * header2[sampleRate];
1863
1863
  if (this._preSkipRemaining > 0) {
1864
- this._preSkipRemaining -= samples3;
1865
- samples3 = this._preSkipRemaining < 0 ? -this._preSkipRemaining : 0;
1864
+ this._preSkipRemaining -= samples2;
1865
+ samples2 = this._preSkipRemaining < 0 ? -this._preSkipRemaining : 0;
1866
1866
  }
1867
- return new OpusFrame(segment, header2, samples3);
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, samples3) {
1886
- super(header2, data3, samples3);
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](oggPages) {
2884
- const frames = oggPages.map((page2) => page2[codecFrames2].map((f) => f[data2])).flat();
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 = oggPages[oggPages.length - 1];
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
- return new codec_parser_default(ogg ? "audio/ogg" : "audio/flac", {
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[samples2] || 0), 0);
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;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@audio/decode-flac",
3
- "version": "1.3.3",
3
+ "version": "1.3.5",
4
4
  "description": "Decode FLAC audio with libFLAC WASM",
5
5
  "type": "module",
6
6
  "main": "decode-flac.js",
@@ -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`) is not supported. 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.
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
- function findBox(buf, name) {
148
- let found = false
149
- walk(buf, 0, buf.length, type => { if (type === name) found = true })
150
- return found
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
- if (!track.sizes || !track.stco?.length) throw Error('Audio track has no sample tables')
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 frames(import('@audio/decode-mp3'))
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 frames(import('@audio/decode-mp3'))
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 dec = await (await import('@audio/decode-aac')).decoder(opts)
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
- async function opus(dOps) {
345
- let channels = dOps[1]
346
- let opts = { channels, sampleRate: 48000, preSkip: r16(dOps, 2), outputGain: (r16(dOps, 8) << 16) >> 16 }
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
- opts.channelMappingTable = Array.from(dOps.subarray(13, 13 + channels))
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 (await import('@audio/decode-opus/core')).createOpusDecoder()
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.1.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.5.0",
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.0",
36
+ "@audio/decode-opus": "^1.3.3",
37
37
  "@audio/decode-eac3": "^1.0.0"
38
38
  },
39
39
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@audio/decode-opus",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "description": "Decode Ogg Opus audio with local libopus WASM",
5
5
  "type": "module",
6
6
  "main": "decode-opus.js",