@livekit/rtc-node 0.13.11 → 0.13.13
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_filter.cjs.map +1 -1
- package/dist/audio_filter.d.ts.map +1 -1
- package/dist/audio_filter.js +1 -4
- package/dist/audio_filter.js.map +1 -1
- package/dist/audio_source.cjs +5 -1
- package/dist/audio_source.cjs.map +1 -1
- package/dist/audio_source.d.ts.map +1 -1
- package/dist/audio_source.js +5 -1
- package/dist/audio_source.js.map +1 -1
- package/dist/audio_stream.cjs +15 -36
- package/dist/audio_stream.cjs.map +1 -1
- package/dist/audio_stream.d.cts +4 -22
- package/dist/audio_stream.d.ts +4 -22
- package/dist/audio_stream.d.ts.map +1 -1
- package/dist/audio_stream.js +15 -36
- package/dist/audio_stream.js.map +1 -1
- package/dist/index.d.cts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/room.cjs +1 -0
- package/dist/room.cjs.map +1 -1
- package/dist/room.d.ts.map +1 -1
- package/dist/room.js +1 -0
- package/dist/room.js.map +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.d.cts +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/video_stream.cjs +20 -48
- package/dist/video_stream.cjs.map +1 -1
- package/dist/video_stream.d.cts +4 -19
- package/dist/video_stream.d.ts +4 -19
- package/dist/video_stream.d.ts.map +1 -1
- package/dist/video_stream.js +20 -48
- package/dist/video_stream.js.map +1 -1
- package/package.json +6 -6
- package/src/audio_filter.ts +2 -4
- package/src/audio_source.ts +7 -3
- package/src/audio_stream.ts +30 -51
- package/src/room.ts +2 -0
- package/src/version.ts +1 -1
- package/src/video_stream.ts +24 -60
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/audio_filter.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { FfiClient } from './ffi_client.js';\nimport {
|
|
1
|
+
{"version":3,"sources":["../src/audio_filter.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { FfiClient } from './ffi_client.js';\nimport type { LoadAudioFilterPluginResponse } from './proto/audio_frame_pb.js';\nimport { LoadAudioFilterPluginRequest } from './proto/audio_frame_pb.js';\n\nexport class AudioFilter {\n constructor(moduleId: string, path: string, dependencies: string[] = []) {\n const req = new LoadAudioFilterPluginRequest({\n moduleId,\n pluginPath: path,\n dependencies,\n });\n\n const res = FfiClient.instance.request<LoadAudioFilterPluginResponse>({\n message: {\n case: 'loadAudioFilterPlugin',\n value: req,\n },\n });\n\n if (res.error) {\n throw new Error(`Failed to initialize audio filter: ${res.error}`);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,wBAA0B;AAE1B,4BAA6C;AAEtC,MAAM,YAAY;AAAA,EACvB,YAAY,UAAkB,MAAc,eAAyB,CAAC,GAAG;AACvE,UAAM,MAAM,IAAI,mDAA6B;AAAA,MAC3C;AAAA,MACA,YAAY;AAAA,MACZ;AAAA,IACF,CAAC;AAED,UAAM,MAAM,4BAAU,SAAS,QAAuC;AAAA,MACpE,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,QAAI,IAAI,OAAO;AACb,YAAM,IAAI,MAAM,sCAAsC,IAAI,KAAK,EAAE;AAAA,IACnE;AAAA,EACF;AACF;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audio_filter.d.ts","sourceRoot":"","sources":["../src/audio_filter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"audio_filter.d.ts","sourceRoot":"","sources":["../src/audio_filter.ts"],"names":[],"mappings":"AAOA,qBAAa,WAAW;gBACV,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,GAAE,MAAM,EAAO;CAkBxE"}
|
package/dist/audio_filter.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { FfiClient } from "./ffi_client.js";
|
|
2
|
-
import {
|
|
3
|
-
LoadAudioFilterPluginRequest,
|
|
4
|
-
LoadAudioFilterPluginResponse
|
|
5
|
-
} from "./proto/audio_frame_pb.js";
|
|
2
|
+
import { LoadAudioFilterPluginRequest } from "./proto/audio_frame_pb.js";
|
|
6
3
|
class AudioFilter {
|
|
7
4
|
constructor(moduleId, path, dependencies = []) {
|
|
8
5
|
const req = new LoadAudioFilterPluginRequest({
|
package/dist/audio_filter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/audio_filter.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { FfiClient } from './ffi_client.js';\nimport {
|
|
1
|
+
{"version":3,"sources":["../src/audio_filter.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { FfiClient } from './ffi_client.js';\nimport type { LoadAudioFilterPluginResponse } from './proto/audio_frame_pb.js';\nimport { LoadAudioFilterPluginRequest } from './proto/audio_frame_pb.js';\n\nexport class AudioFilter {\n constructor(moduleId: string, path: string, dependencies: string[] = []) {\n const req = new LoadAudioFilterPluginRequest({\n moduleId,\n pluginPath: path,\n dependencies,\n });\n\n const res = FfiClient.instance.request<LoadAudioFilterPluginResponse>({\n message: {\n case: 'loadAudioFilterPlugin',\n value: req,\n },\n });\n\n if (res.error) {\n throw new Error(`Failed to initialize audio filter: ${res.error}`);\n }\n }\n}\n"],"mappings":"AAGA,SAAS,iBAAiB;AAE1B,SAAS,oCAAoC;AAEtC,MAAM,YAAY;AAAA,EACvB,YAAY,UAAkB,MAAc,eAAyB,CAAC,GAAG;AACvE,UAAM,MAAM,IAAI,6BAA6B;AAAA,MAC3C;AAAA,MACA,YAAY;AAAA,MACZ;AAAA,IACF,CAAC;AAED,UAAM,MAAM,UAAU,SAAS,QAAuC;AAAA,MACpE,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,QAAI,IAAI,OAAO;AACb,YAAM,IAAI,MAAM,sCAAsC,IAAI,KAAK,EAAE;AAAA,IACnE;AAAA,EACF;AACF;","names":[]}
|
package/dist/audio_source.cjs
CHANGED
|
@@ -83,12 +83,16 @@ class AudioSource {
|
|
|
83
83
|
this.lastCapture = 0;
|
|
84
84
|
this.currentQueueSize = 0;
|
|
85
85
|
this.promise = this.newPromise();
|
|
86
|
+
this.timeout = void 0;
|
|
86
87
|
});
|
|
87
88
|
}
|
|
88
89
|
async captureFrame(frame) {
|
|
89
90
|
if (this.closed) {
|
|
90
91
|
throw new Error("AudioSource is closed");
|
|
91
92
|
}
|
|
93
|
+
if (frame.samplesPerChannel === 0) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
92
96
|
const now = Number(process.hrtime.bigint() / BigInt(1e6));
|
|
93
97
|
const elapsed = this.lastCapture === 0 ? 0 : now - this.lastCapture;
|
|
94
98
|
const frameDurationMs = frame.samplesPerChannel / frame.sampleRate * 1e3;
|
|
@@ -97,7 +101,7 @@ class AudioSource {
|
|
|
97
101
|
if (this.timeout) {
|
|
98
102
|
clearTimeout(this.timeout);
|
|
99
103
|
}
|
|
100
|
-
this.timeout = setTimeout(this.release, this.currentQueueSize
|
|
104
|
+
this.timeout = setTimeout(this.release, this.currentQueueSize);
|
|
101
105
|
const req = new import_audio_frame_pb.CaptureAudioFrameRequest({
|
|
102
106
|
sourceHandle: this.ffiHandle.handle,
|
|
103
107
|
buffer: frame.protoInfo()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/audio_source.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame } from './audio_frame.js';\nimport { FfiClient } from './ffi_client.js';\nimport { FfiHandle } from './napi/native.js';\nimport type {\n AudioSourceInfo,\n CaptureAudioFrameCallback,\n CaptureAudioFrameResponse,\n ClearAudioBufferResponse,\n NewAudioSourceResponse,\n} from './proto/audio_frame_pb.js';\nimport {\n AudioSourceType,\n CaptureAudioFrameRequest,\n ClearAudioBufferRequest,\n NewAudioSourceRequest,\n} from './proto/audio_frame_pb.js';\n\nexport class AudioSource {\n /** @internal */\n info: AudioSourceInfo;\n /** @internal */\n ffiHandle: FfiHandle;\n /** @internal */\n lastCapture: number;\n /** @internal */\n currentQueueSize: number;\n /** @internal */\n release = () => {};\n promise = this.newPromise();\n /** @internal */\n timeout?: ReturnType<typeof setTimeout> = undefined;\n /** @internal */\n closed = false;\n\n sampleRate: number;\n numChannels: number;\n queueSize: number;\n\n constructor(sampleRate: number, numChannels: number, queueSize = 1000) {\n this.sampleRate = sampleRate;\n this.numChannels = numChannels;\n this.queueSize = queueSize;\n\n this.lastCapture = 0;\n this.currentQueueSize = 0;\n\n const req = new NewAudioSourceRequest({\n type: AudioSourceType.AUDIO_SOURCE_NATIVE,\n sampleRate: sampleRate,\n numChannels: numChannels,\n queueSizeMs: queueSize,\n });\n\n const res = FfiClient.instance.request<NewAudioSourceResponse>({\n message: {\n case: 'newAudioSource',\n value: req,\n },\n });\n\n this.info = res.source!.info!;\n this.ffiHandle = new FfiHandle(res.source!.handle!.id!);\n }\n\n get queuedDuration(): number {\n return Math.max(\n this.currentQueueSize - Number(process.hrtime.bigint() / BigInt(1000000)) + this.lastCapture,\n 0,\n );\n }\n\n clearQueue() {\n const req = new ClearAudioBufferRequest({\n sourceHandle: this.ffiHandle.handle,\n });\n\n FfiClient.instance.request<ClearAudioBufferResponse>({\n message: {\n case: 'clearAudioBuffer',\n value: req,\n },\n });\n\n this.release();\n }\n\n /** @internal */\n async newPromise() {\n return new Promise<void>((resolve) => {\n this.release = resolve;\n });\n }\n\n async waitForPlayout() {\n return this.promise.then(() => {\n this.lastCapture = 0;\n this.currentQueueSize = 0;\n this.promise = this.newPromise();\n });\n }\n\n async captureFrame(frame: AudioFrame) {\n if (this.closed) {\n throw new Error('AudioSource is closed');\n }\n const now = Number(process.hrtime.bigint() / BigInt(1000000));\n const elapsed = this.lastCapture === 0 ? 0 : now - this.lastCapture;\n const frameDurationMs = (frame.samplesPerChannel / frame.sampleRate) * 1000;\n this.currentQueueSize += frameDurationMs - elapsed;\n\n this.lastCapture = now;\n\n if (this.timeout) {\n clearTimeout(this.timeout);\n }\n\n
|
|
1
|
+
{"version":3,"sources":["../src/audio_source.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame } from './audio_frame.js';\nimport { FfiClient } from './ffi_client.js';\nimport { FfiHandle } from './napi/native.js';\nimport type {\n AudioSourceInfo,\n CaptureAudioFrameCallback,\n CaptureAudioFrameResponse,\n ClearAudioBufferResponse,\n NewAudioSourceResponse,\n} from './proto/audio_frame_pb.js';\nimport {\n AudioSourceType,\n CaptureAudioFrameRequest,\n ClearAudioBufferRequest,\n NewAudioSourceRequest,\n} from './proto/audio_frame_pb.js';\n\nexport class AudioSource {\n /** @internal */\n info: AudioSourceInfo;\n /** @internal */\n ffiHandle: FfiHandle;\n /** @internal */\n lastCapture: number;\n /** @internal */\n currentQueueSize: number;\n /** @internal */\n release = () => {};\n promise = this.newPromise();\n /** @internal */\n timeout?: ReturnType<typeof setTimeout> = undefined;\n /** @internal */\n closed = false;\n\n sampleRate: number;\n numChannels: number;\n queueSize: number;\n\n constructor(sampleRate: number, numChannels: number, queueSize = 1000) {\n this.sampleRate = sampleRate;\n this.numChannels = numChannels;\n this.queueSize = queueSize;\n\n this.lastCapture = 0;\n this.currentQueueSize = 0;\n\n const req = new NewAudioSourceRequest({\n type: AudioSourceType.AUDIO_SOURCE_NATIVE,\n sampleRate: sampleRate,\n numChannels: numChannels,\n queueSizeMs: queueSize,\n });\n\n const res = FfiClient.instance.request<NewAudioSourceResponse>({\n message: {\n case: 'newAudioSource',\n value: req,\n },\n });\n\n this.info = res.source!.info!;\n this.ffiHandle = new FfiHandle(res.source!.handle!.id!);\n }\n\n get queuedDuration(): number {\n return Math.max(\n this.currentQueueSize - Number(process.hrtime.bigint() / BigInt(1000000)) + this.lastCapture,\n 0,\n );\n }\n\n clearQueue() {\n const req = new ClearAudioBufferRequest({\n sourceHandle: this.ffiHandle.handle,\n });\n\n FfiClient.instance.request<ClearAudioBufferResponse>({\n message: {\n case: 'clearAudioBuffer',\n value: req,\n },\n });\n\n this.release();\n }\n\n /** @internal */\n async newPromise() {\n return new Promise<void>((resolve) => {\n this.release = resolve;\n });\n }\n\n async waitForPlayout() {\n return this.promise.then(() => {\n this.lastCapture = 0;\n this.currentQueueSize = 0;\n this.promise = this.newPromise();\n this.timeout = undefined;\n });\n }\n\n async captureFrame(frame: AudioFrame) {\n if (this.closed) {\n throw new Error('AudioSource is closed');\n }\n\n if (frame.samplesPerChannel === 0) {\n return;\n }\n\n const now = Number(process.hrtime.bigint() / BigInt(1000000));\n const elapsed = this.lastCapture === 0 ? 0 : now - this.lastCapture;\n const frameDurationMs = (frame.samplesPerChannel / frame.sampleRate) * 1000;\n this.currentQueueSize += frameDurationMs - elapsed;\n\n this.lastCapture = now;\n\n if (this.timeout) {\n clearTimeout(this.timeout);\n }\n\n this.timeout = setTimeout(this.release, this.currentQueueSize);\n\n const req = new CaptureAudioFrameRequest({\n sourceHandle: this.ffiHandle.handle,\n buffer: frame.protoInfo(),\n });\n\n const res = FfiClient.instance.request<CaptureAudioFrameResponse>({\n message: { case: 'captureAudioFrame', value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<CaptureAudioFrameCallback>((ev) => {\n return ev.message.case == 'captureAudioFrame' && ev.message.value.asyncId == res.asyncId;\n });\n\n if (cb.error) {\n throw new Error(cb.error);\n }\n }\n\n async close() {\n this.ffiHandle.dispose();\n this.closed = true;\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audio_source.d.ts","sourceRoot":"","sources":["../src/audio_source.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EACV,eAAe,EAKhB,MAAM,2BAA2B,CAAC;AAQnC,qBAAa,WAAW;IACtB,gBAAgB;IAChB,IAAI,EAAE,eAAe,CAAC;IACtB,gBAAgB;IAChB,SAAS,EAAE,SAAS,CAAC;IACrB,gBAAgB;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB;IAChB,OAAO,aAAY;IACnB,OAAO,gBAAqB;IAC5B,gBAAgB;IAChB,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAa;IACpD,gBAAgB;IAChB,MAAM,UAAS;IAEf,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;gBAEN,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,SAAO;IA0BrE,IAAI,cAAc,IAAI,MAAM,CAK3B;IAED,UAAU;IAeV,gBAAgB;IACV,UAAU;IAMV,cAAc;
|
|
1
|
+
{"version":3,"file":"audio_source.d.ts","sourceRoot":"","sources":["../src/audio_source.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EACV,eAAe,EAKhB,MAAM,2BAA2B,CAAC;AAQnC,qBAAa,WAAW;IACtB,gBAAgB;IAChB,IAAI,EAAE,eAAe,CAAC;IACtB,gBAAgB;IAChB,SAAS,EAAE,SAAS,CAAC;IACrB,gBAAgB;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB;IAChB,OAAO,aAAY;IACnB,OAAO,gBAAqB;IAC5B,gBAAgB;IAChB,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAa;IACpD,gBAAgB;IAChB,MAAM,UAAS;IAEf,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;gBAEN,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,SAAO;IA0BrE,IAAI,cAAc,IAAI,MAAM,CAK3B;IAED,UAAU;IAeV,gBAAgB;IACV,UAAU;IAMV,cAAc;IASd,YAAY,CAAC,KAAK,EAAE,UAAU;IAwC9B,KAAK;CAIZ"}
|
package/dist/audio_source.js
CHANGED
|
@@ -65,12 +65,16 @@ class AudioSource {
|
|
|
65
65
|
this.lastCapture = 0;
|
|
66
66
|
this.currentQueueSize = 0;
|
|
67
67
|
this.promise = this.newPromise();
|
|
68
|
+
this.timeout = void 0;
|
|
68
69
|
});
|
|
69
70
|
}
|
|
70
71
|
async captureFrame(frame) {
|
|
71
72
|
if (this.closed) {
|
|
72
73
|
throw new Error("AudioSource is closed");
|
|
73
74
|
}
|
|
75
|
+
if (frame.samplesPerChannel === 0) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
74
78
|
const now = Number(process.hrtime.bigint() / BigInt(1e6));
|
|
75
79
|
const elapsed = this.lastCapture === 0 ? 0 : now - this.lastCapture;
|
|
76
80
|
const frameDurationMs = frame.samplesPerChannel / frame.sampleRate * 1e3;
|
|
@@ -79,7 +83,7 @@ class AudioSource {
|
|
|
79
83
|
if (this.timeout) {
|
|
80
84
|
clearTimeout(this.timeout);
|
|
81
85
|
}
|
|
82
|
-
this.timeout = setTimeout(this.release, this.currentQueueSize
|
|
86
|
+
this.timeout = setTimeout(this.release, this.currentQueueSize);
|
|
83
87
|
const req = new CaptureAudioFrameRequest({
|
|
84
88
|
sourceHandle: this.ffiHandle.handle,
|
|
85
89
|
buffer: frame.protoInfo()
|
package/dist/audio_source.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/audio_source.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame } from './audio_frame.js';\nimport { FfiClient } from './ffi_client.js';\nimport { FfiHandle } from './napi/native.js';\nimport type {\n AudioSourceInfo,\n CaptureAudioFrameCallback,\n CaptureAudioFrameResponse,\n ClearAudioBufferResponse,\n NewAudioSourceResponse,\n} from './proto/audio_frame_pb.js';\nimport {\n AudioSourceType,\n CaptureAudioFrameRequest,\n ClearAudioBufferRequest,\n NewAudioSourceRequest,\n} from './proto/audio_frame_pb.js';\n\nexport class AudioSource {\n /** @internal */\n info: AudioSourceInfo;\n /** @internal */\n ffiHandle: FfiHandle;\n /** @internal */\n lastCapture: number;\n /** @internal */\n currentQueueSize: number;\n /** @internal */\n release = () => {};\n promise = this.newPromise();\n /** @internal */\n timeout?: ReturnType<typeof setTimeout> = undefined;\n /** @internal */\n closed = false;\n\n sampleRate: number;\n numChannels: number;\n queueSize: number;\n\n constructor(sampleRate: number, numChannels: number, queueSize = 1000) {\n this.sampleRate = sampleRate;\n this.numChannels = numChannels;\n this.queueSize = queueSize;\n\n this.lastCapture = 0;\n this.currentQueueSize = 0;\n\n const req = new NewAudioSourceRequest({\n type: AudioSourceType.AUDIO_SOURCE_NATIVE,\n sampleRate: sampleRate,\n numChannels: numChannels,\n queueSizeMs: queueSize,\n });\n\n const res = FfiClient.instance.request<NewAudioSourceResponse>({\n message: {\n case: 'newAudioSource',\n value: req,\n },\n });\n\n this.info = res.source!.info!;\n this.ffiHandle = new FfiHandle(res.source!.handle!.id!);\n }\n\n get queuedDuration(): number {\n return Math.max(\n this.currentQueueSize - Number(process.hrtime.bigint() / BigInt(1000000)) + this.lastCapture,\n 0,\n );\n }\n\n clearQueue() {\n const req = new ClearAudioBufferRequest({\n sourceHandle: this.ffiHandle.handle,\n });\n\n FfiClient.instance.request<ClearAudioBufferResponse>({\n message: {\n case: 'clearAudioBuffer',\n value: req,\n },\n });\n\n this.release();\n }\n\n /** @internal */\n async newPromise() {\n return new Promise<void>((resolve) => {\n this.release = resolve;\n });\n }\n\n async waitForPlayout() {\n return this.promise.then(() => {\n this.lastCapture = 0;\n this.currentQueueSize = 0;\n this.promise = this.newPromise();\n });\n }\n\n async captureFrame(frame: AudioFrame) {\n if (this.closed) {\n throw new Error('AudioSource is closed');\n }\n const now = Number(process.hrtime.bigint() / BigInt(1000000));\n const elapsed = this.lastCapture === 0 ? 0 : now - this.lastCapture;\n const frameDurationMs = (frame.samplesPerChannel / frame.sampleRate) * 1000;\n this.currentQueueSize += frameDurationMs - elapsed;\n\n this.lastCapture = now;\n\n if (this.timeout) {\n clearTimeout(this.timeout);\n }\n\n
|
|
1
|
+
{"version":3,"sources":["../src/audio_source.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame } from './audio_frame.js';\nimport { FfiClient } from './ffi_client.js';\nimport { FfiHandle } from './napi/native.js';\nimport type {\n AudioSourceInfo,\n CaptureAudioFrameCallback,\n CaptureAudioFrameResponse,\n ClearAudioBufferResponse,\n NewAudioSourceResponse,\n} from './proto/audio_frame_pb.js';\nimport {\n AudioSourceType,\n CaptureAudioFrameRequest,\n ClearAudioBufferRequest,\n NewAudioSourceRequest,\n} from './proto/audio_frame_pb.js';\n\nexport class AudioSource {\n /** @internal */\n info: AudioSourceInfo;\n /** @internal */\n ffiHandle: FfiHandle;\n /** @internal */\n lastCapture: number;\n /** @internal */\n currentQueueSize: number;\n /** @internal */\n release = () => {};\n promise = this.newPromise();\n /** @internal */\n timeout?: ReturnType<typeof setTimeout> = undefined;\n /** @internal */\n closed = false;\n\n sampleRate: number;\n numChannels: number;\n queueSize: number;\n\n constructor(sampleRate: number, numChannels: number, queueSize = 1000) {\n this.sampleRate = sampleRate;\n this.numChannels = numChannels;\n this.queueSize = queueSize;\n\n this.lastCapture = 0;\n this.currentQueueSize = 0;\n\n const req = new NewAudioSourceRequest({\n type: AudioSourceType.AUDIO_SOURCE_NATIVE,\n sampleRate: sampleRate,\n numChannels: numChannels,\n queueSizeMs: queueSize,\n });\n\n const res = FfiClient.instance.request<NewAudioSourceResponse>({\n message: {\n case: 'newAudioSource',\n value: req,\n },\n });\n\n this.info = res.source!.info!;\n this.ffiHandle = new FfiHandle(res.source!.handle!.id!);\n }\n\n get queuedDuration(): number {\n return Math.max(\n this.currentQueueSize - Number(process.hrtime.bigint() / BigInt(1000000)) + this.lastCapture,\n 0,\n );\n }\n\n clearQueue() {\n const req = new ClearAudioBufferRequest({\n sourceHandle: this.ffiHandle.handle,\n });\n\n FfiClient.instance.request<ClearAudioBufferResponse>({\n message: {\n case: 'clearAudioBuffer',\n value: req,\n },\n });\n\n this.release();\n }\n\n /** @internal */\n async newPromise() {\n return new Promise<void>((resolve) => {\n this.release = resolve;\n });\n }\n\n async waitForPlayout() {\n return this.promise.then(() => {\n this.lastCapture = 0;\n this.currentQueueSize = 0;\n this.promise = this.newPromise();\n this.timeout = undefined;\n });\n }\n\n async captureFrame(frame: AudioFrame) {\n if (this.closed) {\n throw new Error('AudioSource is closed');\n }\n\n if (frame.samplesPerChannel === 0) {\n return;\n }\n\n const now = Number(process.hrtime.bigint() / BigInt(1000000));\n const elapsed = this.lastCapture === 0 ? 0 : now - this.lastCapture;\n const frameDurationMs = (frame.samplesPerChannel / frame.sampleRate) * 1000;\n this.currentQueueSize += frameDurationMs - elapsed;\n\n this.lastCapture = now;\n\n if (this.timeout) {\n clearTimeout(this.timeout);\n }\n\n this.timeout = setTimeout(this.release, this.currentQueueSize);\n\n const req = new CaptureAudioFrameRequest({\n sourceHandle: this.ffiHandle.handle,\n buffer: frame.protoInfo(),\n });\n\n const res = FfiClient.instance.request<CaptureAudioFrameResponse>({\n message: { case: 'captureAudioFrame', value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<CaptureAudioFrameCallback>((ev) => {\n return ev.message.case == 'captureAudioFrame' && ev.message.value.asyncId == res.asyncId;\n });\n\n if (cb.error) {\n throw new Error(cb.error);\n }\n }\n\n async close() {\n this.ffiHandle.dispose();\n this.closed = true;\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/audio_stream.cjs
CHANGED
|
@@ -21,19 +21,16 @@ __export(audio_stream_exports, {
|
|
|
21
21
|
AudioStream: () => AudioStream
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(audio_stream_exports);
|
|
24
|
-
var
|
|
24
|
+
var import_web = require("node:stream/web");
|
|
25
25
|
var import_audio_frame = require("./audio_frame.cjs");
|
|
26
26
|
var import_ffi_client = require("./ffi_client.cjs");
|
|
27
27
|
var import_audio_frame_pb = require("./proto/audio_frame_pb.cjs");
|
|
28
|
-
class
|
|
28
|
+
class AudioStreamSource {
|
|
29
29
|
constructor(track, sampleRateOrOptions, numChannels) {
|
|
30
|
-
/** @internal */
|
|
31
|
-
this.eventQueue = [];
|
|
32
|
-
/** @internal */
|
|
33
|
-
this.queueResolve = null;
|
|
34
|
-
/** @internal */
|
|
35
|
-
this.mutex = new import_mutex.Mutex();
|
|
36
30
|
this.onEvent = (ev) => {
|
|
31
|
+
if (!this.controller) {
|
|
32
|
+
throw new Error("Stream controller not initialized");
|
|
33
|
+
}
|
|
37
34
|
if (ev.message.case != "audioStreamEvent" || ev.message.value.streamHandle != this.ffiHandle.handle) {
|
|
38
35
|
return;
|
|
39
36
|
}
|
|
@@ -41,19 +38,14 @@ class AudioStream {
|
|
|
41
38
|
switch (streamEvent.case) {
|
|
42
39
|
case "frameReceived":
|
|
43
40
|
const frame = import_audio_frame.AudioFrame.fromOwnedInfo(streamEvent.value.frame);
|
|
44
|
-
|
|
45
|
-
this.queueResolve({ done: false, value: frame });
|
|
46
|
-
this.queueResolve = null;
|
|
47
|
-
} else {
|
|
48
|
-
this.eventQueue.push(frame);
|
|
49
|
-
}
|
|
41
|
+
this.controller.enqueue(frame);
|
|
50
42
|
break;
|
|
51
43
|
case "eos":
|
|
52
44
|
import_ffi_client.FfiClient.instance.off(import_ffi_client.FfiClientEvent.FfiEvent, this.onEvent);
|
|
45
|
+
this.controller.close();
|
|
53
46
|
break;
|
|
54
47
|
}
|
|
55
48
|
};
|
|
56
|
-
this.track = track;
|
|
57
49
|
if (sampleRateOrOptions !== void 0 && typeof sampleRateOrOptions !== "number") {
|
|
58
50
|
this.sampleRate = sampleRateOrOptions.sampleRate ?? 48e3;
|
|
59
51
|
this.numChannels = sampleRateOrOptions.numChannels ?? 1;
|
|
@@ -78,33 +70,20 @@ class AudioStream {
|
|
|
78
70
|
value: req
|
|
79
71
|
}
|
|
80
72
|
});
|
|
81
|
-
this.info = res.stream.info;
|
|
82
73
|
this.ffiHandle = new import_ffi_client.FfiHandle(res.stream.handle.id);
|
|
83
74
|
import_ffi_client.FfiClient.instance.on(import_ffi_client.FfiClientEvent.FfiEvent, this.onEvent);
|
|
84
75
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (this.eventQueue.length > 0) {
|
|
88
|
-
unlock();
|
|
89
|
-
const value = this.eventQueue.shift();
|
|
90
|
-
if (value) {
|
|
91
|
-
return { done: false, value };
|
|
92
|
-
} else {
|
|
93
|
-
return { done: true, value: void 0 };
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
const promise = new Promise(
|
|
97
|
-
(resolve) => this.queueResolve = resolve
|
|
98
|
-
);
|
|
99
|
-
unlock();
|
|
100
|
-
return promise;
|
|
76
|
+
start(controller) {
|
|
77
|
+
this.controller = controller;
|
|
101
78
|
}
|
|
102
|
-
|
|
103
|
-
|
|
79
|
+
cancel() {
|
|
80
|
+
import_ffi_client.FfiClient.instance.off(import_ffi_client.FfiClientEvent.FfiEvent, this.onEvent);
|
|
104
81
|
this.ffiHandle.dispose();
|
|
105
82
|
}
|
|
106
|
-
|
|
107
|
-
|
|
83
|
+
}
|
|
84
|
+
class AudioStream extends import_web.ReadableStream {
|
|
85
|
+
constructor(track, sampleRateOrOptions, numChannels) {
|
|
86
|
+
super(new AudioStreamSource(track, sampleRateOrOptions, numChannels));
|
|
108
87
|
}
|
|
109
88
|
}
|
|
110
89
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/audio_stream.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport {
|
|
1
|
+
{"version":3,"sources":["../src/audio_stream.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { ReadableStream, type UnderlyingSource } from 'node:stream/web';\nimport { AudioFrame } from './audio_frame.js';\nimport type { FfiEvent } from './ffi_client.js';\nimport { FfiClient, FfiClientEvent, FfiHandle } from './ffi_client.js';\nimport type { NewAudioStreamResponse } from './proto/audio_frame_pb.js';\nimport { AudioStreamType, NewAudioStreamRequest } from './proto/audio_frame_pb.js';\nimport type { Track } from './track.js';\n\nexport interface AudioStreamOptions {\n noiseCancellation?: NoiseCancellationOptions;\n sampleRate?: number;\n numChannels?: number;\n}\n\nexport interface NoiseCancellationOptions {\n moduleId: string;\n options: Record<string, any>;\n}\n\nclass AudioStreamSource implements UnderlyingSource<AudioFrame> {\n private controller?: ReadableStreamDefaultController<AudioFrame>;\n private ffiHandle: FfiHandle;\n private sampleRate: number;\n private numChannels: number;\n private ncOptions?: NoiseCancellationOptions;\n\n constructor(\n track: Track,\n sampleRateOrOptions?: number | AudioStreamOptions,\n numChannels?: number,\n ) {\n if (sampleRateOrOptions !== undefined && typeof sampleRateOrOptions !== 'number') {\n this.sampleRate = sampleRateOrOptions.sampleRate ?? 48000;\n this.numChannels = sampleRateOrOptions.numChannels ?? 1;\n this.ncOptions = sampleRateOrOptions.noiseCancellation;\n } else {\n this.sampleRate = (sampleRateOrOptions as number) ?? 48000;\n this.numChannels = numChannels ?? 1;\n }\n\n const req = new NewAudioStreamRequest({\n type: AudioStreamType.AUDIO_STREAM_NATIVE,\n trackHandle: track.ffi_handle.handle,\n sampleRate: this.sampleRate,\n numChannels: this.numChannels,\n ...(this.ncOptions\n ? {\n audioFilterModuleId: this.ncOptions.moduleId,\n audioFilterOptions: JSON.stringify(this.ncOptions.options),\n }\n : {}),\n });\n\n const res = FfiClient.instance.request<NewAudioStreamResponse>({\n message: {\n case: 'newAudioStream',\n value: req,\n },\n });\n\n this.ffiHandle = new FfiHandle(res.stream!.handle!.id!);\n\n FfiClient.instance.on(FfiClientEvent.FfiEvent, this.onEvent);\n }\n\n private onEvent = (ev: FfiEvent) => {\n if (!this.controller) {\n throw new Error('Stream controller not initialized');\n }\n\n if (\n ev.message.case != 'audioStreamEvent' ||\n ev.message.value.streamHandle != this.ffiHandle.handle\n ) {\n return;\n }\n\n const streamEvent = ev.message.value.message;\n switch (streamEvent.case) {\n case 'frameReceived':\n const frame = AudioFrame.fromOwnedInfo(streamEvent.value.frame!);\n this.controller.enqueue(frame);\n break;\n case 'eos':\n FfiClient.instance.off(FfiClientEvent.FfiEvent, this.onEvent);\n this.controller.close();\n break;\n }\n };\n\n start(controller: ReadableStreamDefaultController<AudioFrame>) {\n this.controller = controller;\n }\n\n cancel() {\n FfiClient.instance.off(FfiClientEvent.FfiEvent, this.onEvent);\n this.ffiHandle.dispose();\n }\n}\n\nexport class AudioStream extends ReadableStream<AudioFrame> {\n constructor(track: Track);\n constructor(track: Track, sampleRate: number);\n constructor(track: Track, sampleRate: number, numChannels: number);\n constructor(track: Track, options: AudioStreamOptions);\n constructor(\n track: Track,\n sampleRateOrOptions?: number | AudioStreamOptions,\n numChannels?: number,\n ) {\n super(new AudioStreamSource(track, sampleRateOrOptions, numChannels));\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,iBAAsD;AACtD,yBAA2B;AAE3B,wBAAqD;AAErD,4BAAuD;AAcvD,MAAM,kBAA0D;AAAA,EAO9D,YACE,OACA,qBACA,aACA;AAmCF,SAAQ,UAAU,CAAC,OAAiB;AAClC,UAAI,CAAC,KAAK,YAAY;AACpB,cAAM,IAAI,MAAM,mCAAmC;AAAA,MACrD;AAEA,UACE,GAAG,QAAQ,QAAQ,sBACnB,GAAG,QAAQ,MAAM,gBAAgB,KAAK,UAAU,QAChD;AACA;AAAA,MACF;AAEA,YAAM,cAAc,GAAG,QAAQ,MAAM;AACrC,cAAQ,YAAY,MAAM;AAAA,QACxB,KAAK;AACH,gBAAM,QAAQ,8BAAW,cAAc,YAAY,MAAM,KAAM;AAC/D,eAAK,WAAW,QAAQ,KAAK;AAC7B;AAAA,QACF,KAAK;AACH,sCAAU,SAAS,IAAI,iCAAe,UAAU,KAAK,OAAO;AAC5D,eAAK,WAAW,MAAM;AACtB;AAAA,MACJ;AAAA,IACF;AAzDE,QAAI,wBAAwB,UAAa,OAAO,wBAAwB,UAAU;AAChF,WAAK,aAAa,oBAAoB,cAAc;AACpD,WAAK,cAAc,oBAAoB,eAAe;AACtD,WAAK,YAAY,oBAAoB;AAAA,IACvC,OAAO;AACL,WAAK,aAAc,uBAAkC;AACrD,WAAK,cAAc,eAAe;AAAA,IACpC;AAEA,UAAM,MAAM,IAAI,4CAAsB;AAAA,MACpC,MAAM,sCAAgB;AAAA,MACtB,aAAa,MAAM,WAAW;AAAA,MAC9B,YAAY,KAAK;AAAA,MACjB,aAAa,KAAK;AAAA,MAClB,GAAI,KAAK,YACL;AAAA,QACE,qBAAqB,KAAK,UAAU;AAAA,QACpC,oBAAoB,KAAK,UAAU,KAAK,UAAU,OAAO;AAAA,MAC3D,IACA,CAAC;AAAA,IACP,CAAC;AAED,UAAM,MAAM,4BAAU,SAAS,QAAgC;AAAA,MAC7D,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,SAAK,YAAY,IAAI,4BAAU,IAAI,OAAQ,OAAQ,EAAG;AAEtD,gCAAU,SAAS,GAAG,iCAAe,UAAU,KAAK,OAAO;AAAA,EAC7D;AAAA,EA2BA,MAAM,YAAyD;AAC7D,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,SAAS;AACP,gCAAU,SAAS,IAAI,iCAAe,UAAU,KAAK,OAAO;AAC5D,SAAK,UAAU,QAAQ;AAAA,EACzB;AACF;AAEO,MAAM,oBAAoB,0BAA2B;AAAA,EAK1D,YACE,OACA,qBACA,aACA;AACA,UAAM,IAAI,kBAAkB,OAAO,qBAAqB,WAAW,CAAC;AAAA,EACtE;AACF;","names":[]}
|
package/dist/audio_stream.d.cts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ReadableStream } from 'node:stream/web';
|
|
2
2
|
import { AudioFrame } from './audio_frame.cjs';
|
|
3
|
-
import { FfiHandle } from './napi/native.d.cjs';
|
|
4
|
-
import { AudioStreamInfo } from './proto/audio_frame_pb.cjs';
|
|
5
3
|
import { Track } from './track.cjs';
|
|
4
|
+
import './proto/audio_frame_pb.cjs';
|
|
6
5
|
import '@bufbuild/protobuf';
|
|
7
6
|
import './proto/track_pb.cjs';
|
|
8
7
|
import './proto/stats_pb.cjs';
|
|
9
8
|
import './proto/e2ee_pb.cjs';
|
|
10
9
|
import './proto/handle_pb.cjs';
|
|
11
10
|
import './audio_source.cjs';
|
|
11
|
+
import './napi/native.d.cjs';
|
|
12
12
|
import './video_source.cjs';
|
|
13
13
|
import './proto/video_frame_pb.cjs';
|
|
14
14
|
import './video_frame.cjs';
|
|
@@ -22,29 +22,11 @@ interface NoiseCancellationOptions {
|
|
|
22
22
|
moduleId: string;
|
|
23
23
|
options: Record<string, any>;
|
|
24
24
|
}
|
|
25
|
-
declare class AudioStream
|
|
26
|
-
/** @internal */
|
|
27
|
-
info: AudioStreamInfo;
|
|
28
|
-
/** @internal */
|
|
29
|
-
ffiHandle: FfiHandle;
|
|
30
|
-
/** @internal */
|
|
31
|
-
eventQueue: (AudioFrame | null)[];
|
|
32
|
-
/** @internal */
|
|
33
|
-
queueResolve: ((value: IteratorResult<AudioFrame>) => void) | null;
|
|
34
|
-
/** @internal */
|
|
35
|
-
mutex: Mutex;
|
|
36
|
-
track: Track;
|
|
37
|
-
sampleRate: number;
|
|
38
|
-
numChannels: number;
|
|
39
|
-
ncOptions?: NoiseCancellationOptions;
|
|
25
|
+
declare class AudioStream extends ReadableStream<AudioFrame> {
|
|
40
26
|
constructor(track: Track);
|
|
41
27
|
constructor(track: Track, sampleRate: number);
|
|
42
28
|
constructor(track: Track, sampleRate: number, numChannels: number);
|
|
43
29
|
constructor(track: Track, options: AudioStreamOptions);
|
|
44
|
-
private onEvent;
|
|
45
|
-
next(): Promise<IteratorResult<AudioFrame>>;
|
|
46
|
-
close(): void;
|
|
47
|
-
[Symbol.asyncIterator](): AudioStream;
|
|
48
30
|
}
|
|
49
31
|
|
|
50
32
|
export { AudioStream, type AudioStreamOptions, type NoiseCancellationOptions };
|
package/dist/audio_stream.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ReadableStream } from 'node:stream/web';
|
|
2
2
|
import { AudioFrame } from './audio_frame.js';
|
|
3
|
-
import { FfiHandle } from './napi/native.d.js';
|
|
4
|
-
import { AudioStreamInfo } from './proto/audio_frame_pb.js';
|
|
5
3
|
import { Track } from './track.js';
|
|
4
|
+
import './proto/audio_frame_pb.js';
|
|
6
5
|
import '@bufbuild/protobuf';
|
|
7
6
|
import './proto/track_pb.js';
|
|
8
7
|
import './proto/stats_pb.js';
|
|
9
8
|
import './proto/e2ee_pb.js';
|
|
10
9
|
import './proto/handle_pb.js';
|
|
11
10
|
import './audio_source.js';
|
|
11
|
+
import './napi/native.d.js';
|
|
12
12
|
import './video_source.js';
|
|
13
13
|
import './proto/video_frame_pb.js';
|
|
14
14
|
import './video_frame.js';
|
|
@@ -22,29 +22,11 @@ interface NoiseCancellationOptions {
|
|
|
22
22
|
moduleId: string;
|
|
23
23
|
options: Record<string, any>;
|
|
24
24
|
}
|
|
25
|
-
declare class AudioStream
|
|
26
|
-
/** @internal */
|
|
27
|
-
info: AudioStreamInfo;
|
|
28
|
-
/** @internal */
|
|
29
|
-
ffiHandle: FfiHandle;
|
|
30
|
-
/** @internal */
|
|
31
|
-
eventQueue: (AudioFrame | null)[];
|
|
32
|
-
/** @internal */
|
|
33
|
-
queueResolve: ((value: IteratorResult<AudioFrame>) => void) | null;
|
|
34
|
-
/** @internal */
|
|
35
|
-
mutex: Mutex;
|
|
36
|
-
track: Track;
|
|
37
|
-
sampleRate: number;
|
|
38
|
-
numChannels: number;
|
|
39
|
-
ncOptions?: NoiseCancellationOptions;
|
|
25
|
+
declare class AudioStream extends ReadableStream<AudioFrame> {
|
|
40
26
|
constructor(track: Track);
|
|
41
27
|
constructor(track: Track, sampleRate: number);
|
|
42
28
|
constructor(track: Track, sampleRate: number, numChannels: number);
|
|
43
29
|
constructor(track: Track, options: AudioStreamOptions);
|
|
44
|
-
private onEvent;
|
|
45
|
-
next(): Promise<IteratorResult<AudioFrame>>;
|
|
46
|
-
close(): void;
|
|
47
|
-
[Symbol.asyncIterator](): AudioStream;
|
|
48
30
|
}
|
|
49
31
|
|
|
50
32
|
export { AudioStream, type AudioStreamOptions, type NoiseCancellationOptions };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audio_stream.d.ts","sourceRoot":"","sources":["../src/audio_stream.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"audio_stream.d.ts","sourceRoot":"","sources":["../src/audio_stream.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAyB,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAK9C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,WAAW,kBAAkB;IACjC,iBAAiB,CAAC,EAAE,wBAAwB,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B;AAmFD,qBAAa,WAAY,SAAQ,cAAc,CAAC,UAAU,CAAC;gBAC7C,KAAK,EAAE,KAAK;gBACZ,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM;gBAChC,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;gBACrD,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB;CAQtD"}
|
package/dist/audio_stream.js
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ReadableStream } from "node:stream/web";
|
|
2
2
|
import { AudioFrame } from "./audio_frame.js";
|
|
3
3
|
import { FfiClient, FfiClientEvent, FfiHandle } from "./ffi_client.js";
|
|
4
4
|
import { AudioStreamType, NewAudioStreamRequest } from "./proto/audio_frame_pb.js";
|
|
5
|
-
class
|
|
5
|
+
class AudioStreamSource {
|
|
6
6
|
constructor(track, sampleRateOrOptions, numChannels) {
|
|
7
|
-
/** @internal */
|
|
8
|
-
this.eventQueue = [];
|
|
9
|
-
/** @internal */
|
|
10
|
-
this.queueResolve = null;
|
|
11
|
-
/** @internal */
|
|
12
|
-
this.mutex = new Mutex();
|
|
13
7
|
this.onEvent = (ev) => {
|
|
8
|
+
if (!this.controller) {
|
|
9
|
+
throw new Error("Stream controller not initialized");
|
|
10
|
+
}
|
|
14
11
|
if (ev.message.case != "audioStreamEvent" || ev.message.value.streamHandle != this.ffiHandle.handle) {
|
|
15
12
|
return;
|
|
16
13
|
}
|
|
@@ -18,19 +15,14 @@ class AudioStream {
|
|
|
18
15
|
switch (streamEvent.case) {
|
|
19
16
|
case "frameReceived":
|
|
20
17
|
const frame = AudioFrame.fromOwnedInfo(streamEvent.value.frame);
|
|
21
|
-
|
|
22
|
-
this.queueResolve({ done: false, value: frame });
|
|
23
|
-
this.queueResolve = null;
|
|
24
|
-
} else {
|
|
25
|
-
this.eventQueue.push(frame);
|
|
26
|
-
}
|
|
18
|
+
this.controller.enqueue(frame);
|
|
27
19
|
break;
|
|
28
20
|
case "eos":
|
|
29
21
|
FfiClient.instance.off(FfiClientEvent.FfiEvent, this.onEvent);
|
|
22
|
+
this.controller.close();
|
|
30
23
|
break;
|
|
31
24
|
}
|
|
32
25
|
};
|
|
33
|
-
this.track = track;
|
|
34
26
|
if (sampleRateOrOptions !== void 0 && typeof sampleRateOrOptions !== "number") {
|
|
35
27
|
this.sampleRate = sampleRateOrOptions.sampleRate ?? 48e3;
|
|
36
28
|
this.numChannels = sampleRateOrOptions.numChannels ?? 1;
|
|
@@ -55,33 +47,20 @@ class AudioStream {
|
|
|
55
47
|
value: req
|
|
56
48
|
}
|
|
57
49
|
});
|
|
58
|
-
this.info = res.stream.info;
|
|
59
50
|
this.ffiHandle = new FfiHandle(res.stream.handle.id);
|
|
60
51
|
FfiClient.instance.on(FfiClientEvent.FfiEvent, this.onEvent);
|
|
61
52
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (this.eventQueue.length > 0) {
|
|
65
|
-
unlock();
|
|
66
|
-
const value = this.eventQueue.shift();
|
|
67
|
-
if (value) {
|
|
68
|
-
return { done: false, value };
|
|
69
|
-
} else {
|
|
70
|
-
return { done: true, value: void 0 };
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
const promise = new Promise(
|
|
74
|
-
(resolve) => this.queueResolve = resolve
|
|
75
|
-
);
|
|
76
|
-
unlock();
|
|
77
|
-
return promise;
|
|
53
|
+
start(controller) {
|
|
54
|
+
this.controller = controller;
|
|
78
55
|
}
|
|
79
|
-
|
|
80
|
-
|
|
56
|
+
cancel() {
|
|
57
|
+
FfiClient.instance.off(FfiClientEvent.FfiEvent, this.onEvent);
|
|
81
58
|
this.ffiHandle.dispose();
|
|
82
59
|
}
|
|
83
|
-
|
|
84
|
-
|
|
60
|
+
}
|
|
61
|
+
class AudioStream extends ReadableStream {
|
|
62
|
+
constructor(track, sampleRateOrOptions, numChannels) {
|
|
63
|
+
super(new AudioStreamSource(track, sampleRateOrOptions, numChannels));
|
|
85
64
|
}
|
|
86
65
|
}
|
|
87
66
|
export {
|
package/dist/audio_stream.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/audio_stream.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport {
|
|
1
|
+
{"version":3,"sources":["../src/audio_stream.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { ReadableStream, type UnderlyingSource } from 'node:stream/web';\nimport { AudioFrame } from './audio_frame.js';\nimport type { FfiEvent } from './ffi_client.js';\nimport { FfiClient, FfiClientEvent, FfiHandle } from './ffi_client.js';\nimport type { NewAudioStreamResponse } from './proto/audio_frame_pb.js';\nimport { AudioStreamType, NewAudioStreamRequest } from './proto/audio_frame_pb.js';\nimport type { Track } from './track.js';\n\nexport interface AudioStreamOptions {\n noiseCancellation?: NoiseCancellationOptions;\n sampleRate?: number;\n numChannels?: number;\n}\n\nexport interface NoiseCancellationOptions {\n moduleId: string;\n options: Record<string, any>;\n}\n\nclass AudioStreamSource implements UnderlyingSource<AudioFrame> {\n private controller?: ReadableStreamDefaultController<AudioFrame>;\n private ffiHandle: FfiHandle;\n private sampleRate: number;\n private numChannels: number;\n private ncOptions?: NoiseCancellationOptions;\n\n constructor(\n track: Track,\n sampleRateOrOptions?: number | AudioStreamOptions,\n numChannels?: number,\n ) {\n if (sampleRateOrOptions !== undefined && typeof sampleRateOrOptions !== 'number') {\n this.sampleRate = sampleRateOrOptions.sampleRate ?? 48000;\n this.numChannels = sampleRateOrOptions.numChannels ?? 1;\n this.ncOptions = sampleRateOrOptions.noiseCancellation;\n } else {\n this.sampleRate = (sampleRateOrOptions as number) ?? 48000;\n this.numChannels = numChannels ?? 1;\n }\n\n const req = new NewAudioStreamRequest({\n type: AudioStreamType.AUDIO_STREAM_NATIVE,\n trackHandle: track.ffi_handle.handle,\n sampleRate: this.sampleRate,\n numChannels: this.numChannels,\n ...(this.ncOptions\n ? {\n audioFilterModuleId: this.ncOptions.moduleId,\n audioFilterOptions: JSON.stringify(this.ncOptions.options),\n }\n : {}),\n });\n\n const res = FfiClient.instance.request<NewAudioStreamResponse>({\n message: {\n case: 'newAudioStream',\n value: req,\n },\n });\n\n this.ffiHandle = new FfiHandle(res.stream!.handle!.id!);\n\n FfiClient.instance.on(FfiClientEvent.FfiEvent, this.onEvent);\n }\n\n private onEvent = (ev: FfiEvent) => {\n if (!this.controller) {\n throw new Error('Stream controller not initialized');\n }\n\n if (\n ev.message.case != 'audioStreamEvent' ||\n ev.message.value.streamHandle != this.ffiHandle.handle\n ) {\n return;\n }\n\n const streamEvent = ev.message.value.message;\n switch (streamEvent.case) {\n case 'frameReceived':\n const frame = AudioFrame.fromOwnedInfo(streamEvent.value.frame!);\n this.controller.enqueue(frame);\n break;\n case 'eos':\n FfiClient.instance.off(FfiClientEvent.FfiEvent, this.onEvent);\n this.controller.close();\n break;\n }\n };\n\n start(controller: ReadableStreamDefaultController<AudioFrame>) {\n this.controller = controller;\n }\n\n cancel() {\n FfiClient.instance.off(FfiClientEvent.FfiEvent, this.onEvent);\n this.ffiHandle.dispose();\n }\n}\n\nexport class AudioStream extends ReadableStream<AudioFrame> {\n constructor(track: Track);\n constructor(track: Track, sampleRate: number);\n constructor(track: Track, sampleRate: number, numChannels: number);\n constructor(track: Track, options: AudioStreamOptions);\n constructor(\n track: Track,\n sampleRateOrOptions?: number | AudioStreamOptions,\n numChannels?: number,\n ) {\n super(new AudioStreamSource(track, sampleRateOrOptions, numChannels));\n }\n}\n"],"mappings":"AAGA,SAAS,sBAA6C;AACtD,SAAS,kBAAkB;AAE3B,SAAS,WAAW,gBAAgB,iBAAiB;AAErD,SAAS,iBAAiB,6BAA6B;AAcvD,MAAM,kBAA0D;AAAA,EAO9D,YACE,OACA,qBACA,aACA;AAmCF,SAAQ,UAAU,CAAC,OAAiB;AAClC,UAAI,CAAC,KAAK,YAAY;AACpB,cAAM,IAAI,MAAM,mCAAmC;AAAA,MACrD;AAEA,UACE,GAAG,QAAQ,QAAQ,sBACnB,GAAG,QAAQ,MAAM,gBAAgB,KAAK,UAAU,QAChD;AACA;AAAA,MACF;AAEA,YAAM,cAAc,GAAG,QAAQ,MAAM;AACrC,cAAQ,YAAY,MAAM;AAAA,QACxB,KAAK;AACH,gBAAM,QAAQ,WAAW,cAAc,YAAY,MAAM,KAAM;AAC/D,eAAK,WAAW,QAAQ,KAAK;AAC7B;AAAA,QACF,KAAK;AACH,oBAAU,SAAS,IAAI,eAAe,UAAU,KAAK,OAAO;AAC5D,eAAK,WAAW,MAAM;AACtB;AAAA,MACJ;AAAA,IACF;AAzDE,QAAI,wBAAwB,UAAa,OAAO,wBAAwB,UAAU;AAChF,WAAK,aAAa,oBAAoB,cAAc;AACpD,WAAK,cAAc,oBAAoB,eAAe;AACtD,WAAK,YAAY,oBAAoB;AAAA,IACvC,OAAO;AACL,WAAK,aAAc,uBAAkC;AACrD,WAAK,cAAc,eAAe;AAAA,IACpC;AAEA,UAAM,MAAM,IAAI,sBAAsB;AAAA,MACpC,MAAM,gBAAgB;AAAA,MACtB,aAAa,MAAM,WAAW;AAAA,MAC9B,YAAY,KAAK;AAAA,MACjB,aAAa,KAAK;AAAA,MAClB,GAAI,KAAK,YACL;AAAA,QACE,qBAAqB,KAAK,UAAU;AAAA,QACpC,oBAAoB,KAAK,UAAU,KAAK,UAAU,OAAO;AAAA,MAC3D,IACA,CAAC;AAAA,IACP,CAAC;AAED,UAAM,MAAM,UAAU,SAAS,QAAgC;AAAA,MAC7D,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,SAAK,YAAY,IAAI,UAAU,IAAI,OAAQ,OAAQ,EAAG;AAEtD,cAAU,SAAS,GAAG,eAAe,UAAU,KAAK,OAAO;AAAA,EAC7D;AAAA,EA2BA,MAAM,YAAyD;AAC7D,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,SAAS;AACP,cAAU,SAAS,IAAI,eAAe,UAAU,KAAK,OAAO;AAC5D,SAAK,UAAU,QAAQ;AAAA,EACzB;AACF;AAEO,MAAM,oBAAoB,eAA2B;AAAA,EAK1D,YACE,OACA,qBACA,aACA;AACA,UAAM,IAAI,kBAAkB,OAAO,qBAAqB,WAAW,CAAC;AAAA,EACtE;AACF;","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -25,7 +25,6 @@ export { VideoFrameEvent, VideoStream } from './video_stream.cjs';
|
|
|
25
25
|
import './proto/audio_frame_pb.cjs';
|
|
26
26
|
import '@bufbuild/protobuf';
|
|
27
27
|
import './proto/handle_pb.cjs';
|
|
28
|
-
import '@livekit/mutex';
|
|
29
28
|
import 'node:stream/web';
|
|
30
29
|
import './proto/stats_pb.cjs';
|
|
31
30
|
import 'node:fs';
|
package/dist/index.d.ts
CHANGED
|
@@ -25,7 +25,6 @@ export { VideoFrameEvent, VideoStream } from './video_stream.js';
|
|
|
25
25
|
import './proto/audio_frame_pb.js';
|
|
26
26
|
import '@bufbuild/protobuf';
|
|
27
27
|
import './proto/handle_pb.js';
|
|
28
|
-
import '@livekit/mutex';
|
|
29
28
|
import 'node:stream/web';
|
|
30
29
|
import './proto/stats_pb.js';
|
|
31
30
|
import 'node:fs';
|
package/dist/room.cjs
CHANGED
|
@@ -316,6 +316,7 @@ class Room extends import_events.default {
|
|
|
316
316
|
const cb = await import_ffi_client.FfiClient.instance.waitFor((ev) => {
|
|
317
317
|
return ev.message.case == "connect" && ev.message.value.asyncId == res.asyncId;
|
|
318
318
|
});
|
|
319
|
+
import_log.log.debug("Connect callback received");
|
|
319
320
|
switch (cb.message.case) {
|
|
320
321
|
case "result":
|
|
321
322
|
this.ffiHandle = new import_ffi_client.FfiHandle(cb.message.value.room.handle.id);
|