@openclaw/whatsapp 2026.5.28 → 2026.5.31-beta.1
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/{access-control-Z0fYaWrx.js → access-control-C53zKYSN.js} +1 -1
- package/dist/{accounts-BMGM1RtF.js → accounts-DgViSyJx.js} +1 -0
- package/dist/{action-runtime-BdhkGtaP.js → action-runtime-Cyp5GNIT.js} +2 -2
- package/dist/action-runtime-api.js +1 -1
- package/dist/action-runtime.runtime.js +1 -1
- package/dist/api.js +9 -9
- package/dist/{approval-handler.runtime-C25wPeBf.js → approval-handler.runtime-BVmOu6x1.js} +1 -2
- package/dist/{auth-store-BrKb0mwT.js → auth-store-CZ22aNcV.js} +4 -2
- package/dist/{channel-D3y4A5Dd.js → channel-DA2BAIo5.js} +17 -64
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel-react-action-Cd2qkLqp.js → channel-react-action-zvbaCnGe.js} +3 -3
- package/dist/{channel.runtime-C228XUjs.js → channel.runtime-Q1LZDB5s.js} +4 -4
- package/dist/{channel.setup-BJQyTUUP.js → channel.setup-DHXOo4h5.js} +2 -3
- package/dist/{config-schema-CsNDlDpL.js → config-schema-CROZuhT-.js} +16 -0
- package/dist/{connection-controller-mpPGmqGq.js → connection-controller-Bnm4INld.js} +2 -2
- package/dist/contract-api.js +1 -1
- package/dist/light-runtime-api.js +1 -1
- package/dist/{login-CE4UYnyO.js → login-2fuBM7Je.js} +4 -4
- package/dist/{login-qr-LBvhEes5.js → login-qr-B1o7GFy8.js} +10 -6
- package/dist/login-qr-runtime.js +1 -1
- package/dist/{monitor-Ccph7Y8M.js → monitor-BVRq04Dt.js} +36 -18
- package/dist/runtime-api.js +7 -7
- package/dist/{send-C4LG-Cl6.js → send-DSlVXKL_.js} +53 -41
- package/dist/{send-api-C66vkRl9.js → send-api-Bjn-h80j.js} +3 -2
- package/dist/{session-D8UW2Vbn.js → session-DyGWNClj.js} +1 -1
- package/dist/{setup-core-DpfT4K-2.js → setup-core-OvPMaAsx.js} +4 -4
- package/dist/{setup-finalize-CFnxX7la.js → setup-finalize-Dk23pfKc.js} +3 -3
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-DRsmp0ZS.js → setup-surface-F-jVrH8u.js} +3 -3
- package/node_modules/@audio/decode-aac/LICENSE +9 -0
- package/node_modules/@audio/decode-aac/README.md +60 -0
- package/node_modules/@audio/decode-aac/decode-aac.d.ts +16 -0
- package/node_modules/@audio/decode-aac/decode-aac.js +391 -0
- package/node_modules/@audio/decode-aac/package.json +47 -0
- package/node_modules/@audio/decode-aac/src/aac.wasm.cjs +0 -0
- package/node_modules/@audio/decode-aiff/LICENSE +21 -0
- package/node_modules/@audio/decode-aiff/README.md +53 -0
- package/node_modules/@audio/decode-aiff/decode-aiff.d.ts +16 -0
- package/node_modules/@audio/decode-aiff/decode-aiff.js +583 -0
- package/node_modules/@audio/decode-aiff/package.json +42 -0
- package/node_modules/@audio/decode-amr/LICENSE +191 -0
- package/node_modules/@audio/decode-amr/README.md +65 -0
- package/node_modules/@audio/decode-amr/decode-amr.d.ts +16 -0
- package/node_modules/@audio/decode-amr/decode-amr.js +159 -0
- package/node_modules/@audio/decode-amr/package.json +48 -0
- package/node_modules/@audio/decode-amr/src/amr.wasm.cjs +0 -0
- package/node_modules/@audio/decode-caf/LICENSE +21 -0
- package/node_modules/@audio/decode-caf/README.md +55 -0
- package/node_modules/@audio/decode-caf/decode-caf.d.ts +16 -0
- package/node_modules/@audio/decode-caf/decode-caf.js +190 -0
- package/node_modules/@audio/decode-caf/package.json +43 -0
- package/node_modules/{audio-buffer → @audio/decode-flac}/LICENSE +5 -2
- package/node_modules/@audio/decode-flac/README.md +23 -0
- package/node_modules/@audio/decode-flac/decode-flac.d.ts +16 -0
- package/node_modules/@audio/decode-flac/decode-flac.js +2994 -0
- package/node_modules/@audio/decode-flac/meta.js +115 -0
- package/node_modules/@audio/decode-flac/package.json +49 -0
- package/node_modules/@audio/decode-mp3/LICENSE +25 -0
- package/node_modules/@audio/decode-mp3/README.md +23 -0
- package/node_modules/@audio/decode-mp3/decode-mp3.d.ts +16 -0
- package/node_modules/@audio/decode-mp3/decode-mp3.js +868 -0
- package/node_modules/@audio/decode-mp3/meta.js +143 -0
- package/node_modules/@audio/decode-mp3/package.json +50 -0
- package/node_modules/@audio/decode-opus/LICENSE +25 -0
- package/node_modules/@audio/decode-opus/README.md +23 -0
- package/node_modules/@audio/decode-opus/decode-opus.d.ts +16 -0
- package/node_modules/@audio/decode-opus/decode-opus.js +3179 -0
- package/node_modules/@audio/decode-opus/package.json +47 -0
- package/node_modules/@audio/decode-qoa/LICENSE +25 -0
- package/node_modules/@audio/decode-qoa/README.md +21 -0
- package/node_modules/@audio/decode-qoa/decode-qoa.d.ts +16 -0
- package/node_modules/@audio/decode-qoa/decode-qoa.js +278 -0
- package/node_modules/@audio/decode-qoa/package.json +46 -0
- package/node_modules/@audio/decode-vorbis/LICENSE +25 -0
- package/node_modules/@audio/decode-vorbis/README.md +23 -0
- package/node_modules/@audio/decode-vorbis/decode-vorbis.d.ts +16 -0
- package/node_modules/@audio/decode-vorbis/decode-vorbis.js +2984 -0
- package/node_modules/@audio/decode-vorbis/package.json +47 -0
- package/node_modules/@audio/decode-wav/decode-wav.js +104 -0
- package/node_modules/@audio/decode-wav/meta.js +114 -0
- package/node_modules/@audio/decode-wav/package.json +27 -0
- package/node_modules/@audio/decode-webm/LICENSE +21 -0
- package/node_modules/@audio/decode-webm/README.md +57 -0
- package/node_modules/@audio/decode-webm/decode-webm.d.ts +16 -0
- package/node_modules/@audio/decode-webm/decode-webm.js +3964 -0
- package/node_modules/@audio/decode-webm/package.json +51 -0
- package/node_modules/@audio/decode-wma/LICENSE +12 -0
- package/node_modules/@audio/decode-wma/README.md +76 -0
- package/node_modules/@audio/decode-wma/decode-wma.d.ts +33 -0
- package/node_modules/@audio/decode-wma/decode-wma.js +525 -0
- package/node_modules/@audio/decode-wma/package.json +47 -0
- package/node_modules/@audio/decode-wma/src/wma.wasm.cjs +0 -0
- package/node_modules/audio-decode/.claude/settings.json +204 -0
- package/node_modules/audio-decode/.github/workflows/test.js.yml +11 -20
- package/node_modules/audio-decode/.gitmodules +9 -0
- package/node_modules/audio-decode/audio-decode.d.ts +48 -10
- package/node_modules/audio-decode/audio-decode.js +193 -77
- package/node_modules/audio-decode/meta.js +11 -0
- package/node_modules/audio-decode/package.json +49 -21
- package/node_modules/audio-decode/readme.md +129 -29
- package/node_modules/audio-decode/stream.d.ts +15 -0
- package/node_modules/audio-decode/stream.js +1 -0
- package/node_modules/audio-decode/test.html +29 -10
- package/node_modules/lru-cache/dist/commonjs/browser/index.d.ts +2 -2
- package/node_modules/lru-cache/dist/commonjs/browser/index.d.ts.map +1 -1
- package/node_modules/lru-cache/dist/commonjs/browser/index.js.map +1 -1
- package/node_modules/lru-cache/dist/commonjs/browser/index.min.js.map +1 -1
- package/node_modules/lru-cache/dist/commonjs/index.d.ts +2 -2
- package/node_modules/lru-cache/dist/commonjs/index.d.ts.map +1 -1
- package/node_modules/lru-cache/dist/commonjs/index.js.map +1 -1
- package/node_modules/lru-cache/dist/commonjs/index.min.js.map +1 -1
- package/node_modules/lru-cache/dist/commonjs/node/index.d.ts +2 -2
- package/node_modules/lru-cache/dist/commonjs/node/index.d.ts.map +1 -1
- package/node_modules/lru-cache/dist/commonjs/node/index.js.map +1 -1
- package/node_modules/lru-cache/dist/commonjs/node/index.min.js.map +1 -1
- package/node_modules/lru-cache/dist/esm/browser/index.d.ts +2 -2
- package/node_modules/lru-cache/dist/esm/browser/index.d.ts.map +1 -1
- package/node_modules/lru-cache/dist/esm/browser/index.js.map +1 -1
- package/node_modules/lru-cache/dist/esm/browser/index.min.js.map +1 -1
- package/node_modules/lru-cache/dist/esm/index.d.ts +2 -2
- package/node_modules/lru-cache/dist/esm/index.d.ts.map +1 -1
- package/node_modules/lru-cache/dist/esm/index.js.map +1 -1
- package/node_modules/lru-cache/dist/esm/index.min.js.map +1 -1
- package/node_modules/lru-cache/dist/esm/node/index.d.ts +2 -2
- package/node_modules/lru-cache/dist/esm/node/index.d.ts.map +1 -1
- package/node_modules/lru-cache/dist/esm/node/index.js.map +1 -1
- package/node_modules/lru-cache/dist/esm/node/index.min.js.map +1 -1
- package/node_modules/lru-cache/package.json +1 -1
- package/node_modules/typebox/build/type/script/mapping.d.mts +5 -2
- package/node_modules/typebox/build/type/script/mapping.mjs +15 -8
- package/node_modules/typebox/build/type/script/parser.d.mts +3 -1
- package/node_modules/typebox/build/type/script/parser.mjs +2 -1
- package/node_modules/typebox/package.json +29 -29
- package/npm-shrinkwrap.json +156 -39
- package/openclaw.plugin.json +76 -0
- package/package.json +6 -6
- package/node_modules/audio-buffer/.eslintrc.json +0 -44
- package/node_modules/audio-buffer/.github/workflows/node.js.yml +0 -31
- package/node_modules/audio-buffer/.travis.yml +0 -7
- package/node_modules/audio-buffer/index.js +0 -76
- package/node_modules/audio-buffer/package.json +0 -37
- package/node_modules/audio-buffer/readme.md +0 -56
- package/node_modules/audio-decode/.eslintrc.json +0 -43
- package/node_modules/audio-decode/.travis.yml +0 -13
- package/node_modules/audio-decode/tea.yaml +0 -6
- package/node_modules/audio-decode/test-case.js +0 -11
- package/node_modules/audio-decode/test.js +0 -107
- package/node_modules/node-wav/README.md +0 -35
- package/node_modules/node-wav/file.wav +0 -0
- package/node_modules/node-wav/index.js +0 -291
- package/node_modules/node-wav/package.json +0 -29
- package/node_modules/node-wav/tests/file1.wav +0 -0
- package/node_modules/node-wav/tests/test.js +0 -66
- package/node_modules/node-wav/x.js +0 -12
- package/node_modules/node-wav/x.json +0 -86702
- package/node_modules/node-wav/x.js~ +0 -13
|
@@ -1,92 +1,208 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* @module
|
|
2
|
+
* Audio decoder: whole-file, streaming, chunked
|
|
3
|
+
* @module audio-decode
|
|
4
|
+
*
|
|
5
|
+
* let { channelData, sampleRate } = await decode(buf)
|
|
6
|
+
*
|
|
7
|
+
* for await (let pcm of decode.mp3(source)) { ... }
|
|
8
|
+
*
|
|
9
|
+
* let dec = await decode.mp3()
|
|
10
|
+
* let { channelData, sampleRate } = await dec(chunk)
|
|
11
|
+
* await dec() // close
|
|
4
12
|
*/
|
|
5
13
|
|
|
6
14
|
import getType from 'audio-type';
|
|
7
|
-
import AudioBufferShim from 'audio-buffer';
|
|
8
15
|
|
|
9
|
-
const
|
|
16
|
+
const EMPTY = Object.freeze({ channelData: Object.freeze([]), sampleRate: 0 })
|
|
10
17
|
|
|
11
18
|
/**
|
|
12
|
-
* Decode
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* @returns {Promise<AudioBuffer>} A promise that resolves to the decoded audio buffer.
|
|
16
|
-
* @throws {Error} Throws an error if the decode target is invalid or if the audio format is not supported.
|
|
19
|
+
* Decode audio.
|
|
20
|
+
* 1 arg: whole-file — auto-detects format, returns Promise<AudioData>
|
|
21
|
+
* 2 args: chunked — streams from ReadableStream/AsyncIterable, returns AsyncGenerator<AudioData>
|
|
17
22
|
*/
|
|
18
|
-
export default
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (!
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
23
|
+
export default function decode(src, format) {
|
|
24
|
+
if (format) return decodeChunked(src, format)
|
|
25
|
+
return decodeWhole(src)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function decodeWhole(src) {
|
|
29
|
+
if (!src || typeof src === 'string' || !(src.buffer || src.byteLength || src.length))
|
|
30
|
+
throw TypeError('Expected ArrayBuffer or Uint8Array')
|
|
31
|
+
let buf = new Uint8Array(src)
|
|
32
|
+
|
|
33
|
+
let type = getType(buf)
|
|
34
|
+
if (!type) throw Error('Unknown audio format')
|
|
35
|
+
if (!decode[type]) throw Error('No decoder for ' + type)
|
|
36
|
+
|
|
37
|
+
let dec = await decode[type]()
|
|
38
|
+
try {
|
|
39
|
+
let result = await dec(buf)
|
|
40
|
+
let flushed = await dec()
|
|
41
|
+
return merge(result, flushed)
|
|
42
|
+
} catch (e) { dec.free(); throw e }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Decode a ReadableStream or async iterable of encoded audio chunks.
|
|
47
|
+
* @param {ReadableStream|AsyncIterable} source
|
|
48
|
+
* @param {string} format - codec name
|
|
49
|
+
* @returns {AsyncGenerator<{channelData: Float32Array[], sampleRate: number}>}
|
|
50
|
+
*/
|
|
51
|
+
export async function* decodeChunked(source, format) {
|
|
52
|
+
if (!decode[format]) throw Error('No decoder for ' + format)
|
|
53
|
+
let dec = await decode[format]()
|
|
54
|
+
try {
|
|
55
|
+
if (source.getReader) {
|
|
56
|
+
let reader = source.getReader()
|
|
57
|
+
while (true) {
|
|
58
|
+
let { done, value } = await reader.read()
|
|
59
|
+
if (done) break
|
|
60
|
+
let result = await dec(value instanceof Uint8Array ? value : new Uint8Array(value))
|
|
61
|
+
if (result.channelData.length) yield result
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
for await (let chunk of source) {
|
|
65
|
+
let result = await dec(chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk))
|
|
66
|
+
if (result.channelData.length) yield result
|
|
67
|
+
}
|
|
63
68
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
let flushed = await dec()
|
|
70
|
+
if (flushed.channelData.length) yield flushed
|
|
71
|
+
} finally {
|
|
72
|
+
dec.free()
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// --- format registration ---
|
|
77
|
+
|
|
78
|
+
function reg(name, load) {
|
|
79
|
+
decode[name] = fmt(name, async () => {
|
|
80
|
+
let mod = await load()
|
|
81
|
+
// @audio/* packages export { decoder, default }
|
|
82
|
+
if (mod.decoder) {
|
|
83
|
+
let codec = await mod.decoder()
|
|
84
|
+
return streamDecoder(
|
|
85
|
+
chunk => codec.decode(chunk),
|
|
86
|
+
codec.flush ? () => codec.flush() : null,
|
|
87
|
+
codec.free ? () => codec.free() : null
|
|
88
|
+
)
|
|
72
89
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
90
|
+
// wasm-audio-decoders export class with .ready
|
|
91
|
+
let init = mod.default || mod
|
|
92
|
+
let codec = typeof init === 'function' ? await init() : init
|
|
93
|
+
if (codec.ready) await codec.ready
|
|
94
|
+
return streamDecoder(
|
|
95
|
+
chunk => codec.decode(chunk),
|
|
96
|
+
codec.flush ? () => codec.flush() : null,
|
|
97
|
+
codec.free ? () => codec.free() : null
|
|
98
|
+
)
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function fmt(name, init) {
|
|
103
|
+
let fn = (src) => {
|
|
104
|
+
if (!src) return init()
|
|
105
|
+
// async iterable / ReadableStream → streaming decode
|
|
106
|
+
if (src[Symbol.asyncIterator] || src.getReader) return decodeChunked(src, name)
|
|
107
|
+
// buffer → whole-file decode
|
|
108
|
+
console.warn('decode.' + name + '(data) is deprecated, use decode(data)')
|
|
109
|
+
return (async () => {
|
|
110
|
+
let dec = await init()
|
|
111
|
+
try {
|
|
112
|
+
let result = await dec(src instanceof Uint8Array ? src : new Uint8Array(src.buffer || src))
|
|
113
|
+
let flushed = await dec()
|
|
114
|
+
return merge(result, flushed)
|
|
115
|
+
} catch (e) { dec.free(); throw e }
|
|
116
|
+
})()
|
|
117
|
+
}
|
|
118
|
+
return fn
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// --- codecs ---
|
|
122
|
+
|
|
123
|
+
reg('mp3', () => import('@audio/decode-mp3'))
|
|
124
|
+
reg('flac', () => import('@audio/decode-flac'))
|
|
125
|
+
reg('opus', () => import('@audio/decode-opus'))
|
|
126
|
+
reg('oga', () => import('@audio/decode-vorbis'))
|
|
127
|
+
|
|
128
|
+
reg('m4a', () => import('@audio/decode-aac'))
|
|
129
|
+
|
|
130
|
+
reg('wav', () => import('@audio/decode-wav'))
|
|
131
|
+
reg('qoa', () => import('@audio/decode-qoa'))
|
|
132
|
+
|
|
133
|
+
reg('aac', () => import('@audio/decode-aac'))
|
|
134
|
+
reg('aiff', () => import('@audio/decode-aiff'))
|
|
135
|
+
reg('caf', () => import('@audio/decode-caf'))
|
|
136
|
+
reg('webm', () => import('@audio/decode-webm'))
|
|
137
|
+
reg('amr', () => import('@audio/decode-amr'))
|
|
138
|
+
reg('wma', () => import('@audio/decode-wma'))
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* StreamDecoder — a callable function:
|
|
142
|
+
* dec(chunk) — decode data, returns { channelData, sampleRate }
|
|
143
|
+
* dec() — end of stream: flush remaining samples + free resources
|
|
144
|
+
* dec.flush() — flush without freeing
|
|
145
|
+
* dec.free() — release resources without flushing
|
|
146
|
+
*/
|
|
147
|
+
function streamDecoder(onDecode, onFlush, onFree) {
|
|
148
|
+
let done = false
|
|
149
|
+
let fn = async (chunk) => {
|
|
150
|
+
if (chunk) {
|
|
151
|
+
if (done) throw Error('Decoder already freed')
|
|
152
|
+
try { return norm(await onDecode(chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk))) }
|
|
153
|
+
catch (e) { done = true; onFree?.(); throw e }
|
|
79
154
|
}
|
|
80
|
-
|
|
155
|
+
// null/undefined = end of stream
|
|
156
|
+
if (done) return EMPTY
|
|
157
|
+
done = true
|
|
158
|
+
try {
|
|
159
|
+
let result = onFlush ? norm(await onFlush()) : EMPTY
|
|
160
|
+
onFree?.()
|
|
161
|
+
return result
|
|
162
|
+
} catch (e) { onFree?.(); throw e }
|
|
163
|
+
}
|
|
164
|
+
fn.flush = async () => {
|
|
165
|
+
if (done) return EMPTY
|
|
166
|
+
return onFlush ? norm(await onFlush()) : EMPTY
|
|
81
167
|
}
|
|
168
|
+
fn.free = () => {
|
|
169
|
+
if (done) return
|
|
170
|
+
done = true
|
|
171
|
+
onFree?.()
|
|
172
|
+
}
|
|
173
|
+
return fn
|
|
82
174
|
}
|
|
83
175
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
176
|
+
// extract { channelData, sampleRate } from codec result
|
|
177
|
+
function norm(r) {
|
|
178
|
+
if (!r?.channelData?.length) return EMPTY
|
|
179
|
+
let { channelData, sampleRate, samplesDecoded } = r
|
|
180
|
+
if (samplesDecoded != null && samplesDecoded < channelData[0].length)
|
|
181
|
+
channelData = channelData.map(ch => ch.subarray(0, samplesDecoded))
|
|
182
|
+
if (!channelData[0]?.length) return EMPTY
|
|
183
|
+
// collapse duplicate stereo to mono (some decoders always output 2ch for mono sources)
|
|
184
|
+
if (channelData.length === 2) {
|
|
185
|
+
let a = channelData[0], b = channelData[1], same = true
|
|
186
|
+
for (let i = 0; i < a.length; i += 37) { if (a[i] !== b[i]) { same = false; break } }
|
|
187
|
+
if (same) channelData = [a]
|
|
188
|
+
}
|
|
189
|
+
return { channelData, sampleRate }
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// merge two decode results
|
|
193
|
+
function merge(a, b) {
|
|
194
|
+
if (!b?.channelData?.length) return a
|
|
195
|
+
if (!a?.channelData?.length) return b
|
|
196
|
+
let ach = a.channelData.length, bch = b.channelData.length
|
|
197
|
+
let ch = Math.max(ach, bch)
|
|
198
|
+
return {
|
|
199
|
+
channelData: Array.from({ length: ch }, (_, i) => {
|
|
200
|
+
let ac = a.channelData[i % ach], bc = b.channelData[i % bch]
|
|
201
|
+
let merged = new Float32Array(ac.length + bc.length)
|
|
202
|
+
merged.set(ac)
|
|
203
|
+
merged.set(bc, ac.length)
|
|
204
|
+
return merged
|
|
205
|
+
}),
|
|
206
|
+
sampleRate: a.sampleRate
|
|
207
|
+
}
|
|
92
208
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Meta parsers — re-export from codec packages.
|
|
3
|
+
* @module audio-decode/meta
|
|
4
|
+
*
|
|
5
|
+
* import { wav, mp3, flac } from 'audio-decode/meta'
|
|
6
|
+
* let result = wav(bytes) // { meta, markers, regions } | null
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export { parseMeta as wav } from '@audio/decode-wav/meta'
|
|
10
|
+
export { parseMeta as mp3, parseId3v2 } from '@audio/decode-mp3/meta'
|
|
11
|
+
export { parseMeta as flac } from '@audio/decode-flac/meta'
|
|
@@ -1,49 +1,77 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "audio-decode",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.10.1",
|
|
4
4
|
"description": "Decode audio data in node or browser",
|
|
5
|
-
"main": "audio-decode.js",
|
|
6
|
-
"module": "audio-decode.js",
|
|
7
|
-
"browser": "audio-decode.js",
|
|
8
5
|
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "audio-decode.js",
|
|
9
8
|
"types": "audio-decode.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"browser": "./audio-decode.js",
|
|
12
|
+
"node": "./audio-decode.js",
|
|
13
|
+
"default": "./audio-decode.js"
|
|
14
|
+
},
|
|
15
|
+
"./stream": "./stream.js",
|
|
16
|
+
"./meta": "./meta.js",
|
|
17
|
+
"./package.json": "./package.json"
|
|
18
|
+
},
|
|
19
|
+
"workspaces": [
|
|
20
|
+
"packages/*"
|
|
21
|
+
],
|
|
10
22
|
"dependencies": {
|
|
11
|
-
"@
|
|
12
|
-
"@
|
|
13
|
-
"audio-
|
|
14
|
-
"audio-
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"qoa
|
|
23
|
+
"@audio/decode-aac": "^1.0.2",
|
|
24
|
+
"@audio/decode-aiff": "^1.0.0",
|
|
25
|
+
"@audio/decode-amr": "^1.0.0",
|
|
26
|
+
"@audio/decode-caf": "^1.0.0",
|
|
27
|
+
"@audio/decode-flac": "^1.1.0",
|
|
28
|
+
"@audio/decode-mp3": "^1.1.0",
|
|
29
|
+
"@audio/decode-opus": "^1.0.0",
|
|
30
|
+
"@audio/decode-qoa": "^1.0.0",
|
|
31
|
+
"@audio/decode-vorbis": "^1.0.0",
|
|
32
|
+
"@audio/decode-wav": "^1.2.0",
|
|
33
|
+
"@audio/decode-webm": "^1.0.0",
|
|
34
|
+
"@audio/decode-wma": "^1.0.0",
|
|
35
|
+
"audio-type": "^2.4.0"
|
|
19
36
|
},
|
|
20
37
|
"devDependencies": {
|
|
21
|
-
"audio-lena": "^
|
|
38
|
+
"audio-lena": "^3.0.0",
|
|
22
39
|
"base64-arraybuffer": "^1.0.2",
|
|
23
|
-
"
|
|
40
|
+
"esbuild": "^0.28.0",
|
|
41
|
+
"playwright": "^1.58.0",
|
|
42
|
+
"tst": "^9.2.2"
|
|
24
43
|
},
|
|
25
44
|
"scripts": {
|
|
26
|
-
"test": "node test.js"
|
|
45
|
+
"test": "node test.js",
|
|
46
|
+
"test:browser": "node test.browser.js",
|
|
47
|
+
"test:all": "node test.js && node test.browser.js",
|
|
48
|
+
"publish:all": "npm publish --workspaces && npm publish"
|
|
27
49
|
},
|
|
28
50
|
"repository": {
|
|
29
51
|
"type": "git",
|
|
30
52
|
"url": "git+https://github.com/audiojs/audio-decode.git"
|
|
31
53
|
},
|
|
32
54
|
"keywords": [
|
|
33
|
-
"audiojs",
|
|
34
55
|
"audio",
|
|
35
|
-
"dsp",
|
|
36
56
|
"decode",
|
|
37
|
-
"
|
|
38
|
-
"audio decoder",
|
|
39
|
-
"web audio decoder",
|
|
57
|
+
"decoder",
|
|
40
58
|
"codec",
|
|
41
59
|
"mp3",
|
|
42
60
|
"wav",
|
|
43
61
|
"ogg",
|
|
44
62
|
"vorbis",
|
|
45
63
|
"opus",
|
|
46
|
-
"
|
|
64
|
+
"flac",
|
|
65
|
+
"aac",
|
|
66
|
+
"m4a",
|
|
67
|
+
"qoa",
|
|
68
|
+
"aiff",
|
|
69
|
+
"caf",
|
|
70
|
+
"webm",
|
|
71
|
+
"amr",
|
|
72
|
+
"wma",
|
|
73
|
+
"pcm",
|
|
74
|
+
"streaming"
|
|
47
75
|
],
|
|
48
76
|
"author": "ΔY <dfcreative@gmail.com>",
|
|
49
77
|
"license": "MIT",
|
|
@@ -1,49 +1,149 @@
|
|
|
1
|
-
# audio-decode [](https://github.com/audiojs/audio-decode/actions/workflows/test.js.yml)
|
|
1
|
+
# audio-decode [](https://github.com/audiojs/audio-decode/actions/workflows/test.js.yml)
|
|
2
2
|
|
|
3
|
-
Decode audio
|
|
3
|
+
Decode any audio format to raw samples.<br>
|
|
4
|
+
JS / WASM – no ffmpeg, no native bindings, works in both node and browser.<br>
|
|
5
|
+
Small API, minimal size, near-native performance, lazy-loading, chunked decoding.
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
[](https://npmjs.org/package/audio-decode/)
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* [x] `ogg vorbis`
|
|
10
|
-
* [x] `flac`
|
|
11
|
-
* [x] `opus`
|
|
12
|
-
* [ ] `alac`
|
|
13
|
-
* [ ] `aac`
|
|
14
|
-
* [ ] `m4a`
|
|
15
|
-
* [x] [`qoa`](https://github.com/phoboslab/qoa)
|
|
9
|
+
```js
|
|
10
|
+
import decode from 'audio-decode';
|
|
16
11
|
|
|
17
|
-
|
|
12
|
+
const { channelData, sampleRate } = await decode(anyAudioBuffer);
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
#### Supported formats
|
|
16
|
+
|
|
17
|
+
| Format | Package | Size | Engine |
|
|
18
|
+
|--------|---------|------|--------|
|
|
19
|
+
| MP3 | [@audio/decode-mp3](./packages/decode-mp3) | 92 KB | WASM |
|
|
20
|
+
| WAV | [@audio/decode-wav](./packages/decode-wav) | 4 KB | JS |
|
|
21
|
+
| OGG Vorbis | [@audio/decode-vorbis](./packages/decode-vorbis) | 164 KB | WASM |
|
|
22
|
+
| FLAC | [@audio/decode-flac](./packages/decode-flac) | 133 KB | WASM |
|
|
23
|
+
| Opus | [@audio/decode-opus](./packages/decode-opus) | 178 KB | WASM |
|
|
24
|
+
| M4A / AAC | [@audio/decode-aac](./packages/decode-aac) | 368 KB | WASM |
|
|
25
|
+
| QOA | [@audio/decode-qoa](./packages/decode-qoa) | 8 KB | JS |
|
|
26
|
+
| AIFF | [@audio/decode-aiff](./packages/decode-aiff) | 20 KB | JS |
|
|
27
|
+
| CAF | [@audio/decode-caf](./packages/decode-caf) | 7 KB | JS |
|
|
28
|
+
| WebM | [@audio/decode-webm](./packages/decode-webm) | 263 KB | WASM |
|
|
29
|
+
| AMR | [@audio/decode-amr](./packages/decode-amr) | 241 KB | WASM |
|
|
30
|
+
| WMA | [@audio/decode-wma](./packages/decode-wma) | 91 KB | WASM |
|
|
31
|
+
|
|
32
|
+
### Whole-file
|
|
33
|
+
|
|
34
|
+
Auto-detects format. Input can be _ArrayBuffer_, _Uint8Array_, or _Buffer_.
|
|
18
35
|
|
|
19
36
|
```js
|
|
20
|
-
import
|
|
21
|
-
import buffer from 'audio-lena/mp3';
|
|
37
|
+
import decode from 'audio-decode'
|
|
22
38
|
|
|
23
|
-
let
|
|
39
|
+
let { channelData, sampleRate } = await decode(buf)
|
|
24
40
|
```
|
|
25
41
|
|
|
26
|
-
|
|
42
|
+
### Chunked
|
|
27
43
|
|
|
28
|
-
|
|
44
|
+
```js
|
|
45
|
+
let dec = await decode.mp3()
|
|
46
|
+
let a = await dec(chunk1) // { channelData, sampleRate }
|
|
47
|
+
let b = await dec(chunk2)
|
|
48
|
+
await dec() // close
|
|
49
|
+
```
|
|
29
50
|
|
|
30
|
-
|
|
51
|
+
### Streaming
|
|
31
52
|
|
|
32
53
|
```js
|
|
33
|
-
import decode
|
|
54
|
+
import decode from 'audio-decode'
|
|
34
55
|
|
|
35
|
-
await
|
|
36
|
-
|
|
56
|
+
for await (let { channelData, sampleRate } of decode.mp3(response.body)) {
|
|
57
|
+
// process chunks
|
|
58
|
+
}
|
|
37
59
|
```
|
|
38
60
|
|
|
39
|
-
|
|
61
|
+
Works with `ReadableStream`, `fetch` body, Node stream, or any async iterable.
|
|
62
|
+
|
|
63
|
+
Formats: `mp3`, `flac`, `opus`, `oga`, `m4a`, `wav`, `qoa`, `aac`, `aiff`, `caf`, `webm`, `amr`, `wma`.
|
|
64
|
+
|
|
65
|
+
### Browser
|
|
66
|
+
|
|
67
|
+
Each codec is a self-contained bundle under `@audio/*` — no transitive deps, no import map bloat.
|
|
68
|
+
For selective loading in the browser (avoids bundling all codecs):
|
|
69
|
+
|
|
70
|
+
```html
|
|
71
|
+
<script type="importmap">
|
|
72
|
+
{
|
|
73
|
+
"imports": {
|
|
74
|
+
"audio-decode": "https://esm.sh/audio-decode",
|
|
75
|
+
"audio-type": "https://esm.sh/audio-type",
|
|
76
|
+
"@audio/decode-mp3": "https://esm.sh/@audio/decode-mp3",
|
|
77
|
+
"@audio/decode-wav": "https://esm.sh/@audio/decode-wav",
|
|
78
|
+
"@audio/decode-flac": "https://esm.sh/@audio/decode-flac",
|
|
79
|
+
"@audio/decode-opus": "https://esm.sh/@audio/decode-opus",
|
|
80
|
+
"@audio/decode-vorbis": "https://esm.sh/@audio/decode-vorbis",
|
|
81
|
+
"@audio/decode-aac": "https://esm.sh/@audio/decode-aac",
|
|
82
|
+
"@audio/decode-qoa": "https://esm.sh/@audio/decode-qoa",
|
|
83
|
+
"@audio/decode-aiff": "https://esm.sh/@audio/decode-aiff",
|
|
84
|
+
"@audio/decode-caf": "https://esm.sh/@audio/decode-caf",
|
|
85
|
+
"@audio/decode-webm": "https://esm.sh/@audio/decode-webm",
|
|
86
|
+
"@audio/decode-amr": "https://esm.sh/@audio/decode-amr",
|
|
87
|
+
"@audio/decode-wma": "https://esm.sh/@audio/decode-wma"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
</script>
|
|
91
|
+
<script type="module">
|
|
92
|
+
import decode from 'audio-decode'
|
|
93
|
+
let { channelData, sampleRate } = await decode(buf)
|
|
94
|
+
</script>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Only list the codecs you need — each `@audio/decode-*` package bundles all its WASM/JS deps internally.
|
|
98
|
+
|
|
99
|
+
### Metadata
|
|
40
100
|
|
|
41
|
-
|
|
42
|
-
* [Web Audio Decoders](https://developer.mozilla.org/en-US/docs/Web/API/AudioDecoder) – native decoders API, hope one day will be fixed or alternatively polyfilled.
|
|
43
|
-
* [decodeAudioData](https://github.com/eshaz/wasm-audio-decoders) – default in-browser decoding method.
|
|
44
|
-
* [ffmpeg.wasm](https://github.com/ffmpegwasm/ffmpeg.wasm) – ultimate encoding/decoding library (8.5Mb of code).
|
|
101
|
+
Read tags, pictures, markers and regions without decoding samples. Available for `wav`, `mp3`, `flac`.
|
|
45
102
|
|
|
46
|
-
|
|
103
|
+
```js
|
|
104
|
+
import { wav, mp3, flac } from 'audio-decode/meta'
|
|
105
|
+
|
|
106
|
+
let { meta, sampleRate, markers, regions } = mp3(bytes)
|
|
107
|
+
// meta: { title, artist, album, year, bpm, key, comment, pictures, raw, ... }
|
|
108
|
+
// markers: [{ sample, label }]
|
|
109
|
+
// regions: [{ sample, length, label }]
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Each codec sub-package also exposes its parser directly:
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
import { parseMeta } from '@audio/decode-wav/meta'
|
|
116
|
+
let info = parseMeta(wavBytes)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### WebWorker
|
|
120
|
+
|
|
121
|
+
Each `@audio/decode-*` package is a self-contained ESM module — import directly in a worker:
|
|
122
|
+
|
|
123
|
+
```js
|
|
124
|
+
// decode-worker.js
|
|
125
|
+
import decode from '@audio/decode-mp3'
|
|
126
|
+
|
|
127
|
+
self.onmessage = async ({ data }) => {
|
|
128
|
+
let pcm = await decode(data)
|
|
129
|
+
self.postMessage(pcm, pcm.channelData.map(ch => ch.buffer))
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// main.js
|
|
133
|
+
let worker = new Worker('./decode-worker.js', { type: 'module' })
|
|
134
|
+
worker.postMessage(mp3buf, [mp3buf])
|
|
135
|
+
worker.onmessage = ({ data }) => { /* { channelData, sampleRate } */ }
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## See also
|
|
47
139
|
|
|
48
|
-
[
|
|
140
|
+
* [audio-encode](https://github.com/audiojs/audio-encode) – encode PCM into any audio format.
|
|
141
|
+
* [audio-type](https://github.com/audiojs/audio-type) – detect audio format from buffer.
|
|
142
|
+
<!--
|
|
143
|
+
* [wasm-audio-decoders](https://github.com/eshaz/wasm-audio-decoders) – compact & fast WASM audio decoders.
|
|
144
|
+
* [AudioDecoder](https://developer.mozilla.org/en-US/docs/Web/API/AudioDecoder) – native WebCodecs decoder API.
|
|
145
|
+
* [decodeAudioData](https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/decodeAudioData) – built-in browser decoding method.
|
|
146
|
+
* [ffmpeg.wasm](https://github.com/ffmpegwasm/ffmpeg.wasm) – full encoding/decoding library.
|
|
147
|
+
-->
|
|
49
148
|
|
|
149
|
+
<p align="center"><a href="./LICENSE">MIT</a> • <a href="https://github.com/krishnized/license/">ॐ</a>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AudioData } from './audio-decode.js';
|
|
2
|
+
|
|
3
|
+
type Format = 'mp3' | 'flac' | 'opus' | 'oga' | 'm4a' | 'wav' | 'qoa' | 'aac' | 'aiff' | 'caf' | 'webm' | 'amr' | 'wma';
|
|
4
|
+
|
|
5
|
+
/** Chunked decode from stream or async iterable. */
|
|
6
|
+
declare function decodeChunked(
|
|
7
|
+
source: ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>,
|
|
8
|
+
format: Format
|
|
9
|
+
): AsyncGenerator<AudioData>;
|
|
10
|
+
|
|
11
|
+
export default decodeChunked;
|
|
12
|
+
export { decodeChunked };
|
|
13
|
+
|
|
14
|
+
export default decodeStream;
|
|
15
|
+
export { decodeStream };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { decodeChunked as default, decodeChunked } from './audio-decode.js'
|
|
@@ -1,15 +1,34 @@
|
|
|
1
|
-
<!
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<title>audio-decode tests</title>
|
|
2
3
|
<script type="importmap">
|
|
3
|
-
|
|
4
|
+
{
|
|
4
5
|
"imports": {
|
|
5
|
-
"
|
|
6
|
+
"./audio-decode.js": "./audio-decode.js",
|
|
7
|
+
"audio-lena/wav": "./node_modules/audio-lena/wav.js",
|
|
8
|
+
"audio-lena/mp3": "./node_modules/audio-lena/mp3.js",
|
|
9
|
+
"audio-lena/ogg": "./node_modules/audio-lena/ogg.js",
|
|
10
|
+
"audio-lena/flac": "./node_modules/audio-lena/flac.js",
|
|
11
|
+
"audio-lena/opus": "./node_modules/audio-lena/opus.js",
|
|
12
|
+
"audio-lena/aiff": "./node_modules/audio-lena/aiff.js",
|
|
13
|
+
"audio-lena/caf": "./node_modules/audio-lena/caf.js",
|
|
14
|
+
"audio-lena/webm": "./node_modules/audio-lena/webm.js",
|
|
15
|
+
"audio-lena/aac": "./node_modules/audio-lena/aac.js",
|
|
16
|
+
"audio-lena/m4a": "./node_modules/audio-lena/m4a.js",
|
|
6
17
|
"audio-type": "./node_modules/audio-type/audio-type.js",
|
|
7
|
-
"
|
|
8
|
-
"audio-
|
|
9
|
-
"audio-
|
|
10
|
-
"audio-
|
|
11
|
-
"audio-
|
|
18
|
+
"tst": "./node_modules/tst/tst.js",
|
|
19
|
+
"@audio/decode-mp3": "./packages/decode-mp3/decode-mp3.js",
|
|
20
|
+
"@audio/decode-wav": "./packages/decode-wav/decode-wav.js",
|
|
21
|
+
"@audio/decode-flac": "./packages/decode-flac/decode-flac.js",
|
|
22
|
+
"@audio/decode-opus": "./packages/decode-opus/decode-opus.js",
|
|
23
|
+
"@audio/decode-vorbis": "./packages/decode-vorbis/decode-vorbis.js",
|
|
24
|
+
"@audio/decode-aac": "./packages/decode-aac/decode-aac.js",
|
|
25
|
+
"@audio/decode-qoa": "./packages/decode-qoa/decode-qoa.js",
|
|
26
|
+
"@audio/decode-aiff": "./packages/decode-aiff/decode-aiff.js",
|
|
27
|
+
"@audio/decode-caf": "./packages/decode-caf/decode-caf.js",
|
|
28
|
+
"@audio/decode-webm": "./packages/decode-webm/decode-webm.js",
|
|
29
|
+
"@audio/decode-amr": "./packages/decode-amr/decode-amr.js",
|
|
30
|
+
"@audio/decode-wma": "./packages/decode-wma/decode-wma.js"
|
|
12
31
|
}
|
|
13
|
-
|
|
32
|
+
}
|
|
14
33
|
</script>
|
|
15
|
-
<script src="./test.js"
|
|
34
|
+
<script type="module" src="./test.js"></script>
|