@livekit/rtc-node 0.13.6 → 0.13.8
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_source.cjs +6 -0
- package/dist/audio_source.cjs.map +1 -1
- package/dist/audio_source.d.cts +2 -0
- package/dist/audio_source.d.ts +2 -0
- package/dist/audio_source.d.ts.map +1 -1
- package/dist/audio_source.js +6 -0
- package/dist/audio_source.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_source.cjs +6 -0
- package/dist/video_source.cjs.map +1 -1
- package/dist/video_source.d.cts +2 -0
- package/dist/video_source.d.ts +2 -0
- package/dist/video_source.d.ts.map +1 -1
- package/dist/video_source.js +6 -0
- package/dist/video_source.js.map +1 -1
- package/package.json +6 -6
- package/src/audio_source.ts +6 -0
- package/src/nodejs.rs +12 -5
- package/src/version.ts +1 -1
- package/src/video_source.ts +6 -0
package/dist/audio_source.cjs
CHANGED
|
@@ -32,6 +32,8 @@ class AudioSource {
|
|
|
32
32
|
this.promise = this.newPromise();
|
|
33
33
|
/** @internal */
|
|
34
34
|
this.timeout = void 0;
|
|
35
|
+
/** @internal */
|
|
36
|
+
this.closed = false;
|
|
35
37
|
this.sampleRate = sampleRate;
|
|
36
38
|
this.numChannels = numChannels;
|
|
37
39
|
this.queueSize = queueSize;
|
|
@@ -84,6 +86,9 @@ class AudioSource {
|
|
|
84
86
|
});
|
|
85
87
|
}
|
|
86
88
|
async captureFrame(frame) {
|
|
89
|
+
if (this.closed) {
|
|
90
|
+
throw new Error("AudioSource is closed");
|
|
91
|
+
}
|
|
87
92
|
const now = Number(process.hrtime.bigint() / BigInt(1e6));
|
|
88
93
|
const elapsed = this.lastCapture === 0 ? 0 : now - this.lastCapture;
|
|
89
94
|
const frameDurationMs = frame.samplesPerChannel / frame.sampleRate * 1e3;
|
|
@@ -109,6 +114,7 @@ class AudioSource {
|
|
|
109
114
|
}
|
|
110
115
|
async close() {
|
|
111
116
|
this.ffiHandle.dispose();
|
|
117
|
+
this.closed = true;
|
|
112
118
|
}
|
|
113
119
|
}
|
|
114
120
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -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\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 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 // remove 50ms to account for processing time\n // (e.g. using wait_for_playout for very small chunks)\n this.timeout = setTimeout(this.release, this.currentQueueSize - 50);\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 }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,wBAA0B;AAC1B,oBAA0B;AAQ1B,4BAKO;AAEA,MAAM,YAAY;AAAA,
|
|
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 // remove 50ms to account for processing time\n // (e.g. using wait_for_playout for very small chunks)\n this.timeout = setTimeout(this.release, this.currentQueueSize - 50);\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":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,wBAA0B;AAC1B,oBAA0B;AAQ1B,4BAKO;AAEA,MAAM,YAAY;AAAA,EAqBvB,YAAY,YAAoB,aAAqB,YAAY,KAAM;AAXvE;AAAA,mBAAU,MAAM;AAAA,IAAC;AACjB,mBAAU,KAAK,WAAW;AAE1B;AAAA,mBAA0C;AAE1C;AAAA,kBAAS;AAOP,SAAK,aAAa;AAClB,SAAK,cAAc;AACnB,SAAK,YAAY;AAEjB,SAAK,cAAc;AACnB,SAAK,mBAAmB;AAExB,UAAM,MAAM,IAAI,4CAAsB;AAAA,MACpC,MAAM,sCAAgB;AAAA,MACtB;AAAA,MACA;AAAA,MACA,aAAa;AAAA,IACf,CAAC;AAED,UAAM,MAAM,4BAAU,SAAS,QAAgC;AAAA,MAC7D,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,SAAK,OAAO,IAAI,OAAQ;AACxB,SAAK,YAAY,IAAI,wBAAU,IAAI,OAAQ,OAAQ,EAAG;AAAA,EACxD;AAAA,EAEA,IAAI,iBAAyB;AAC3B,WAAO,KAAK;AAAA,MACV,KAAK,mBAAmB,OAAO,QAAQ,OAAO,OAAO,IAAI,OAAO,GAAO,CAAC,IAAI,KAAK;AAAA,MACjF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aAAa;AACX,UAAM,MAAM,IAAI,8CAAwB;AAAA,MACtC,cAAc,KAAK,UAAU;AAAA,IAC/B,CAAC;AAED,gCAAU,SAAS,QAAkC;AAAA,MACnD,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA,EAGA,MAAM,aAAa;AACjB,WAAO,IAAI,QAAc,CAAC,YAAY;AACpC,WAAK,UAAU;AAAA,IACjB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,iBAAiB;AACrB,WAAO,KAAK,QAAQ,KAAK,MAAM;AAC7B,WAAK,cAAc;AACnB,WAAK,mBAAmB;AACxB,WAAK,UAAU,KAAK,WAAW;AAAA,IACjC,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,aAAa,OAAmB;AACpC,QAAI,KAAK,QAAQ;AACf,YAAM,IAAI,MAAM,uBAAuB;AAAA,IACzC;AACA,UAAM,MAAM,OAAO,QAAQ,OAAO,OAAO,IAAI,OAAO,GAAO,CAAC;AAC5D,UAAM,UAAU,KAAK,gBAAgB,IAAI,IAAI,MAAM,KAAK;AACxD,UAAM,kBAAmB,MAAM,oBAAoB,MAAM,aAAc;AACvE,SAAK,oBAAoB,kBAAkB;AAE3C,SAAK,cAAc;AAEnB,QAAI,KAAK,SAAS;AAChB,mBAAa,KAAK,OAAO;AAAA,IAC3B;AAIA,SAAK,UAAU,WAAW,KAAK,SAAS,KAAK,mBAAmB,EAAE;AAElE,UAAM,MAAM,IAAI,+CAAyB;AAAA,MACvC,cAAc,KAAK,UAAU;AAAA,MAC7B,QAAQ,MAAM,UAAU;AAAA,IAC1B,CAAC;AAED,UAAM,MAAM,4BAAU,SAAS,QAAmC;AAAA,MAChE,SAAS,EAAE,MAAM,qBAAqB,OAAO,IAAI;AAAA,IACnD,CAAC;AAED,UAAM,KAAK,MAAM,4BAAU,SAAS,QAAmC,CAAC,OAAO;AAC7E,aAAO,GAAG,QAAQ,QAAQ,uBAAuB,GAAG,QAAQ,MAAM,WAAW,IAAI;AAAA,IACnF,CAAC;AAED,QAAI,GAAG,OAAO;AACZ,YAAM,IAAI,MAAM,GAAG,KAAK;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ;AACZ,SAAK,UAAU,QAAQ;AACvB,SAAK,SAAS;AAAA,EAChB;AACF;","names":[]}
|
package/dist/audio_source.d.cts
CHANGED
package/dist/audio_source.d.ts
CHANGED
|
@@ -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;
|
|
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;IAQd,YAAY,CAAC,KAAK,EAAE,UAAU;IAqC9B,KAAK;CAIZ"}
|
package/dist/audio_source.js
CHANGED
|
@@ -14,6 +14,8 @@ class AudioSource {
|
|
|
14
14
|
this.promise = this.newPromise();
|
|
15
15
|
/** @internal */
|
|
16
16
|
this.timeout = void 0;
|
|
17
|
+
/** @internal */
|
|
18
|
+
this.closed = false;
|
|
17
19
|
this.sampleRate = sampleRate;
|
|
18
20
|
this.numChannels = numChannels;
|
|
19
21
|
this.queueSize = queueSize;
|
|
@@ -66,6 +68,9 @@ class AudioSource {
|
|
|
66
68
|
});
|
|
67
69
|
}
|
|
68
70
|
async captureFrame(frame) {
|
|
71
|
+
if (this.closed) {
|
|
72
|
+
throw new Error("AudioSource is closed");
|
|
73
|
+
}
|
|
69
74
|
const now = Number(process.hrtime.bigint() / BigInt(1e6));
|
|
70
75
|
const elapsed = this.lastCapture === 0 ? 0 : now - this.lastCapture;
|
|
71
76
|
const frameDurationMs = frame.samplesPerChannel / frame.sampleRate * 1e3;
|
|
@@ -91,6 +96,7 @@ class AudioSource {
|
|
|
91
96
|
}
|
|
92
97
|
async close() {
|
|
93
98
|
this.ffiHandle.dispose();
|
|
99
|
+
this.closed = true;
|
|
94
100
|
}
|
|
95
101
|
}
|
|
96
102
|
export {
|
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\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 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 // remove 50ms to account for processing time\n // (e.g. using wait_for_playout for very small chunks)\n this.timeout = setTimeout(this.release, this.currentQueueSize - 50);\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 }\n}\n"],"mappings":"AAIA,SAAS,iBAAiB;AAC1B,SAAS,iBAAiB;AAQ1B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,MAAM,YAAY;AAAA,
|
|
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 // remove 50ms to account for processing time\n // (e.g. using wait_for_playout for very small chunks)\n this.timeout = setTimeout(this.release, this.currentQueueSize - 50);\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":"AAIA,SAAS,iBAAiB;AAC1B,SAAS,iBAAiB;AAQ1B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,MAAM,YAAY;AAAA,EAqBvB,YAAY,YAAoB,aAAqB,YAAY,KAAM;AAXvE;AAAA,mBAAU,MAAM;AAAA,IAAC;AACjB,mBAAU,KAAK,WAAW;AAE1B;AAAA,mBAA0C;AAE1C;AAAA,kBAAS;AAOP,SAAK,aAAa;AAClB,SAAK,cAAc;AACnB,SAAK,YAAY;AAEjB,SAAK,cAAc;AACnB,SAAK,mBAAmB;AAExB,UAAM,MAAM,IAAI,sBAAsB;AAAA,MACpC,MAAM,gBAAgB;AAAA,MACtB;AAAA,MACA;AAAA,MACA,aAAa;AAAA,IACf,CAAC;AAED,UAAM,MAAM,UAAU,SAAS,QAAgC;AAAA,MAC7D,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,SAAK,OAAO,IAAI,OAAQ;AACxB,SAAK,YAAY,IAAI,UAAU,IAAI,OAAQ,OAAQ,EAAG;AAAA,EACxD;AAAA,EAEA,IAAI,iBAAyB;AAC3B,WAAO,KAAK;AAAA,MACV,KAAK,mBAAmB,OAAO,QAAQ,OAAO,OAAO,IAAI,OAAO,GAAO,CAAC,IAAI,KAAK;AAAA,MACjF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aAAa;AACX,UAAM,MAAM,IAAI,wBAAwB;AAAA,MACtC,cAAc,KAAK,UAAU;AAAA,IAC/B,CAAC;AAED,cAAU,SAAS,QAAkC;AAAA,MACnD,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA,EAGA,MAAM,aAAa;AACjB,WAAO,IAAI,QAAc,CAAC,YAAY;AACpC,WAAK,UAAU;AAAA,IACjB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,iBAAiB;AACrB,WAAO,KAAK,QAAQ,KAAK,MAAM;AAC7B,WAAK,cAAc;AACnB,WAAK,mBAAmB;AACxB,WAAK,UAAU,KAAK,WAAW;AAAA,IACjC,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,aAAa,OAAmB;AACpC,QAAI,KAAK,QAAQ;AACf,YAAM,IAAI,MAAM,uBAAuB;AAAA,IACzC;AACA,UAAM,MAAM,OAAO,QAAQ,OAAO,OAAO,IAAI,OAAO,GAAO,CAAC;AAC5D,UAAM,UAAU,KAAK,gBAAgB,IAAI,IAAI,MAAM,KAAK;AACxD,UAAM,kBAAmB,MAAM,oBAAoB,MAAM,aAAc;AACvE,SAAK,oBAAoB,kBAAkB;AAE3C,SAAK,cAAc;AAEnB,QAAI,KAAK,SAAS;AAChB,mBAAa,KAAK,OAAO;AAAA,IAC3B;AAIA,SAAK,UAAU,WAAW,KAAK,SAAS,KAAK,mBAAmB,EAAE;AAElE,UAAM,MAAM,IAAI,yBAAyB;AAAA,MACvC,cAAc,KAAK,UAAU;AAAA,MAC7B,QAAQ,MAAM,UAAU;AAAA,IAC1B,CAAC;AAED,UAAM,MAAM,UAAU,SAAS,QAAmC;AAAA,MAChE,SAAS,EAAE,MAAM,qBAAqB,OAAO,IAAI;AAAA,IACnD,CAAC;AAED,UAAM,KAAK,MAAM,UAAU,SAAS,QAAmC,CAAC,OAAO;AAC7E,aAAO,GAAG,QAAQ,QAAQ,uBAAuB,GAAG,QAAQ,MAAM,WAAW,IAAI;AAAA,IACnF,CAAC;AAED,QAAI,GAAG,OAAO;AACZ,YAAM,IAAI,MAAM,GAAG,KAAK;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ;AACZ,SAAK,UAAU,QAAQ;AACvB,SAAK,SAAS;AAAA,EAChB;AACF;","names":[]}
|
package/dist/version.cjs
CHANGED
|
@@ -21,7 +21,7 @@ __export(version_exports, {
|
|
|
21
21
|
SDK_VERSION: () => SDK_VERSION
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(version_exports);
|
|
24
|
-
const SDK_VERSION = "0.13.
|
|
24
|
+
const SDK_VERSION = "0.13.8";
|
|
25
25
|
// Annotate the CommonJS export names for ESM import in node:
|
|
26
26
|
0 && (module.exports = {
|
|
27
27
|
SDK_VERSION
|
package/dist/version.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/version.ts"],"sourcesContent":["export const SDK_VERSION = \"0.13.
|
|
1
|
+
{"version":3,"sources":["../src/version.ts"],"sourcesContent":["export const SDK_VERSION = \"0.13.8\";\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,MAAM,cAAc;","names":[]}
|
package/dist/version.d.cts
CHANGED
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
package/dist/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/version.ts"],"sourcesContent":["export const SDK_VERSION = \"0.13.
|
|
1
|
+
{"version":3,"sources":["../src/version.ts"],"sourcesContent":["export const SDK_VERSION = \"0.13.8\";\n"],"mappings":"AAAO,MAAM,cAAc;","names":[]}
|
package/dist/video_source.cjs
CHANGED
|
@@ -25,6 +25,8 @@ var import_ffi_client = require("./ffi_client.cjs");
|
|
|
25
25
|
var import_video_frame_pb = require("./proto/video_frame_pb.cjs");
|
|
26
26
|
class VideoSource {
|
|
27
27
|
constructor(width, height) {
|
|
28
|
+
/** @internal */
|
|
29
|
+
this.closed = false;
|
|
28
30
|
var _a;
|
|
29
31
|
this.width = width;
|
|
30
32
|
this.height = height;
|
|
@@ -45,6 +47,9 @@ class VideoSource {
|
|
|
45
47
|
this.ffiHandle = new import_ffi_client.FfiHandle(res.source.handle.id);
|
|
46
48
|
}
|
|
47
49
|
captureFrame(frame, timestampUs = BigInt(0), rotation = import_video_frame_pb.VideoRotation.VIDEO_ROTATION_0) {
|
|
50
|
+
if (this.closed) {
|
|
51
|
+
throw new Error("VideoSource is closed");
|
|
52
|
+
}
|
|
48
53
|
const req = new import_video_frame_pb.CaptureVideoFrameRequest({
|
|
49
54
|
sourceHandle: this.ffiHandle.handle,
|
|
50
55
|
buffer: frame.protoInfo(),
|
|
@@ -57,6 +62,7 @@ class VideoSource {
|
|
|
57
62
|
}
|
|
58
63
|
async close() {
|
|
59
64
|
this.ffiHandle.dispose();
|
|
65
|
+
this.closed = true;
|
|
60
66
|
}
|
|
61
67
|
}
|
|
62
68
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/video_source.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { FfiClient, FfiHandle } from './ffi_client.js';\nimport type {\n CaptureVideoFrameResponse,\n NewVideoSourceResponse,\n VideoSourceInfo,\n} from './proto/video_frame_pb.js';\nimport {\n CaptureVideoFrameRequest,\n NewVideoSourceRequest,\n VideoRotation,\n VideoSourceType,\n} from './proto/video_frame_pb.js';\nimport type { VideoFrame } from './video_frame.js';\n\nexport class VideoSource {\n /** @internal */\n info?: VideoSourceInfo;\n /** @internal */\n ffiHandle: FfiHandle;\n\n width: number;\n height: number;\n\n constructor(width: number, height: number) {\n this.width = width;\n this.height = height;\n\n const req = new NewVideoSourceRequest({\n type: VideoSourceType.VIDEO_SOURCE_NATIVE,\n resolution: {\n width: width,\n height: height,\n },\n });\n\n const res = FfiClient.instance.request<NewVideoSourceResponse>({\n message: {\n case: 'newVideoSource',\n value: req,\n },\n });\n\n this.info = res.source?.info;\n this.ffiHandle = new FfiHandle(res.source!.handle!.id!);\n }\n\n captureFrame(\n frame: VideoFrame,\n timestampUs = BigInt(0),\n rotation = VideoRotation.VIDEO_ROTATION_0,\n ) {\n const req = new CaptureVideoFrameRequest({\n sourceHandle: this.ffiHandle.handle,\n buffer: frame.protoInfo(),\n rotation,\n timestampUs,\n });\n\n FfiClient.instance.request<CaptureVideoFrameResponse>({\n message: { case: 'captureVideoFrame', value: req },\n });\n }\n\n async close() {\n this.ffiHandle.dispose();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,wBAAqC;AAMrC,4BAKO;AAGA,MAAM,YAAY;AAAA,
|
|
1
|
+
{"version":3,"sources":["../src/video_source.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { FfiClient, FfiHandle } from './ffi_client.js';\nimport type {\n CaptureVideoFrameResponse,\n NewVideoSourceResponse,\n VideoSourceInfo,\n} from './proto/video_frame_pb.js';\nimport {\n CaptureVideoFrameRequest,\n NewVideoSourceRequest,\n VideoRotation,\n VideoSourceType,\n} from './proto/video_frame_pb.js';\nimport type { VideoFrame } from './video_frame.js';\n\nexport class VideoSource {\n /** @internal */\n info?: VideoSourceInfo;\n /** @internal */\n ffiHandle: FfiHandle;\n /** @internal */\n closed = false;\n\n width: number;\n height: number;\n\n constructor(width: number, height: number) {\n this.width = width;\n this.height = height;\n\n const req = new NewVideoSourceRequest({\n type: VideoSourceType.VIDEO_SOURCE_NATIVE,\n resolution: {\n width: width,\n height: height,\n },\n });\n\n const res = FfiClient.instance.request<NewVideoSourceResponse>({\n message: {\n case: 'newVideoSource',\n value: req,\n },\n });\n\n this.info = res.source?.info;\n this.ffiHandle = new FfiHandle(res.source!.handle!.id!);\n }\n\n captureFrame(\n frame: VideoFrame,\n timestampUs = BigInt(0),\n rotation = VideoRotation.VIDEO_ROTATION_0,\n ) {\n if (this.closed) {\n throw new Error('VideoSource is closed');\n }\n const req = new CaptureVideoFrameRequest({\n sourceHandle: this.ffiHandle.handle,\n buffer: frame.protoInfo(),\n rotation,\n timestampUs,\n });\n\n FfiClient.instance.request<CaptureVideoFrameResponse>({\n message: { case: 'captureVideoFrame', value: req },\n });\n }\n\n async close() {\n this.ffiHandle.dispose();\n this.closed = true;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,wBAAqC;AAMrC,4BAKO;AAGA,MAAM,YAAY;AAAA,EAWvB,YAAY,OAAe,QAAgB;AAL3C;AAAA,kBAAS;AAvBX;AA6BI,SAAK,QAAQ;AACb,SAAK,SAAS;AAEd,UAAM,MAAM,IAAI,4CAAsB;AAAA,MACpC,MAAM,sCAAgB;AAAA,MACtB,YAAY;AAAA,QACV;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAED,UAAM,MAAM,4BAAU,SAAS,QAAgC;AAAA,MAC7D,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,SAAK,QAAO,SAAI,WAAJ,mBAAY;AACxB,SAAK,YAAY,IAAI,4BAAU,IAAI,OAAQ,OAAQ,EAAG;AAAA,EACxD;AAAA,EAEA,aACE,OACA,cAAc,OAAO,CAAC,GACtB,WAAW,oCAAc,kBACzB;AACA,QAAI,KAAK,QAAQ;AACf,YAAM,IAAI,MAAM,uBAAuB;AAAA,IACzC;AACA,UAAM,MAAM,IAAI,+CAAyB;AAAA,MACvC,cAAc,KAAK,UAAU;AAAA,MAC7B,QAAQ,MAAM,UAAU;AAAA,MACxB;AAAA,MACA;AAAA,IACF,CAAC;AAED,gCAAU,SAAS,QAAmC;AAAA,MACpD,SAAS,EAAE,MAAM,qBAAqB,OAAO,IAAI;AAAA,IACnD,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,QAAQ;AACZ,SAAK,UAAU,QAAQ;AACvB,SAAK,SAAS;AAAA,EAChB;AACF;","names":[]}
|
package/dist/video_source.d.cts
CHANGED
package/dist/video_source.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"video_source.d.ts","sourceRoot":"","sources":["../src/video_source.ts"],"names":[],"mappings":"AAGA,OAAO,EAAa,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,EAGV,eAAe,EAChB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAGL,aAAa,EAEd,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,qBAAa,WAAW;IACtB,gBAAgB;IAChB,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,gBAAgB;IAChB,SAAS,EAAE,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"video_source.d.ts","sourceRoot":"","sources":["../src/video_source.ts"],"names":[],"mappings":"AAGA,OAAO,EAAa,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,EAGV,eAAe,EAChB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAGL,aAAa,EAEd,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,qBAAa,WAAW;IACtB,gBAAgB;IAChB,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,gBAAgB;IAChB,SAAS,EAAE,SAAS,CAAC;IACrB,gBAAgB;IAChB,MAAM,UAAS;IAEf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;gBAEH,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAuBzC,YAAY,CACV,KAAK,EAAE,UAAU,EACjB,WAAW,SAAY,EACvB,QAAQ,gBAAiC;IAiBrC,KAAK;CAIZ"}
|
package/dist/video_source.js
CHANGED
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
} from "./proto/video_frame_pb.js";
|
|
8
8
|
class VideoSource {
|
|
9
9
|
constructor(width, height) {
|
|
10
|
+
/** @internal */
|
|
11
|
+
this.closed = false;
|
|
10
12
|
var _a;
|
|
11
13
|
this.width = width;
|
|
12
14
|
this.height = height;
|
|
@@ -27,6 +29,9 @@ class VideoSource {
|
|
|
27
29
|
this.ffiHandle = new FfiHandle(res.source.handle.id);
|
|
28
30
|
}
|
|
29
31
|
captureFrame(frame, timestampUs = BigInt(0), rotation = VideoRotation.VIDEO_ROTATION_0) {
|
|
32
|
+
if (this.closed) {
|
|
33
|
+
throw new Error("VideoSource is closed");
|
|
34
|
+
}
|
|
30
35
|
const req = new CaptureVideoFrameRequest({
|
|
31
36
|
sourceHandle: this.ffiHandle.handle,
|
|
32
37
|
buffer: frame.protoInfo(),
|
|
@@ -39,6 +44,7 @@ class VideoSource {
|
|
|
39
44
|
}
|
|
40
45
|
async close() {
|
|
41
46
|
this.ffiHandle.dispose();
|
|
47
|
+
this.closed = true;
|
|
42
48
|
}
|
|
43
49
|
}
|
|
44
50
|
export {
|
package/dist/video_source.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/video_source.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { FfiClient, FfiHandle } from './ffi_client.js';\nimport type {\n CaptureVideoFrameResponse,\n NewVideoSourceResponse,\n VideoSourceInfo,\n} from './proto/video_frame_pb.js';\nimport {\n CaptureVideoFrameRequest,\n NewVideoSourceRequest,\n VideoRotation,\n VideoSourceType,\n} from './proto/video_frame_pb.js';\nimport type { VideoFrame } from './video_frame.js';\n\nexport class VideoSource {\n /** @internal */\n info?: VideoSourceInfo;\n /** @internal */\n ffiHandle: FfiHandle;\n\n width: number;\n height: number;\n\n constructor(width: number, height: number) {\n this.width = width;\n this.height = height;\n\n const req = new NewVideoSourceRequest({\n type: VideoSourceType.VIDEO_SOURCE_NATIVE,\n resolution: {\n width: width,\n height: height,\n },\n });\n\n const res = FfiClient.instance.request<NewVideoSourceResponse>({\n message: {\n case: 'newVideoSource',\n value: req,\n },\n });\n\n this.info = res.source?.info;\n this.ffiHandle = new FfiHandle(res.source!.handle!.id!);\n }\n\n captureFrame(\n frame: VideoFrame,\n timestampUs = BigInt(0),\n rotation = VideoRotation.VIDEO_ROTATION_0,\n ) {\n const req = new CaptureVideoFrameRequest({\n sourceHandle: this.ffiHandle.handle,\n buffer: frame.protoInfo(),\n rotation,\n timestampUs,\n });\n\n FfiClient.instance.request<CaptureVideoFrameResponse>({\n message: { case: 'captureVideoFrame', value: req },\n });\n }\n\n async close() {\n this.ffiHandle.dispose();\n }\n}\n"],"mappings":"AAGA,SAAS,WAAW,iBAAiB;AAMrC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGA,MAAM,YAAY;AAAA,
|
|
1
|
+
{"version":3,"sources":["../src/video_source.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { FfiClient, FfiHandle } from './ffi_client.js';\nimport type {\n CaptureVideoFrameResponse,\n NewVideoSourceResponse,\n VideoSourceInfo,\n} from './proto/video_frame_pb.js';\nimport {\n CaptureVideoFrameRequest,\n NewVideoSourceRequest,\n VideoRotation,\n VideoSourceType,\n} from './proto/video_frame_pb.js';\nimport type { VideoFrame } from './video_frame.js';\n\nexport class VideoSource {\n /** @internal */\n info?: VideoSourceInfo;\n /** @internal */\n ffiHandle: FfiHandle;\n /** @internal */\n closed = false;\n\n width: number;\n height: number;\n\n constructor(width: number, height: number) {\n this.width = width;\n this.height = height;\n\n const req = new NewVideoSourceRequest({\n type: VideoSourceType.VIDEO_SOURCE_NATIVE,\n resolution: {\n width: width,\n height: height,\n },\n });\n\n const res = FfiClient.instance.request<NewVideoSourceResponse>({\n message: {\n case: 'newVideoSource',\n value: req,\n },\n });\n\n this.info = res.source?.info;\n this.ffiHandle = new FfiHandle(res.source!.handle!.id!);\n }\n\n captureFrame(\n frame: VideoFrame,\n timestampUs = BigInt(0),\n rotation = VideoRotation.VIDEO_ROTATION_0,\n ) {\n if (this.closed) {\n throw new Error('VideoSource is closed');\n }\n const req = new CaptureVideoFrameRequest({\n sourceHandle: this.ffiHandle.handle,\n buffer: frame.protoInfo(),\n rotation,\n timestampUs,\n });\n\n FfiClient.instance.request<CaptureVideoFrameResponse>({\n message: { case: 'captureVideoFrame', value: req },\n });\n }\n\n async close() {\n this.ffiHandle.dispose();\n this.closed = true;\n }\n}\n"],"mappings":"AAGA,SAAS,WAAW,iBAAiB;AAMrC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGA,MAAM,YAAY;AAAA,EAWvB,YAAY,OAAe,QAAgB;AAL3C;AAAA,kBAAS;AAvBX;AA6BI,SAAK,QAAQ;AACb,SAAK,SAAS;AAEd,UAAM,MAAM,IAAI,sBAAsB;AAAA,MACpC,MAAM,gBAAgB;AAAA,MACtB,YAAY;AAAA,QACV;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAED,UAAM,MAAM,UAAU,SAAS,QAAgC;AAAA,MAC7D,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,SAAK,QAAO,SAAI,WAAJ,mBAAY;AACxB,SAAK,YAAY,IAAI,UAAU,IAAI,OAAQ,OAAQ,EAAG;AAAA,EACxD;AAAA,EAEA,aACE,OACA,cAAc,OAAO,CAAC,GACtB,WAAW,cAAc,kBACzB;AACA,QAAI,KAAK,QAAQ;AACf,YAAM,IAAI,MAAM,uBAAuB;AAAA,IACzC;AACA,UAAM,MAAM,IAAI,yBAAyB;AAAA,MACvC,cAAc,KAAK,UAAU;AAAA,MAC7B,QAAQ,MAAM,UAAU;AAAA,MACxB;AAAA,MACA;AAAA,IACF,CAAC;AAED,cAAU,SAAS,QAAmC;AAAA,MACpD,SAAS,EAAE,MAAM,qBAAqB,OAAO,IAAI;AAAA,IACnD,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,QAAQ;AACZ,SAAK,UAAU,QAAQ;AACvB,SAAK,SAAS;AAAA,EAChB;AACF;","names":[]}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "LiveKit RTC Node",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"author": "LiveKit",
|
|
6
|
-
"version": "0.13.
|
|
6
|
+
"version": "0.13.8",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"require": "dist/index.cjs",
|
|
9
9
|
"types": "dist/index.d.ts",
|
|
@@ -61,11 +61,11 @@
|
|
|
61
61
|
"@bufbuild/protoc-gen-es": "^1.10.0"
|
|
62
62
|
},
|
|
63
63
|
"optionalDependencies": {
|
|
64
|
-
"@livekit/rtc-node-darwin-x64": "0.13.
|
|
65
|
-
"@livekit/rtc-node-linux-arm64-gnu": "0.13.
|
|
66
|
-
"@livekit/rtc-node-
|
|
67
|
-
"@livekit/rtc-node-
|
|
68
|
-
"@livekit/rtc-node-
|
|
64
|
+
"@livekit/rtc-node-darwin-x64": "0.13.8",
|
|
65
|
+
"@livekit/rtc-node-linux-arm64-gnu": "0.13.8",
|
|
66
|
+
"@livekit/rtc-node-darwin-arm64": "0.13.8",
|
|
67
|
+
"@livekit/rtc-node-linux-x64-gnu": "0.13.8",
|
|
68
|
+
"@livekit/rtc-node-win32-x64-msvc": "0.13.8"
|
|
69
69
|
},
|
|
70
70
|
"engines": {
|
|
71
71
|
"node": ">= 18"
|
package/src/audio_source.ts
CHANGED
|
@@ -32,6 +32,8 @@ export class AudioSource {
|
|
|
32
32
|
promise = this.newPromise();
|
|
33
33
|
/** @internal */
|
|
34
34
|
timeout?: ReturnType<typeof setTimeout> = undefined;
|
|
35
|
+
/** @internal */
|
|
36
|
+
closed = false;
|
|
35
37
|
|
|
36
38
|
sampleRate: number;
|
|
37
39
|
numChannels: number;
|
|
@@ -101,6 +103,9 @@ export class AudioSource {
|
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
async captureFrame(frame: AudioFrame) {
|
|
106
|
+
if (this.closed) {
|
|
107
|
+
throw new Error('AudioSource is closed');
|
|
108
|
+
}
|
|
104
109
|
const now = Number(process.hrtime.bigint() / BigInt(1000000));
|
|
105
110
|
const elapsed = this.lastCapture === 0 ? 0 : now - this.lastCapture;
|
|
106
111
|
const frameDurationMs = (frame.samplesPerChannel / frame.sampleRate) * 1000;
|
|
@@ -136,5 +141,6 @@ export class AudioSource {
|
|
|
136
141
|
|
|
137
142
|
async close() {
|
|
138
143
|
this.ffiHandle.dispose();
|
|
144
|
+
this.closed = true;
|
|
139
145
|
}
|
|
140
146
|
}
|
package/src/nodejs.rs
CHANGED
|
@@ -40,23 +40,30 @@ fn livekit_initialize(cb: JsFunction, capture_logs: bool, sdk_version: String) {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
#[napi]
|
|
43
|
-
fn livekit_ffi_request(data: Uint8Array) -> Uint8Array {
|
|
43
|
+
fn livekit_ffi_request(data: Uint8Array) -> Result<Uint8Array> {
|
|
44
44
|
let data = data.to_vec();
|
|
45
45
|
let res = match proto::FfiRequest::decode(data.as_slice()) {
|
|
46
46
|
Ok(res) => res,
|
|
47
47
|
Err(err) => {
|
|
48
|
-
|
|
48
|
+
return Err(Error::from_reason(format!(
|
|
49
|
+
"failed to decode request: {}",
|
|
50
|
+
err.to_string()
|
|
51
|
+
)));
|
|
49
52
|
}
|
|
50
53
|
};
|
|
51
54
|
|
|
52
|
-
let res = match server::requests::handle_request(&FFI_SERVER, res) {
|
|
55
|
+
let res = match server::requests::handle_request(&FFI_SERVER, res.clone()) {
|
|
53
56
|
Ok(res) => res,
|
|
54
57
|
Err(err) => {
|
|
55
|
-
|
|
58
|
+
return Err(Error::from_reason(format!(
|
|
59
|
+
"failed to handle request: {} ({:?})",
|
|
60
|
+
err.to_string(),
|
|
61
|
+
res
|
|
62
|
+
)));
|
|
56
63
|
}
|
|
57
64
|
}
|
|
58
65
|
.encode_to_vec();
|
|
59
|
-
Uint8Array::new(res)
|
|
66
|
+
Ok(Uint8Array::new(res))
|
|
60
67
|
}
|
|
61
68
|
|
|
62
69
|
// FfiHandle must be used instead
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const SDK_VERSION = "0.13.
|
|
1
|
+
export const SDK_VERSION = "0.13.8";
|
package/src/video_source.ts
CHANGED
|
@@ -20,6 +20,8 @@ export class VideoSource {
|
|
|
20
20
|
info?: VideoSourceInfo;
|
|
21
21
|
/** @internal */
|
|
22
22
|
ffiHandle: FfiHandle;
|
|
23
|
+
/** @internal */
|
|
24
|
+
closed = false;
|
|
23
25
|
|
|
24
26
|
width: number;
|
|
25
27
|
height: number;
|
|
@@ -52,6 +54,9 @@ export class VideoSource {
|
|
|
52
54
|
timestampUs = BigInt(0),
|
|
53
55
|
rotation = VideoRotation.VIDEO_ROTATION_0,
|
|
54
56
|
) {
|
|
57
|
+
if (this.closed) {
|
|
58
|
+
throw new Error('VideoSource is closed');
|
|
59
|
+
}
|
|
55
60
|
const req = new CaptureVideoFrameRequest({
|
|
56
61
|
sourceHandle: this.ffiHandle.handle,
|
|
57
62
|
buffer: frame.protoInfo(),
|
|
@@ -66,5 +71,6 @@ export class VideoSource {
|
|
|
66
71
|
|
|
67
72
|
async close() {
|
|
68
73
|
this.ffiHandle.dispose();
|
|
74
|
+
this.closed = true;
|
|
69
75
|
}
|
|
70
76
|
}
|