diff --git a/packages/livekit-rtc/src/audio_frame.ts b/packages/livekit-rtc/src/audio_frame.ts index 5fb296c4..484bbd56 100644 --- a/packages/livekit-rtc/src/audio_frame.ts +++ b/packages/livekit-rtc/src/audio_frame.ts @@ -30,15 +30,15 @@ export class AudioFrame { /** @internal */ static fromOwnedInfo(owned: OwnedAudioFrameBuffer): AudioFrame { - const info = owned.info; - const len = info.numChannels * info.samplesPerChannel * 2; // c_int16 - const data = FfiClient.instance.copyBuffer(info.dataPtr, len); + const info = owned.info!; + const len = info.numChannels! * info.samplesPerChannel! * 2; // c_int16 + const data = FfiClient.instance.copyBuffer(info.dataPtr!, len); new FfiHandle(owned.handle.id).dispose(); return new AudioFrame( new Int16Array(data.buffer), - info.sampleRate, - info.numChannels, - info.samplesPerChannel, + info.sampleRate!, + info.numChannels!, + info.samplesPerChannel!, ); } @@ -63,8 +63,8 @@ export class AudioFrame { * @param buffer - a single AudioFrame or list thereof */ export const combineAudioFrames = (buffer: AudioFrame | AudioFrame[]): AudioFrame => { - if (!buffer['length']) { - return buffer as AudioFrame; + if (!Array.isArray(buffer)) { + return buffer; } buffer = buffer as AudioFrame[]; diff --git a/packages/livekit-rtc/src/audio_resampler.ts b/packages/livekit-rtc/src/audio_resampler.ts index 22efb56a..0f3fd0e3 100644 --- a/packages/livekit-rtc/src/audio_resampler.ts +++ b/packages/livekit-rtc/src/audio_resampler.ts @@ -75,11 +75,15 @@ export class AudioResampler { }, }); - if (res.error) { - throw new Error(res.error); - } - this.#ffiHandle = new FfiHandle(res.resampler.handle.id); + switch (res.message.case) { + case 'resampler': + this.#ffiHandle = new FfiHandle(res.message.value.handle.id); + break; + case 'error': + default: + throw new Error(res.message.value); + } } /** @@ -115,7 +119,7 @@ export class AudioResampler { return []; } - const outputData = FfiClient.instance.copyBuffer(res.outputPtr, res.size); + const outputData = FfiClient.instance.copyBuffer(res.outputPtr, res.size!); return [ new AudioFrame( new Int16Array(outputData.buffer), @@ -153,7 +157,7 @@ export class AudioResampler { return []; } - const outputData = FfiClient.instance.copyBuffer(res.outputPtr, res.size); + const outputData = FfiClient.instance.copyBuffer(res.outputPtr, res.size!); return [ new AudioFrame( new Int16Array(outputData.buffer), diff --git a/packages/livekit-rtc/src/audio_source.ts b/packages/livekit-rtc/src/audio_source.ts index 657411ad..9db5ff05 100644 --- a/packages/livekit-rtc/src/audio_source.ts +++ b/packages/livekit-rtc/src/audio_source.ts @@ -20,7 +20,7 @@ import { export class AudioSource { /** @internal */ - info: AudioSourceInfo; + info?: AudioSourceInfo; /** @internal */ ffiHandle: FfiHandle; /** @internal */ @@ -59,8 +59,8 @@ export class AudioSource { }, }); - this.info = res.source.info; - this.ffiHandle = new FfiHandle(res.source.handle.id); + this.info = res.source?.info; + this.ffiHandle = new FfiHandle(res.source?.handle.id); } get queuedDuration(): number { diff --git a/packages/livekit-rtc/src/audio_stream.ts b/packages/livekit-rtc/src/audio_stream.ts index d012c9c2..f1354453 100644 --- a/packages/livekit-rtc/src/audio_stream.ts +++ b/packages/livekit-rtc/src/audio_stream.ts @@ -11,7 +11,7 @@ import type { Track } from './track.js'; export class AudioStream implements AsyncIterableIterator { /** @internal */ - info: AudioStreamInfo; + info?: AudioStreamInfo; /** @internal */ ffiHandle: FfiHandle; /** @internal */ @@ -44,8 +44,8 @@ export class AudioStream implements AsyncIterableIterator { }, }); - this.info = res.stream.info; - this.ffiHandle = new FfiHandle(res.stream.handle.id); + this.info = res.stream?.info; + this.ffiHandle = new FfiHandle(res.stream?.handle.id); FfiClient.instance.on(FfiClientEvent.FfiEvent, this.onEvent); } diff --git a/packages/livekit-rtc/src/e2ee.ts b/packages/livekit-rtc/src/e2ee.ts index 694f74bc..d315f6f5 100644 --- a/packages/livekit-rtc/src/e2ee.ts +++ b/packages/livekit-rtc/src/e2ee.ts @@ -99,7 +99,7 @@ export class KeyProvider { }, }); - return (res.message.value as GetSharedKeyResponse).key; + return (res.message.value as GetSharedKeyResponse).key!; } ratchetSharedKey(keyIndex: number): Uint8Array { @@ -120,7 +120,7 @@ export class KeyProvider { }, }); - return (res.message.value as RatchetSharedKeyResponse).newKey; + return (res.message.value as RatchetSharedKeyResponse).newKey!; } setKey(participantIdentity: string, keyIndex: number) { @@ -162,7 +162,7 @@ export class KeyProvider { }, }); - return (res.message.value as GetKeyResponse).key; + return (res.message.value as GetKeyResponse).key!; } ratchetKey(participantIdentity: string, keyIndex: number): Uint8Array { @@ -184,7 +184,7 @@ export class KeyProvider { }, }); - return (res.message.value as RatchetKeyResponse).newKey; + return (res.message.value as RatchetKeyResponse).newKey!; } } @@ -255,12 +255,11 @@ export class E2EEManager { this.roomHandle = roomHandle; this.enabled = opts !== undefined; - if (opts !== undefined) { - const options = { ...defaultE2EEOptions, ...opts }; + opts ??= defaultE2EEOptions; + const options = { ...defaultE2EEOptions, ...opts }; - this.options = options; - this.keyProvider = new KeyProvider(roomHandle, options.keyProviderOptions); - } + this.options = options; + this.keyProvider = new KeyProvider(roomHandle, options.keyProviderOptions); } setEnabled(enabled: boolean) { @@ -305,9 +304,9 @@ export class E2EEManager { (cryptor) => new FrameCryptor( this.roomHandle, - cryptor.participantIdentity, - cryptor.keyIndex, - cryptor.enabled, + cryptor.participantIdentity!, + cryptor.keyIndex!, + cryptor.enabled!, ), ); diff --git a/packages/livekit-rtc/src/ffi_client.ts b/packages/livekit-rtc/src/ffi_client.ts index 1c733ce1..ee4e78a1 100644 --- a/packages/livekit-rtc/src/ffi_client.ts +++ b/packages/livekit-rtc/src/ffi_client.ts @@ -15,7 +15,7 @@ import { import { FfiEvent, FfiRequest, FfiResponse } from './proto/ffi_pb.js'; import { SDK_VERSION } from './version.js'; -export { FfiHandle, type FfiEvent, type FfiResponse, type FfiRequest, livekitDispose as dispose }; +export { FfiHandle, type FfiEvent, type FfiResponse, FfiRequest, livekitDispose as dispose }; export type FfiClientCallbacks = { ffi_event: (event: FfiEvent) => void; diff --git a/packages/livekit-rtc/src/participant.ts b/packages/livekit-rtc/src/participant.ts index de2a93e1..f6e4142f 100644 --- a/packages/livekit-rtc/src/participant.ts +++ b/packages/livekit-rtc/src/participant.ts @@ -38,8 +38,18 @@ import { SetLocalNameRequest, UnpublishTrackRequest, } from './proto/room_pb.js'; -import { PerformRpcCallback, PerformRpcRequest, PerformRpcResponse, RegisterRpcMethodRequest, RegisterRpcMethodResponse, RpcMethodInvocationResponseRequest, RpcMethodInvocationResponseResponse, UnregisterRpcMethodRequest, UnregisterRpcMethodResponse } from './proto/rpc_pb.js'; -import { RpcError, type PerformRpcParams, type RpcInvocationData } from './rpc.js'; +import { + PerformRpcCallback, + PerformRpcRequest, + PerformRpcResponse, + RegisterRpcMethodRequest, + RegisterRpcMethodResponse, + RpcMethodInvocationResponseRequest, + RpcMethodInvocationResponseResponse, + UnregisterRpcMethodRequest, + UnregisterRpcMethodResponse, +} from './proto/rpc_pb.js'; +import { type PerformRpcParams, RpcError, type RpcInvocationData } from './rpc.js'; import type { LocalTrack } from './track.js'; import type { RemoteTrackPublication, TrackPublication } from './track_publication.js'; import { LocalTrackPublication } from './track_publication.js'; @@ -48,7 +58,7 @@ import type { ChatMessage } from './types.js'; export abstract class Participant { /** @internal */ - info: ParticipantInfo; + info?: ParticipantInfo; /** @internal */ ffi_handle: FfiHandle; @@ -60,28 +70,28 @@ export abstract class Participant { this.ffi_handle = new FfiHandle(owned_info.handle.id); } - get sid(): string { - return this.info.sid; + get sid(): string | undefined { + return this.info?.sid; } - get name(): string { - return this.info.name; + get name(): string | undefined { + return this.info?.name; } - get identity(): string { - return this.info.identity; + get identity(): string | undefined { + return this.info?.identity; } - get metadata(): string { - return this.info.metadata; + get metadata(): string | undefined { + return this.info?.metadata; } - get attributes(): Record { - return this.info.attributes; + get attributes(): Record | undefined { + return this.info?.attributes; } - get kind(): ParticipantKind { - return this.info.kind; + get kind(): ParticipantKind | undefined { + return this.info?.kind; } } @@ -223,11 +233,19 @@ export class LocalParticipant extends Participant { return ev.message.case == 'chatMessage' && ev.message.value.asyncId == res.asyncId; }); - if (cb.error) { - throw new Error(cb.error); + switch (cb.message.case) { + case 'chatMessage': + const { id, timestamp, editTimestamp, message } = cb.message.value!; + return { + id: id!, + timestamp: Number(timestamp), + editTimestamp: Number(editTimestamp), + message: message!, + }; + case 'error': + default: + throw new Error(cb.message.value); } - const { id, timestamp, editTimestamp, message } = cb.chatMessage!; - return { id, timestamp: Number(timestamp), editTimestamp: Number(editTimestamp), message }; } /** @@ -261,11 +279,19 @@ export class LocalParticipant extends Participant { return ev.message.case == 'chatMessage' && ev.message.value.asyncId == res.asyncId; }); - if (cb.error) { - throw new Error(cb.error); + switch (cb.message.case) { + case 'chatMessage': + const { id, timestamp, editTimestamp, message } = cb.message.value!; + return { + id: id!, + timestamp: Number(timestamp), + editTimestamp: Number(editTimestamp), + message: message!, + }; + case 'error': + default: + throw new Error(cb.message.value); } - const { id, timestamp, editTimestamp, message } = cb.chatMessage!; - return { id, timestamp: Number(timestamp), editTimestamp: Number(editTimestamp), message }; } async updateName(name: string) { @@ -286,7 +312,7 @@ export class LocalParticipant extends Participant { async setAttributes(attributes: Record) { const req = new SetLocalAttributesRequest({ localParticipantHandle: this.ffi_handle.handle, - attributes: attributes, + attributes: Object.entries(attributes).map(([key, value]) => ({ key, value })), }); const res = FfiClient.instance.request({ @@ -316,15 +342,17 @@ export class LocalParticipant extends Participant { return ev.message.case == 'publishTrack' && ev.message.value.asyncId == res.asyncId; }); - if (cb.error) { - throw new Error(cb.error); - } + switch (cb.message.case) { + case 'publication': + const track_publication = new LocalTrackPublication(cb.message.value!); + track_publication.track = track; + this.trackPublications.set(track_publication.sid!, track_publication); - const track_publication = new LocalTrackPublication(cb.publication!); - track_publication.track = track; - this.trackPublications.set(track_publication.sid, track_publication); - - return track_publication; + return track_publication; + case 'error': + default: + throw new Error(cb.message.value); + } } async unpublishTrack(trackSid: string) { @@ -384,7 +412,7 @@ export class LocalParticipant extends Participant { throw RpcError.fromProto(cb.error); } - return cb.payload; + return cb.payload!; } /** diff --git a/packages/livekit-rtc/src/rpc.ts b/packages/livekit-rtc/src/rpc.ts index 0df24898..54ad443b 100644 --- a/packages/livekit-rtc/src/rpc.ts +++ b/packages/livekit-rtc/src/rpc.ts @@ -68,7 +68,7 @@ export class RpcError extends Error { } static fromProto(proto: RpcError_Proto) { - return new RpcError(proto.code, proto.message, proto.data); + return new RpcError(proto.code!, proto.message!, proto.data); } toProto() { diff --git a/packages/livekit-rtc/src/track.ts b/packages/livekit-rtc/src/track.ts index 9b4e11cb..ea9086ae 100644 --- a/packages/livekit-rtc/src/track.ts +++ b/packages/livekit-rtc/src/track.ts @@ -16,7 +16,7 @@ import type { VideoSource } from './video_source.js'; export abstract class Track { /** @internal */ - info: TrackInfo; + info?: TrackInfo; /** @internal */ ffi_handle: FfiHandle; @@ -26,24 +26,24 @@ export abstract class Track { this.ffi_handle = new FfiHandle(owned.handle.id); } - get sid(): string { - return this.info.sid; + get sid(): string | undefined { + return this.info?.sid; } - get name(): string { - return this.info.name; + get name(): string | undefined { + return this.info?.name; } - get kind(): TrackKind { - return this.info.kind; + get kind(): TrackKind | undefined { + return this.info?.kind; } - get stream_state(): StreamState { - return this.info.streamState; + get stream_state(): StreamState | undefined { + return this.info?.streamState; } - get muted(): boolean { - return this.info.muted; + get muted(): boolean | undefined { + return this.info?.muted; } } @@ -62,7 +62,7 @@ export class LocalAudioTrack extends Track { message: { case: 'createAudioTrack', value: req }, }); - return new LocalAudioTrack(res.track); + return new LocalAudioTrack(res.track!); } } @@ -81,7 +81,7 @@ export class LocalVideoTrack extends Track { message: { case: 'createVideoTrack', value: req }, }); - return new LocalVideoTrack(res.track); + return new LocalVideoTrack(res.track!); } } diff --git a/packages/livekit-rtc/src/track_publication.ts b/packages/livekit-rtc/src/track_publication.ts index eed08f66..5ed634ae 100644 --- a/packages/livekit-rtc/src/track_publication.ts +++ b/packages/livekit-rtc/src/track_publication.ts @@ -19,7 +19,7 @@ export abstract class TrackPublication { ffiHandle: FfiHandle; /** @internal */ - info: TrackPublicationInfo; + info?: TrackPublicationInfo; track?: Track; constructor(ownedInfo: OwnedTrackPublication) { @@ -27,44 +27,44 @@ export abstract class TrackPublication { this.ffiHandle = new FfiHandle(ownedInfo.handle.id); } - get sid(): string { - return this.info.sid; + get sid(): string | undefined { + return this.info?.sid; } - get name(): string { - return this.info.name; + get name(): string | undefined { + return this.info?.name; } - get kind(): TrackKind { - return this.info.kind; + get kind(): TrackKind | undefined { + return this.info?.kind; } - get source(): TrackSource { - return this.info.source; + get source(): TrackSource | undefined { + return this.info?.source; } - get simulcasted(): boolean { - return this.info.simulcasted; + get simulcasted(): boolean | undefined { + return this.info?.simulcasted; } - get width(): number { - return this.info.width; + get width(): number | undefined { + return this.info?.width; } - get height(): number { - return this.info.height; + get height(): number | undefined { + return this.info?.height; } - get mimeType(): string { - return this.info.mimeType; + get mimeType(): string | undefined { + return this.info?.mimeType; } - get muted(): boolean { - return this.info.muted; + get muted(): boolean | undefined { + return this.info?.muted; } - get encryptionType(): EncryptionType { - return this.info.encryptionType; + get encryptionType(): EncryptionType | undefined { + return this.info?.encryptionType; } } diff --git a/packages/livekit-rtc/src/video_frame.ts b/packages/livekit-rtc/src/video_frame.ts index 9b8f9e19..68c3be63 100644 --- a/packages/livekit-rtc/src/video_frame.ts +++ b/packages/livekit-rtc/src/video_frame.ts @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2024 LiveKit, Inc. // // SPDX-License-Identifier: Apache-2.0 -import { FfiClient, type FfiRequest } from './ffi_client.js'; +import { FfiClient, FfiRequest } from './ffi_client.js'; import type { OwnedVideoBuffer, VideoConvertResponse } from './proto/video_frame_pb.js'; import { VideoBufferInfo, @@ -55,15 +55,15 @@ export class VideoFrame { /** @internal */ static fromOwnedInfo(owned: OwnedVideoBuffer): VideoFrame { - const info = owned.info; + const info = owned.info!; return new VideoFrame( FfiClient.instance.copyBuffer( - info.dataPtr, - getPlaneLength(info.type, info.width, info.height), + info.dataPtr!, + getPlaneLength(info.type!, info.width!, info.height!), ), - info.width, - info.height, - info.type, + info.width!, + info.height!, + info.type!, ); } @@ -72,7 +72,7 @@ export class VideoFrame { if (planeNth >= planeInfos.length) return; const planeInfo = planeInfos[planeNth]!; - return FfiClient.instance.copyBuffer(planeInfo.dataPtr, planeInfo.size); + return FfiClient.instance.copyBuffer(planeInfo.dataPtr!, planeInfo.size!); } convert(dstType: VideoBufferType, flipY = false): VideoFrame { @@ -87,11 +87,14 @@ export class VideoFrame { }, }); const resp = FfiClient.instance.request(req); - if (resp.error) { - throw resp.error; - } - return VideoFrame.fromOwnedInfo(resp.buffer); + switch (resp.message.case) { + case 'buffer': + return VideoFrame.fromOwnedInfo(resp.message.value); + case 'error': + default: + throw resp.message.value + } } } @@ -132,12 +135,12 @@ const getPlaneInfos = ( case VideoBufferType.I420: { const y = new VideoBufferInfo_ComponentInfo({ dataPtr, stride: width, size: width * height }); const u = new VideoBufferInfo_ComponentInfo({ - dataPtr: y.dataPtr + BigInt(y.size), + dataPtr: y.dataPtr! + BigInt(y.size!), stride: chromaWidth, size: chromaWidth * chromaHeight, }); const v = new VideoBufferInfo_ComponentInfo({ - dataPtr: u.dataPtr + BigInt(u.size), + dataPtr: u.dataPtr! + BigInt(u.size!), stride: chromaWidth, size: chromaWidth * chromaHeight, }); @@ -146,17 +149,17 @@ const getPlaneInfos = ( case VideoBufferType.I420A: { const y = new VideoBufferInfo_ComponentInfo({ dataPtr, stride: width, size: width * height }); const u = new VideoBufferInfo_ComponentInfo({ - dataPtr: y.dataPtr + BigInt(y.size), + dataPtr: y.dataPtr! + BigInt(y.size!), stride: chromaWidth, size: chromaWidth * chromaHeight, }); const v = new VideoBufferInfo_ComponentInfo({ - dataPtr: u.dataPtr + BigInt(u.size), + dataPtr: u.dataPtr! + BigInt(u.size!), stride: chromaWidth, size: chromaWidth * chromaHeight, }); const a = new VideoBufferInfo_ComponentInfo({ - dataPtr: v.dataPtr + BigInt(v.size), + dataPtr: v.dataPtr! + BigInt(v.size!), stride: width, size: width * height, }); @@ -165,12 +168,12 @@ const getPlaneInfos = ( case VideoBufferType.I422: { const y = new VideoBufferInfo_ComponentInfo({ dataPtr, stride: width, size: width * height }); const u = new VideoBufferInfo_ComponentInfo({ - dataPtr: y.dataPtr + BigInt(y.size), + dataPtr: y.dataPtr! + BigInt(y.size!), stride: chromaWidth, size: chromaWidth * height, }); const v = new VideoBufferInfo_ComponentInfo({ - dataPtr: u.dataPtr + BigInt(u.size), + dataPtr: u.dataPtr! + BigInt(u.size!), stride: chromaWidth, size: chromaWidth * height, }); @@ -179,12 +182,12 @@ const getPlaneInfos = ( case VideoBufferType.I444: { const y = new VideoBufferInfo_ComponentInfo({ dataPtr, stride: width, size: width * height }); const u = new VideoBufferInfo_ComponentInfo({ - dataPtr: y.dataPtr + BigInt(y.size), + dataPtr: y.dataPtr! + BigInt(y.size!), stride: width, size: width * height, }); const v = new VideoBufferInfo_ComponentInfo({ - dataPtr: u.dataPtr + BigInt(u.size), + dataPtr: u.dataPtr! + BigInt(u.size!), stride: width, size: width * height, }); @@ -197,12 +200,12 @@ const getPlaneInfos = ( size: width * height * 2, }); const u = new VideoBufferInfo_ComponentInfo({ - dataPtr: y.dataPtr + BigInt(y.size), + dataPtr: y.dataPtr! + BigInt(y.size!), stride: chromaWidth * 2, size: chromaWidth * chromaHeight * 2, }); const v = new VideoBufferInfo_ComponentInfo({ - dataPtr: u.dataPtr + BigInt(u.size), + dataPtr: u.dataPtr! + BigInt(u.size!), stride: chromaWidth * 2, size: chromaWidth * chromaHeight * 2, }); @@ -211,7 +214,7 @@ const getPlaneInfos = ( case VideoBufferType.NV12: { const y = new VideoBufferInfo_ComponentInfo({ dataPtr, stride: width, size: width * height }); const uv = new VideoBufferInfo_ComponentInfo({ - dataPtr: y.dataPtr + BigInt(y.size), + dataPtr: y.dataPtr! + BigInt(y.size!), stride: chromaWidth * 2, size: chromaWidth * chromaHeight * 2, }); diff --git a/packages/livekit-rtc/src/video_source.ts b/packages/livekit-rtc/src/video_source.ts index 62ea199a..66384c99 100644 --- a/packages/livekit-rtc/src/video_source.ts +++ b/packages/livekit-rtc/src/video_source.ts @@ -17,7 +17,7 @@ import type { VideoFrame } from './video_frame.js'; export class VideoSource { /** @internal */ - info: VideoSourceInfo; + info?: VideoSourceInfo; /** @internal */ ffiHandle: FfiHandle; @@ -43,8 +43,8 @@ export class VideoSource { }, }); - this.info = res.source.info; - this.ffiHandle = new FfiHandle(res.source.handle.id); + this.info = res.source?.info; + this.ffiHandle = new FfiHandle(res.source?.handle.id); } captureFrame(frame: VideoFrame, timestampUs = BigInt(0), rotation = VideoRotation.VIDEO_ROTATION_0) { diff --git a/packages/livekit-rtc/src/video_stream.ts b/packages/livekit-rtc/src/video_stream.ts index aaf57162..075ed682 100644 --- a/packages/livekit-rtc/src/video_stream.ts +++ b/packages/livekit-rtc/src/video_stream.ts @@ -21,7 +21,7 @@ export type VideoFrameEvent = { export class VideoStream implements AsyncIterableIterator { /** @internal */ - info: VideoStreamInfo; + info?: VideoStreamInfo; /** @internal */ ffiHandle: FfiHandle; /** @internal */ @@ -48,8 +48,8 @@ export class VideoStream implements AsyncIterableIterator { }, }); - this.info = res.stream.info; - this.ffiHandle = new FfiHandle(res.stream.handle.id); + this.info = res.stream?.info; + this.ffiHandle = new FfiHandle(res.stream?.handle.id); FfiClient.instance.on(FfiClientEvent.FfiEvent, this.onEvent); }