@audio/decode-mp4 1.0.0 → 1.1.0
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/README.md +4 -2
- package/decode-mp4.js +13 -6
- package/package.json +20 -2
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @audio/decode-mp4
|
|
2
2
|
|
|
3
3
|
Decode the audio track of MP4, MOV, M4A, M4V and 3GP files to PCM float samples.<br>
|
|
4
|
-
A pure-JS ISO BMFF demuxer that skips the video track and routes the audio to the matching codec package, loaded on demand.
|
|
4
|
+
A pure-JS ISO BMFF demuxer that skips the video track and routes the audio (AAC, ALAC, MP3, FLAC, Opus, AC-3, DTS, AMR, PCM) to the matching codec package, loaded on demand.
|
|
5
5
|
|
|
6
6
|
[](https://npmjs.org/package/@audio/decode-mp4/)
|
|
7
7
|
|
|
@@ -29,8 +29,10 @@ dec.free()
|
|
|
29
29
|
| `samr`, `sawb` | AMR-NB, AMR-WB | [@audio/decode-amr](../decode-amr) |
|
|
30
30
|
| `sowt`, `twos`, `in24`, `in32`, `fl32`, `fl64`, `lpcm`, `ipcm`, `fpcm`, `raw `, `NONE` | PCM 8–32 bit int, 32/64 bit float, either endianness | built in |
|
|
31
31
|
| `ulaw`, `alaw` | G.711 | built in |
|
|
32
|
+
| `ac-3`, `mp4a` (0xA5) | AC-3 | [@audio/decode-ac3](../decode-ac3) |
|
|
33
|
+
| `dtsc`, `dtsh`, `dtsl`, `dtse`, `mp4a` (0xA9) | DTS (core) | [@audio/decode-dts](../decode-dts) |
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
E-AC-3 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.
|
|
34
36
|
|
|
35
37
|
Codec packages are imported dynamically, which is unavailable inside an AudioWorklet — decode in the main thread or a Worker.
|
|
36
38
|
|
package/decode-mp4.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MP4 / MOV / M4A / M4V / 3GP audio decoder — ISO BMFF demuxer that routes the audio track to a codec:
|
|
3
3
|
* AAC, ALAC → @audio/decode-aac · MP3 → @audio/decode-mp3 · FLAC → @audio/decode-flac
|
|
4
|
-
* Opus → @audio/decode-opus/core · AMR → @audio/decode-amr ·
|
|
4
|
+
* Opus → @audio/decode-opus/core · AMR → @audio/decode-amr · AC-3 → @audio/decode-ac3 · DTS → @audio/decode-dts
|
|
5
|
+
* PCM / µ-law / A-law inline.
|
|
5
6
|
*
|
|
6
7
|
* let { channelData, sampleRate } = await decode(mp4buf)
|
|
7
8
|
* let dec = await decoder(); let result = await dec.decode(chunk)
|
|
@@ -248,13 +249,16 @@ function advance(st) {
|
|
|
248
249
|
// ===== codec routing =====
|
|
249
250
|
|
|
250
251
|
const MP3_OTI = new Set([0x69, 0x6B]), AAC_OTI = new Set([0x40, 0x66, 0x67, 0x68])
|
|
251
|
-
const UNSUPPORTED = {
|
|
252
|
+
const UNSUPPORTED = { 0xA6: 'E-AC-3', 0xE1: 'QCELP', 'ec-3': 'E-AC-3' }
|
|
253
|
+
const DTS_TYPES = new Set(['dtsc', 'dtsh', 'dtsl', 'dtse']) // DTS-HD variants carry a decodable core
|
|
252
254
|
|
|
253
255
|
async function createCodec({ entry, children }) {
|
|
254
256
|
let { type } = entry
|
|
255
257
|
if (type === 'mp4a') {
|
|
256
258
|
let { oti, dsi } = children.esds ? parseEsds(children.esds) : {}
|
|
257
|
-
if (MP3_OTI.has(oti)) return mp3
|
|
259
|
+
if (MP3_OTI.has(oti)) return frames(import('@audio/decode-mp3'))
|
|
260
|
+
if (oti === 0xA5) return frames(import('@audio/decode-ac3'))
|
|
261
|
+
if (oti === 0xA9) return frames(import('@audio/decode-dts'))
|
|
258
262
|
if (!oti || AAC_OTI.has(oti)) {
|
|
259
263
|
if (!dsi) throw Error('MP4 AAC track has no AudioSpecificConfig')
|
|
260
264
|
return aac({ asc: dsi })
|
|
@@ -265,7 +269,7 @@ async function createCodec({ entry, children }) {
|
|
|
265
269
|
if (!children.alac) throw Error('MP4 ALAC track has no magic cookie')
|
|
266
270
|
return aac({ alac: children.alac })
|
|
267
271
|
}
|
|
268
|
-
if (type === '.mp3') return mp3
|
|
272
|
+
if (type === '.mp3') return frames(import('@audio/decode-mp3'))
|
|
269
273
|
if (type === 'fLaC') {
|
|
270
274
|
if (!children.dfLa) throw Error('MP4 FLAC track has no dfLa box')
|
|
271
275
|
return flac(children.dfLa.subarray(4))
|
|
@@ -275,6 +279,8 @@ async function createCodec({ entry, children }) {
|
|
|
275
279
|
return opus(children.dOps)
|
|
276
280
|
}
|
|
277
281
|
if (type === 'samr' || type === 'sawb') return amr(type === 'sawb')
|
|
282
|
+
if (type === 'ac-3') return frames(import('@audio/decode-ac3'))
|
|
283
|
+
if (DTS_TYPES.has(type)) return frames(import('@audio/decode-dts'))
|
|
278
284
|
let fmt = pcmFormat(entry, children)
|
|
279
285
|
if (fmt) return pcm(fmt)
|
|
280
286
|
throw unsupported(UNSUPPORTED[type] || type)
|
|
@@ -316,8 +322,9 @@ async function aac(opts) {
|
|
|
316
322
|
return { feed: frames => dec.decode(frames), flush: () => dec.flush(), free: () => dec.free() }
|
|
317
323
|
}
|
|
318
324
|
|
|
319
|
-
|
|
320
|
-
|
|
325
|
+
// self-synchronizing frame streams (MP3, AC-3, DTS): the codec resyncs on concatenated samples
|
|
326
|
+
async function frames(load) {
|
|
327
|
+
let dec = await (await load).decoder()
|
|
321
328
|
return { feed: frames => dec.decode(concat(frames)), flush: () => dec.flush?.() ?? EMPTY, free: () => dec.free() }
|
|
322
329
|
}
|
|
323
330
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@audio/decode-mp4",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
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",
|
|
@@ -28,7 +28,9 @@
|
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@audio/decode-aac": "^1.5.0",
|
|
31
|
+
"@audio/decode-ac3": "^1.0.0",
|
|
31
32
|
"@audio/decode-amr": "^1.3.0",
|
|
33
|
+
"@audio/decode-dts": "^1.0.0",
|
|
32
34
|
"@audio/decode-flac": "^1.3.0",
|
|
33
35
|
"@audio/decode-mp3": "^1.3.0",
|
|
34
36
|
"@audio/decode-opus": "^1.3.0"
|
|
@@ -39,7 +41,23 @@
|
|
|
39
41
|
"engines": {
|
|
40
42
|
"node": ">=18"
|
|
41
43
|
},
|
|
42
|
-
"keywords": [
|
|
44
|
+
"keywords": [
|
|
45
|
+
"mp4",
|
|
46
|
+
"mov",
|
|
47
|
+
"m4a",
|
|
48
|
+
"m4v",
|
|
49
|
+
"3gp",
|
|
50
|
+
"quicktime",
|
|
51
|
+
"isobmff",
|
|
52
|
+
"demux",
|
|
53
|
+
"video",
|
|
54
|
+
"audio",
|
|
55
|
+
"decode",
|
|
56
|
+
"decoder",
|
|
57
|
+
"aac",
|
|
58
|
+
"alac",
|
|
59
|
+
"pcm"
|
|
60
|
+
],
|
|
43
61
|
"license": "MIT",
|
|
44
62
|
"author": "audiojs",
|
|
45
63
|
"homepage": "https://github.com/audiojs/decode/tree/main/packages/decode-mp4",
|