@camstack/addon-pipeline 0.1.20 → 0.2.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/audio-analyzer/index.js +736 -719
- package/dist/audio-analyzer/index.mjs +726 -679
- package/dist/audio-codec-nodeav/index.js +304 -461
- package/dist/audio-codec-nodeav/index.mjs +300 -462
- package/dist/chunk-BdkLduGY.mjs +5 -0
- package/dist/chunk-D6vf50IK.js +28 -0
- package/dist/codec-runtime-BOk-13PN.js +202 -0
- package/dist/codec-runtime-BsqlEjPi.mjs +197 -0
- package/dist/constants-B_b0a-6h.mjs +3119 -0
- package/dist/{index-CMcx_k6Y.js → constants-D65v6yp6.js} +3107 -2935
- package/dist/decoder-nodeav/index.js +1374 -1444
- package/dist/decoder-nodeav/index.mjs +1369 -1425
- package/dist/detection-pipeline/index.js +6462 -5613
- package/dist/detection-pipeline/index.mjs +6451 -5574
- package/dist/dist-7ewQjTle.js +22454 -0
- package/dist/dist-C5jnNl0n.mjs +22089 -0
- package/dist/motion-wasm/index.js +469 -467
- package/dist/motion-wasm/index.mjs +464 -446
- package/dist/pipeline-runner/index.js +2029 -1827
- package/dist/pipeline-runner/index.mjs +2025 -1811
- package/dist/recorder/index.js +2045 -2157
- package/dist/recorder/index.mjs +2042 -2156
- package/dist/stream-broker/_stub.js +1806 -1352
- package/dist/stream-broker/_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-D4-DHanK.mjs +156 -0
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-Tf-HACFd.mjs +26 -0
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-C9WX5HNw.mjs +26 -0
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-BO7TIbJV.mjs +26 -0
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.js-C9j-2lBe.mjs +26 -0
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-XO0-Pyu6.mjs +26 -0
- package/dist/stream-broker/dist-CYZr2fwk.mjs +2726 -0
- package/dist/stream-broker/hostInit-Di6vceAU.mjs +129 -0
- package/dist/stream-broker/index.js +17778 -15470
- package/dist/stream-broker/index.mjs +17769 -15465
- package/dist/stream-broker/remoteEntry.js +134 -2973
- package/dist/stream-broker/remoteEntry.ssr.js +33 -0
- package/dist/stream-broker/virtualExposes-dYNvIwoR.mjs +27 -0
- package/dist/stream-broker/virtual_mf-exposes-ssr___mfe_internal__addon_stream_broker_widgets__remoteEntry_js-Cmqfp4i_.mjs +10 -0
- package/embed-dist/assets/index-B8VlSD0-.js +150 -0
- package/embed-dist/assets/index-ZhDdp1Nd.css +2 -0
- package/embed-dist/index.html +13 -0
- package/package.json +25 -7
- package/wasm/assembly/index.ts +41 -16
- package/dist/audio-analyzer/index.js.map +0 -1
- package/dist/audio-analyzer/index.mjs.map +0 -1
- package/dist/audio-codec-nodeav/index.js.map +0 -1
- package/dist/audio-codec-nodeav/index.mjs.map +0 -1
- package/dist/decoder-nodeav/index.js.map +0 -1
- package/dist/decoder-nodeav/index.mjs.map +0 -1
- package/dist/detection-pipeline/index.js.map +0 -1
- package/dist/detection-pipeline/index.mjs.map +0 -1
- package/dist/index-5aYef068.mjs +0 -17514
- package/dist/index-5aYef068.mjs.map +0 -1
- package/dist/index-B36NMAdu.js +0 -17513
- package/dist/index-B36NMAdu.js.map +0 -1
- package/dist/index-CMcx_k6Y.js.map +0 -1
- package/dist/index-CYb7cFrv.mjs +0 -5790
- package/dist/index-CYb7cFrv.mjs.map +0 -1
- package/dist/motion-wasm/index.js.map +0 -1
- package/dist/motion-wasm/index.mjs.map +0 -1
- package/dist/pipeline-runner/index.js.map +0 -1
- package/dist/pipeline-runner/index.mjs.map +0 -1
- package/dist/recorder/index.js.map +0 -1
- package/dist/recorder/index.mjs.map +0 -1
- package/dist/stream-broker/@mf-types/compiled-types/stream-broker/widgets/FfmpegParamsField.d.ts +0 -41
- package/dist/stream-broker/@mf-types/compiled-types/stream-broker/widgets/GeometryBuilder.d.ts +0 -54
- package/dist/stream-broker/@mf-types/compiled-types/stream-broker/widgets/StreamBrokerPanel.d.ts +0 -21
- package/dist/stream-broker/@mf-types/compiled-types/stream-broker/widgets/format-ua.d.ts +0 -13
- package/dist/stream-broker/@mf-types/compiled-types/stream-broker/widgets/index.d.ts +0 -15
- package/dist/stream-broker/@mf-types/widgets.d.ts +0 -2
- package/dist/stream-broker/@mf-types.d.ts +0 -3
- package/dist/stream-broker/@mf-types.zip +0 -0
- package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_sdk__loadShare__.mjs-lantnv8e.mjs +0 -12
- package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.mjs-DJ3UNg7O.mjs +0 -30
- package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.mjs-CYXy_bhS.mjs +0 -21
- package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.mjs-U1EUeEPs.mjs +0 -104
- package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_trpc_mf_1_client__loadShare__.mjs-DeouEaSs.mjs +0 -85
- package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_trpc_mf_1_react_mf_2_query__loadShare__.mjs-DHUwjbb9.mjs +0 -62
- package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.mjs-CaDEYBIU.mjs +0 -89
- package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare__react__loadShare__.mjs_commonjs-proxy-D6EROtlA.mjs +0 -29
- package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.mjs-x6pP3Ghk.mjs +0 -36
- package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_2_dom__loadShare__.mjs-DYEKzzY-.mjs +0 -45
- package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-CcnN6sbA.mjs +0 -6
- package/dist/stream-broker/__mfe_internal__addon_stream_broker_widgets__loadShare__react_mf_2_dom_mf_1_client__loadShare__.mjs-DICOtMTl.mjs +0 -34
- package/dist/stream-broker/_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CL9DR49k.mjs +0 -156
- package/dist/stream-broker/client-BvTmMOQu.mjs +0 -9836
- package/dist/stream-broker/getErrorShape-BPSzUA7W-TlK8ipWe.mjs +0 -211
- package/dist/stream-broker/hostInit-ChmiMPS0.mjs +0 -168
- package/dist/stream-broker/index-BxsFuFmE.mjs +0 -2603
- package/dist/stream-broker/index-C-248uOU.mjs +0 -725
- package/dist/stream-broker/index-C05B6jqp.mjs +0 -185
- package/dist/stream-broker/index-CWkKuNLr.mjs +0 -232
- package/dist/stream-broker/index-DOJoSShD.mjs +0 -67784
- package/dist/stream-broker/index-DtOI1aTU.mjs +0 -18504
- package/dist/stream-broker/index-oMq6ilgR.mjs +0 -1641
- package/dist/stream-broker/index-vIWZQBIL.mjs +0 -435
- package/dist/stream-broker/index-xncRG7-x.mjs +0 -2713
- package/dist/stream-broker/index.js.map +0 -1
- package/dist/stream-broker/index.mjs.map +0 -1
- package/dist/stream-broker/jsx-runtime-BRT_HL0A.mjs +0 -55
- package/dist/stream-broker/schemas-B7L0qZtq.mjs +0 -3599
- package/dist/stream-broker/virtualExposes-pCd777Rp.mjs +0 -42
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
//#endregion
|
|
23
|
+
Object.defineProperty(exports, "__toESM", {
|
|
24
|
+
enumerable: true,
|
|
25
|
+
get: function() {
|
|
26
|
+
return __toESM;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
let node_av = require("node-av");
|
|
2
|
+
//#region src/audio-codec-nodeav/addon/codec-runtime.ts
|
|
3
|
+
/**
|
|
4
|
+
* Thin libavcodec/libswresample wrapper backing one decode or encode
|
|
5
|
+
* session in `audio-codec`. Holds:
|
|
6
|
+
* - CodecContext (decoder or encoder)
|
|
7
|
+
* - SoftwareResampleContext for input format → output format
|
|
8
|
+
* - reusable Packet + input/output Frame
|
|
9
|
+
*
|
|
10
|
+
* Stateful — one runtime per session. The cap addon owns the lifecycle.
|
|
11
|
+
*/
|
|
12
|
+
var CODEC_ID_BY_NAME = {
|
|
13
|
+
aac: node_av.AV_CODEC_ID_AAC,
|
|
14
|
+
aac_latm: node_av.AV_CODEC_ID_AAC_LATM,
|
|
15
|
+
opus: node_av.AV_CODEC_ID_OPUS,
|
|
16
|
+
pcm_alaw: node_av.AV_CODEC_ID_PCM_ALAW,
|
|
17
|
+
pcm_mulaw: node_av.AV_CODEC_ID_PCM_MULAW
|
|
18
|
+
};
|
|
19
|
+
function resolveCodecId(codec) {
|
|
20
|
+
return CODEC_ID_BY_NAME[codec.toLowerCase()] ?? null;
|
|
21
|
+
}
|
|
22
|
+
function buildChannelLayout(channels) {
|
|
23
|
+
if (channels === 1) return {
|
|
24
|
+
nbChannels: 1,
|
|
25
|
+
order: node_av.AV_CHANNEL_ORDER_NATIVE,
|
|
26
|
+
mask: node_av.AV_CH_LAYOUT_MONO
|
|
27
|
+
};
|
|
28
|
+
if (channels === 2) return {
|
|
29
|
+
nbChannels: 2,
|
|
30
|
+
order: node_av.AV_CHANNEL_ORDER_NATIVE,
|
|
31
|
+
mask: node_av.AV_CH_LAYOUT_STEREO
|
|
32
|
+
};
|
|
33
|
+
return {
|
|
34
|
+
nbChannels: channels,
|
|
35
|
+
order: node_av.AV_CHANNEL_ORDER_NATIVE,
|
|
36
|
+
mask: 0n
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function pcmFormatToAv(format) {
|
|
40
|
+
switch (format) {
|
|
41
|
+
case "f32le": return node_av.AV_SAMPLE_FMT_FLT;
|
|
42
|
+
case "s16le": return node_av.AV_SAMPLE_FMT_S16;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function bytesPerSample(format) {
|
|
46
|
+
switch (format) {
|
|
47
|
+
case "f32le": return 4;
|
|
48
|
+
case "s16le": return 2;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
var DecodeRuntime = class DecodeRuntime {
|
|
52
|
+
ctx;
|
|
53
|
+
swr;
|
|
54
|
+
packet;
|
|
55
|
+
inFrame;
|
|
56
|
+
outFrame;
|
|
57
|
+
cfg;
|
|
58
|
+
inLayout;
|
|
59
|
+
outLayout;
|
|
60
|
+
inSampleFmt;
|
|
61
|
+
outSampleFmt;
|
|
62
|
+
outBytesPerSample;
|
|
63
|
+
nextPts = 0;
|
|
64
|
+
closed = false;
|
|
65
|
+
static create(cfg) {
|
|
66
|
+
const codecId = resolveCodecId(cfg.codec);
|
|
67
|
+
if (codecId === null) throw new Error(`audio-codec: unknown codec '${cfg.codec}' for decode runtime`);
|
|
68
|
+
const codec = node_av.Codec.findDecoder(codecId);
|
|
69
|
+
if (!codec) throw new Error(`audio-codec: decoder not registered for codec '${cfg.codec}'`);
|
|
70
|
+
const ctx = new node_av.CodecContext();
|
|
71
|
+
ctx.allocContext3(codec);
|
|
72
|
+
ctx.sampleRate = cfg.sourceSampleRate;
|
|
73
|
+
ctx.channels = cfg.sourceChannels;
|
|
74
|
+
const inLayout = buildChannelLayout(cfg.sourceChannels);
|
|
75
|
+
ctx.channelLayout = inLayout;
|
|
76
|
+
if (cfg.extraData && cfg.extraData.byteLength > 0) ctx.extraData = Buffer.from(cfg.extraData);
|
|
77
|
+
const ret = ctx.open2Sync(codec, null);
|
|
78
|
+
if (ret < 0) {
|
|
79
|
+
ctx.freeContext();
|
|
80
|
+
throw new Error(`audio-codec: open2 failed for '${cfg.codec}' (ret=${ret})`);
|
|
81
|
+
}
|
|
82
|
+
const inSampleFmt = ctx.sampleFormat ?? node_av.AV_SAMPLE_FMT_FLT;
|
|
83
|
+
const outSampleFmt = pcmFormatToAv(cfg.targetFormat);
|
|
84
|
+
const outLayout = buildChannelLayout(cfg.targetChannels);
|
|
85
|
+
const swr = new node_av.SoftwareResampleContext();
|
|
86
|
+
const allocRet = swr.allocSetOpts2(outLayout, outSampleFmt, cfg.targetSampleRate, inLayout, inSampleFmt, cfg.sourceSampleRate);
|
|
87
|
+
if (allocRet < 0) {
|
|
88
|
+
ctx.freeContext();
|
|
89
|
+
throw new Error(`audio-codec: swr allocSetOpts2 failed (ret=${allocRet})`);
|
|
90
|
+
}
|
|
91
|
+
const initRet = swr.init();
|
|
92
|
+
if (initRet < 0) {
|
|
93
|
+
ctx.freeContext();
|
|
94
|
+
throw new Error(`audio-codec: swr init failed (ret=${initRet})`);
|
|
95
|
+
}
|
|
96
|
+
const packet = new node_av.Packet();
|
|
97
|
+
packet.alloc();
|
|
98
|
+
const inFrame = new node_av.Frame();
|
|
99
|
+
inFrame.alloc();
|
|
100
|
+
const outFrame = new node_av.Frame();
|
|
101
|
+
outFrame.alloc();
|
|
102
|
+
return new DecodeRuntime(ctx, swr, packet, inFrame, outFrame, cfg, inLayout, outLayout, inSampleFmt, outSampleFmt);
|
|
103
|
+
}
|
|
104
|
+
constructor(ctx, swr, packet, inFrame, outFrame, cfg, inLayout, outLayout, inSampleFmt, outSampleFmt) {
|
|
105
|
+
this.ctx = ctx;
|
|
106
|
+
this.swr = swr;
|
|
107
|
+
this.packet = packet;
|
|
108
|
+
this.inFrame = inFrame;
|
|
109
|
+
this.outFrame = outFrame;
|
|
110
|
+
this.cfg = cfg;
|
|
111
|
+
this.inLayout = inLayout;
|
|
112
|
+
this.outLayout = outLayout;
|
|
113
|
+
this.inSampleFmt = inSampleFmt;
|
|
114
|
+
this.outSampleFmt = outSampleFmt;
|
|
115
|
+
this.outBytesPerSample = bytesPerSample(cfg.targetFormat);
|
|
116
|
+
}
|
|
117
|
+
decode(buf, pts) {
|
|
118
|
+
if (this.closed) return [];
|
|
119
|
+
this.packet.data = Buffer.from(buf);
|
|
120
|
+
if (pts !== void 0) {
|
|
121
|
+
this.packet.pts = BigInt(Math.round(pts));
|
|
122
|
+
this.packet.dts = BigInt(Math.round(pts));
|
|
123
|
+
}
|
|
124
|
+
const sendRet = this.ctx.sendPacketSync(this.packet);
|
|
125
|
+
if (sendRet < 0 && sendRet !== node_av.AVERROR_EAGAIN) throw new Error(`audio-codec: sendPacket failed (ret=${sendRet})`);
|
|
126
|
+
const out = [];
|
|
127
|
+
while (true) {
|
|
128
|
+
const recvRet = this.ctx.receiveFrameSync(this.inFrame);
|
|
129
|
+
if (recvRet === node_av.AVERROR_EAGAIN || recvRet === node_av.AVERROR_EOF) break;
|
|
130
|
+
if (recvRet < 0) throw new Error(`audio-codec: receiveFrame failed (ret=${recvRet})`);
|
|
131
|
+
const pcm = this.resampleFrame(this.inFrame);
|
|
132
|
+
if (pcm) out.push(pcm);
|
|
133
|
+
this.inFrame.unref();
|
|
134
|
+
}
|
|
135
|
+
return out;
|
|
136
|
+
}
|
|
137
|
+
resampleFrame(inFrame) {
|
|
138
|
+
const inSamples = inFrame.nbSamples;
|
|
139
|
+
const outSamples = Math.ceil(inSamples * this.cfg.targetSampleRate / this.cfg.sourceSampleRate) + 32;
|
|
140
|
+
this.outFrame.unref();
|
|
141
|
+
this.outFrame.format = this.outSampleFmt;
|
|
142
|
+
this.outFrame.sampleRate = this.cfg.targetSampleRate;
|
|
143
|
+
this.outFrame.channelLayout = this.outLayout;
|
|
144
|
+
this.outFrame.nbSamples = outSamples;
|
|
145
|
+
const allocRet = this.outFrame.getBuffer(0);
|
|
146
|
+
if (allocRet < 0) throw new Error(`audio-codec: outFrame.getBuffer failed (ret=${allocRet})`);
|
|
147
|
+
const convRet = this.swr.convertFrame(this.outFrame, inFrame);
|
|
148
|
+
if (convRet < 0) throw new Error(`audio-codec: swr.convertFrame failed (ret=${convRet})`);
|
|
149
|
+
const producedSamples = this.outFrame.nbSamples;
|
|
150
|
+
if (producedSamples <= 0) return null;
|
|
151
|
+
const planes = this.outFrame.extendedData;
|
|
152
|
+
if (!planes || planes.length === 0 || !planes[0]) return null;
|
|
153
|
+
const bytes = producedSamples * this.cfg.targetChannels * this.outBytesPerSample;
|
|
154
|
+
const src = planes[0];
|
|
155
|
+
const out = new Uint8Array(new ArrayBuffer(bytes));
|
|
156
|
+
out.set(src.subarray(0, bytes));
|
|
157
|
+
const ptsMs = this.nextPts;
|
|
158
|
+
this.nextPts = ptsMs + Math.round(producedSamples * 1e3 / this.cfg.targetSampleRate);
|
|
159
|
+
return {
|
|
160
|
+
data: out,
|
|
161
|
+
sampleRate: this.cfg.targetSampleRate,
|
|
162
|
+
channels: this.cfg.targetChannels,
|
|
163
|
+
format: this.cfg.targetFormat,
|
|
164
|
+
pts: ptsMs
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
close() {
|
|
168
|
+
if (this.closed) return;
|
|
169
|
+
this.closed = true;
|
|
170
|
+
try {
|
|
171
|
+
this.outFrame.free();
|
|
172
|
+
} catch {}
|
|
173
|
+
try {
|
|
174
|
+
this.inFrame.free();
|
|
175
|
+
} catch {}
|
|
176
|
+
try {
|
|
177
|
+
this.packet.free();
|
|
178
|
+
} catch {}
|
|
179
|
+
try {
|
|
180
|
+
this.swr.free();
|
|
181
|
+
} catch {}
|
|
182
|
+
try {
|
|
183
|
+
this.ctx.freeContext();
|
|
184
|
+
} catch {}
|
|
185
|
+
}
|
|
186
|
+
/** Surfaced for assertion-style tests to inspect computed layouts. */
|
|
187
|
+
describe() {
|
|
188
|
+
return {
|
|
189
|
+
inLayoutMask: this.inLayout.mask,
|
|
190
|
+
outLayoutMask: this.outLayout.mask,
|
|
191
|
+
inSampleFormat: this.inSampleFmt,
|
|
192
|
+
outSampleFormat: this.outSampleFmt
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
//#endregion
|
|
197
|
+
Object.defineProperty(exports, "DecodeRuntime", {
|
|
198
|
+
enumerable: true,
|
|
199
|
+
get: function() {
|
|
200
|
+
return DecodeRuntime;
|
|
201
|
+
}
|
|
202
|
+
});
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { AVERROR_EAGAIN, AVERROR_EOF, AV_CHANNEL_ORDER_NATIVE, AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, AV_CODEC_ID_AAC, AV_CODEC_ID_AAC_LATM, AV_CODEC_ID_OPUS, AV_CODEC_ID_PCM_ALAW, AV_CODEC_ID_PCM_MULAW, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, Codec, CodecContext, Frame, Packet, SoftwareResampleContext } from "node-av";
|
|
2
|
+
//#region src/audio-codec-nodeav/addon/codec-runtime.ts
|
|
3
|
+
/**
|
|
4
|
+
* Thin libavcodec/libswresample wrapper backing one decode or encode
|
|
5
|
+
* session in `audio-codec`. Holds:
|
|
6
|
+
* - CodecContext (decoder or encoder)
|
|
7
|
+
* - SoftwareResampleContext for input format → output format
|
|
8
|
+
* - reusable Packet + input/output Frame
|
|
9
|
+
*
|
|
10
|
+
* Stateful — one runtime per session. The cap addon owns the lifecycle.
|
|
11
|
+
*/
|
|
12
|
+
var CODEC_ID_BY_NAME = {
|
|
13
|
+
aac: AV_CODEC_ID_AAC,
|
|
14
|
+
aac_latm: AV_CODEC_ID_AAC_LATM,
|
|
15
|
+
opus: AV_CODEC_ID_OPUS,
|
|
16
|
+
pcm_alaw: AV_CODEC_ID_PCM_ALAW,
|
|
17
|
+
pcm_mulaw: AV_CODEC_ID_PCM_MULAW
|
|
18
|
+
};
|
|
19
|
+
function resolveCodecId(codec) {
|
|
20
|
+
return CODEC_ID_BY_NAME[codec.toLowerCase()] ?? null;
|
|
21
|
+
}
|
|
22
|
+
function buildChannelLayout(channels) {
|
|
23
|
+
if (channels === 1) return {
|
|
24
|
+
nbChannels: 1,
|
|
25
|
+
order: AV_CHANNEL_ORDER_NATIVE,
|
|
26
|
+
mask: AV_CH_LAYOUT_MONO
|
|
27
|
+
};
|
|
28
|
+
if (channels === 2) return {
|
|
29
|
+
nbChannels: 2,
|
|
30
|
+
order: AV_CHANNEL_ORDER_NATIVE,
|
|
31
|
+
mask: AV_CH_LAYOUT_STEREO
|
|
32
|
+
};
|
|
33
|
+
return {
|
|
34
|
+
nbChannels: channels,
|
|
35
|
+
order: AV_CHANNEL_ORDER_NATIVE,
|
|
36
|
+
mask: 0n
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function pcmFormatToAv(format) {
|
|
40
|
+
switch (format) {
|
|
41
|
+
case "f32le": return AV_SAMPLE_FMT_FLT;
|
|
42
|
+
case "s16le": return AV_SAMPLE_FMT_S16;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function bytesPerSample(format) {
|
|
46
|
+
switch (format) {
|
|
47
|
+
case "f32le": return 4;
|
|
48
|
+
case "s16le": return 2;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
var DecodeRuntime = class DecodeRuntime {
|
|
52
|
+
ctx;
|
|
53
|
+
swr;
|
|
54
|
+
packet;
|
|
55
|
+
inFrame;
|
|
56
|
+
outFrame;
|
|
57
|
+
cfg;
|
|
58
|
+
inLayout;
|
|
59
|
+
outLayout;
|
|
60
|
+
inSampleFmt;
|
|
61
|
+
outSampleFmt;
|
|
62
|
+
outBytesPerSample;
|
|
63
|
+
nextPts = 0;
|
|
64
|
+
closed = false;
|
|
65
|
+
static create(cfg) {
|
|
66
|
+
const codecId = resolveCodecId(cfg.codec);
|
|
67
|
+
if (codecId === null) throw new Error(`audio-codec: unknown codec '${cfg.codec}' for decode runtime`);
|
|
68
|
+
const codec = Codec.findDecoder(codecId);
|
|
69
|
+
if (!codec) throw new Error(`audio-codec: decoder not registered for codec '${cfg.codec}'`);
|
|
70
|
+
const ctx = new CodecContext();
|
|
71
|
+
ctx.allocContext3(codec);
|
|
72
|
+
ctx.sampleRate = cfg.sourceSampleRate;
|
|
73
|
+
ctx.channels = cfg.sourceChannels;
|
|
74
|
+
const inLayout = buildChannelLayout(cfg.sourceChannels);
|
|
75
|
+
ctx.channelLayout = inLayout;
|
|
76
|
+
if (cfg.extraData && cfg.extraData.byteLength > 0) ctx.extraData = Buffer.from(cfg.extraData);
|
|
77
|
+
const ret = ctx.open2Sync(codec, null);
|
|
78
|
+
if (ret < 0) {
|
|
79
|
+
ctx.freeContext();
|
|
80
|
+
throw new Error(`audio-codec: open2 failed for '${cfg.codec}' (ret=${ret})`);
|
|
81
|
+
}
|
|
82
|
+
const inSampleFmt = ctx.sampleFormat ?? AV_SAMPLE_FMT_FLT;
|
|
83
|
+
const outSampleFmt = pcmFormatToAv(cfg.targetFormat);
|
|
84
|
+
const outLayout = buildChannelLayout(cfg.targetChannels);
|
|
85
|
+
const swr = new SoftwareResampleContext();
|
|
86
|
+
const allocRet = swr.allocSetOpts2(outLayout, outSampleFmt, cfg.targetSampleRate, inLayout, inSampleFmt, cfg.sourceSampleRate);
|
|
87
|
+
if (allocRet < 0) {
|
|
88
|
+
ctx.freeContext();
|
|
89
|
+
throw new Error(`audio-codec: swr allocSetOpts2 failed (ret=${allocRet})`);
|
|
90
|
+
}
|
|
91
|
+
const initRet = swr.init();
|
|
92
|
+
if (initRet < 0) {
|
|
93
|
+
ctx.freeContext();
|
|
94
|
+
throw new Error(`audio-codec: swr init failed (ret=${initRet})`);
|
|
95
|
+
}
|
|
96
|
+
const packet = new Packet();
|
|
97
|
+
packet.alloc();
|
|
98
|
+
const inFrame = new Frame();
|
|
99
|
+
inFrame.alloc();
|
|
100
|
+
const outFrame = new Frame();
|
|
101
|
+
outFrame.alloc();
|
|
102
|
+
return new DecodeRuntime(ctx, swr, packet, inFrame, outFrame, cfg, inLayout, outLayout, inSampleFmt, outSampleFmt);
|
|
103
|
+
}
|
|
104
|
+
constructor(ctx, swr, packet, inFrame, outFrame, cfg, inLayout, outLayout, inSampleFmt, outSampleFmt) {
|
|
105
|
+
this.ctx = ctx;
|
|
106
|
+
this.swr = swr;
|
|
107
|
+
this.packet = packet;
|
|
108
|
+
this.inFrame = inFrame;
|
|
109
|
+
this.outFrame = outFrame;
|
|
110
|
+
this.cfg = cfg;
|
|
111
|
+
this.inLayout = inLayout;
|
|
112
|
+
this.outLayout = outLayout;
|
|
113
|
+
this.inSampleFmt = inSampleFmt;
|
|
114
|
+
this.outSampleFmt = outSampleFmt;
|
|
115
|
+
this.outBytesPerSample = bytesPerSample(cfg.targetFormat);
|
|
116
|
+
}
|
|
117
|
+
decode(buf, pts) {
|
|
118
|
+
if (this.closed) return [];
|
|
119
|
+
this.packet.data = Buffer.from(buf);
|
|
120
|
+
if (pts !== void 0) {
|
|
121
|
+
this.packet.pts = BigInt(Math.round(pts));
|
|
122
|
+
this.packet.dts = BigInt(Math.round(pts));
|
|
123
|
+
}
|
|
124
|
+
const sendRet = this.ctx.sendPacketSync(this.packet);
|
|
125
|
+
if (sendRet < 0 && sendRet !== AVERROR_EAGAIN) throw new Error(`audio-codec: sendPacket failed (ret=${sendRet})`);
|
|
126
|
+
const out = [];
|
|
127
|
+
while (true) {
|
|
128
|
+
const recvRet = this.ctx.receiveFrameSync(this.inFrame);
|
|
129
|
+
if (recvRet === AVERROR_EAGAIN || recvRet === AVERROR_EOF) break;
|
|
130
|
+
if (recvRet < 0) throw new Error(`audio-codec: receiveFrame failed (ret=${recvRet})`);
|
|
131
|
+
const pcm = this.resampleFrame(this.inFrame);
|
|
132
|
+
if (pcm) out.push(pcm);
|
|
133
|
+
this.inFrame.unref();
|
|
134
|
+
}
|
|
135
|
+
return out;
|
|
136
|
+
}
|
|
137
|
+
resampleFrame(inFrame) {
|
|
138
|
+
const inSamples = inFrame.nbSamples;
|
|
139
|
+
const outSamples = Math.ceil(inSamples * this.cfg.targetSampleRate / this.cfg.sourceSampleRate) + 32;
|
|
140
|
+
this.outFrame.unref();
|
|
141
|
+
this.outFrame.format = this.outSampleFmt;
|
|
142
|
+
this.outFrame.sampleRate = this.cfg.targetSampleRate;
|
|
143
|
+
this.outFrame.channelLayout = this.outLayout;
|
|
144
|
+
this.outFrame.nbSamples = outSamples;
|
|
145
|
+
const allocRet = this.outFrame.getBuffer(0);
|
|
146
|
+
if (allocRet < 0) throw new Error(`audio-codec: outFrame.getBuffer failed (ret=${allocRet})`);
|
|
147
|
+
const convRet = this.swr.convertFrame(this.outFrame, inFrame);
|
|
148
|
+
if (convRet < 0) throw new Error(`audio-codec: swr.convertFrame failed (ret=${convRet})`);
|
|
149
|
+
const producedSamples = this.outFrame.nbSamples;
|
|
150
|
+
if (producedSamples <= 0) return null;
|
|
151
|
+
const planes = this.outFrame.extendedData;
|
|
152
|
+
if (!planes || planes.length === 0 || !planes[0]) return null;
|
|
153
|
+
const bytes = producedSamples * this.cfg.targetChannels * this.outBytesPerSample;
|
|
154
|
+
const src = planes[0];
|
|
155
|
+
const out = new Uint8Array(new ArrayBuffer(bytes));
|
|
156
|
+
out.set(src.subarray(0, bytes));
|
|
157
|
+
const ptsMs = this.nextPts;
|
|
158
|
+
this.nextPts = ptsMs + Math.round(producedSamples * 1e3 / this.cfg.targetSampleRate);
|
|
159
|
+
return {
|
|
160
|
+
data: out,
|
|
161
|
+
sampleRate: this.cfg.targetSampleRate,
|
|
162
|
+
channels: this.cfg.targetChannels,
|
|
163
|
+
format: this.cfg.targetFormat,
|
|
164
|
+
pts: ptsMs
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
close() {
|
|
168
|
+
if (this.closed) return;
|
|
169
|
+
this.closed = true;
|
|
170
|
+
try {
|
|
171
|
+
this.outFrame.free();
|
|
172
|
+
} catch {}
|
|
173
|
+
try {
|
|
174
|
+
this.inFrame.free();
|
|
175
|
+
} catch {}
|
|
176
|
+
try {
|
|
177
|
+
this.packet.free();
|
|
178
|
+
} catch {}
|
|
179
|
+
try {
|
|
180
|
+
this.swr.free();
|
|
181
|
+
} catch {}
|
|
182
|
+
try {
|
|
183
|
+
this.ctx.freeContext();
|
|
184
|
+
} catch {}
|
|
185
|
+
}
|
|
186
|
+
/** Surfaced for assertion-style tests to inspect computed layouts. */
|
|
187
|
+
describe() {
|
|
188
|
+
return {
|
|
189
|
+
inLayoutMask: this.inLayout.mask,
|
|
190
|
+
outLayoutMask: this.outLayout.mask,
|
|
191
|
+
inSampleFormat: this.inSampleFmt,
|
|
192
|
+
outSampleFormat: this.outSampleFmt
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
//#endregion
|
|
197
|
+
export { DecodeRuntime as t };
|