livekit-client
Advanced tools
Comparing version 2.5.10 to 2.6.0
@@ -26,2 +26,3 @@ import { Mutex } from '@livekit/mutex'; | ||
import { getBrowser } from './utils/browserParser'; | ||
export { RpcError, type RpcInvocationData, type PerformRpcParams } from './room/rpc'; | ||
export * from './connectionHelper/ConnectionCheck'; | ||
@@ -28,0 +29,0 @@ export * from './connectionHelper/checks/Checker'; |
import { Codec, ParticipantInfo, ParticipantPermission } from '@livekit/protocol'; | ||
import type { InternalRoomOptions } from '../../options'; | ||
import type RTCEngine from '../RTCEngine'; | ||
import { type PerformRpcParams, type RpcInvocationData } from '../rpc'; | ||
import LocalTrack from '../track/LocalTrack'; | ||
@@ -32,2 +33,5 @@ import LocalTrackPublication from '../track/LocalTrackPublication'; | ||
private enabledPublishVideoCodecs; | ||
private rpcHandlers; | ||
private pendingAcks; | ||
private pendingResponses; | ||
/** @internal */ | ||
@@ -48,2 +52,3 @@ constructor(sid: string, identity: string, engine: RTCEngine, options: InternalRoomOptions); | ||
private handleSignalRequestResponse; | ||
private handleDataPacket; | ||
/** | ||
@@ -156,2 +161,42 @@ * Sets and updates the metadata of the local participant. | ||
/** | ||
* Initiate an RPC call to a remote participant | ||
* @param params - Parameters for initiating the RPC call, see {@link PerformRpcParams} | ||
* @returns A promise that resolves with the response payload or rejects with an error. | ||
* @throws Error on failure. Details in `message`. | ||
*/ | ||
performRpc({ destinationIdentity, method, payload, responseTimeout, }: PerformRpcParams): Promise<string>; | ||
/** | ||
* Establishes the participant as a receiver for calls of the specified RPC method. | ||
* Will overwrite any existing callback for the same method. | ||
* | ||
* @param method - The name of the indicated RPC method | ||
* @param handler - Will be invoked when an RPC request for this method is received | ||
* @returns A promise that resolves when the method is successfully registered | ||
* | ||
* @example | ||
* ```typescript | ||
* room.localParticipant?.registerRpcMethod( | ||
* 'greet', | ||
* async (data: RpcInvocationData) => { | ||
* console.log(`Received greeting from ${data.callerIdentity}: ${data.payload}`); | ||
* return `Hello, ${data.callerIdentity}!`; | ||
* } | ||
* ); | ||
* ``` | ||
* | ||
* The handler should return a Promise that resolves to a string. | ||
* If unable to respond within `responseTimeout`, the request will result in an error on the caller's side. | ||
* | ||
* You may throw errors of type `RpcError` with a string `message` in the handler, | ||
* and they will be received on the caller's side with the message intact. | ||
* Other errors thrown in your handler will not be transmitted as-is, and will instead arrive to the caller as `1500` ("Application Error"). | ||
*/ | ||
registerRpcMethod(method: string, handler: (data: RpcInvocationData) => Promise<string>): void; | ||
/** | ||
* Unregisters a previously registered RPC method. | ||
* | ||
* @param method - The name of the RPC method to unregister | ||
*/ | ||
unregisterRpcMethod(method: string): void; | ||
/** | ||
* Control who can subscribe to LocalParticipant's published tracks. | ||
@@ -174,3 +219,14 @@ * | ||
setTrackSubscriptionPermissions(allParticipantsAllowed: boolean, participantTrackPermissions?: ParticipantTrackPermission[]): void; | ||
private handleIncomingRpcAck; | ||
private handleIncomingRpcResponse; | ||
private handleIncomingRpcRequest; | ||
/** @internal */ | ||
private publishRpcRequest; | ||
/** @internal */ | ||
private publishRpcResponse; | ||
/** @internal */ | ||
private publishRpcAck; | ||
/** @internal */ | ||
handleParticipantDisconnected(participantIdentity: string): void; | ||
/** @internal */ | ||
setEnabledPublishCodecs(codecs: Codec[]): void; | ||
@@ -177,0 +233,0 @@ /** @internal */ |
@@ -22,2 +22,3 @@ import { EventEmitter } from 'events'; | ||
private loggerOptions; | ||
private ddExtID; | ||
pendingCandidates: RTCIceCandidateInit[]; | ||
@@ -67,4 +68,5 @@ restartingIce: boolean; | ||
private setMungedSDP; | ||
private ensureVideoDDExtensionForSVC; | ||
} | ||
export {}; | ||
//# sourceMappingURL=PCTransport.d.ts.map |
import { TrackPublishedResponse } from '@livekit/protocol'; | ||
import { Track } from './Track'; | ||
import type { TrackPublication } from './TrackPublication'; | ||
import { type AudioCaptureOptions, type CreateLocalTracksOptions, type ScreenShareCaptureOptions, type VideoCaptureOptions } from './options'; | ||
import { type AudioCaptureOptions, type CreateLocalTracksOptions, type ScreenShareCaptureOptions, type VideoCaptureOptions, type VideoCodec } from './options'; | ||
import type { AudioTrack } from './types'; | ||
@@ -29,3 +29,3 @@ export declare function mergeDefaultOptions(options?: CreateLocalTracksOptions, audioDefaults?: AudioCaptureOptions, videoDefaults?: VideoCaptureOptions): CreateLocalTracksOptions; | ||
export declare function screenCaptureToDisplayMediaStreamOptions(options: ScreenShareCaptureOptions): DisplayMediaStreamOptions; | ||
export declare function mimeTypeToVideoCodecString(mimeType: string): "vp8" | "h264" | "vp9" | "av1"; | ||
export declare function mimeTypeToVideoCodecString(mimeType: string): VideoCodec; | ||
export declare function getTrackPublicationInfo<T extends TrackPublication>(tracks: T[]): TrackPublishedResponse[]; | ||
@@ -32,0 +32,0 @@ export declare function getLogContextFromTrack(track: Track | TrackPublication): Record<string, unknown>; |
@@ -26,2 +26,4 @@ import { Mutex } from '@livekit/mutex'; | ||
import { getBrowser } from './utils/browserParser'; | ||
export type { RpcInvocationData, PerformRpcParams } from './room/rpc'; | ||
export { RpcError } from './room/rpc'; | ||
export * from './connectionHelper/ConnectionCheck'; | ||
@@ -28,0 +30,0 @@ export * from './connectionHelper/checks/Checker'; |
import { Codec, ParticipantInfo, ParticipantPermission } from '@livekit/protocol'; | ||
import type { InternalRoomOptions } from '../../options'; | ||
import type RTCEngine from '../RTCEngine'; | ||
import type { PerformRpcParams, RpcInvocationData } from '../rpc'; | ||
import LocalTrack from '../track/LocalTrack'; | ||
@@ -32,2 +33,5 @@ import LocalTrackPublication from '../track/LocalTrackPublication'; | ||
private enabledPublishVideoCodecs; | ||
private rpcHandlers; | ||
private pendingAcks; | ||
private pendingResponses; | ||
/** @internal */ | ||
@@ -48,2 +52,3 @@ constructor(sid: string, identity: string, engine: RTCEngine, options: InternalRoomOptions); | ||
private handleSignalRequestResponse; | ||
private handleDataPacket; | ||
/** | ||
@@ -156,2 +161,42 @@ * Sets and updates the metadata of the local participant. | ||
/** | ||
* Initiate an RPC call to a remote participant | ||
* @param params - Parameters for initiating the RPC call, see {@link PerformRpcParams} | ||
* @returns A promise that resolves with the response payload or rejects with an error. | ||
* @throws Error on failure. Details in `message`. | ||
*/ | ||
performRpc({ destinationIdentity, method, payload, responseTimeout, }: PerformRpcParams): Promise<string>; | ||
/** | ||
* Establishes the participant as a receiver for calls of the specified RPC method. | ||
* Will overwrite any existing callback for the same method. | ||
* | ||
* @param method - The name of the indicated RPC method | ||
* @param handler - Will be invoked when an RPC request for this method is received | ||
* @returns A promise that resolves when the method is successfully registered | ||
* | ||
* @example | ||
* ```typescript | ||
* room.localParticipant?.registerRpcMethod( | ||
* 'greet', | ||
* async (data: RpcInvocationData) => { | ||
* console.log(`Received greeting from ${data.callerIdentity}: ${data.payload}`); | ||
* return `Hello, ${data.callerIdentity}!`; | ||
* } | ||
* ); | ||
* ``` | ||
* | ||
* The handler should return a Promise that resolves to a string. | ||
* If unable to respond within `responseTimeout`, the request will result in an error on the caller's side. | ||
* | ||
* You may throw errors of type `RpcError` with a string `message` in the handler, | ||
* and they will be received on the caller's side with the message intact. | ||
* Other errors thrown in your handler will not be transmitted as-is, and will instead arrive to the caller as `1500` ("Application Error"). | ||
*/ | ||
registerRpcMethod(method: string, handler: (data: RpcInvocationData) => Promise<string>): void; | ||
/** | ||
* Unregisters a previously registered RPC method. | ||
* | ||
* @param method - The name of the RPC method to unregister | ||
*/ | ||
unregisterRpcMethod(method: string): void; | ||
/** | ||
* Control who can subscribe to LocalParticipant's published tracks. | ||
@@ -174,3 +219,14 @@ * | ||
setTrackSubscriptionPermissions(allParticipantsAllowed: boolean, participantTrackPermissions?: ParticipantTrackPermission[]): void; | ||
private handleIncomingRpcAck; | ||
private handleIncomingRpcResponse; | ||
private handleIncomingRpcRequest; | ||
/** @internal */ | ||
private publishRpcRequest; | ||
/** @internal */ | ||
private publishRpcResponse; | ||
/** @internal */ | ||
private publishRpcAck; | ||
/** @internal */ | ||
handleParticipantDisconnected(participantIdentity: string): void; | ||
/** @internal */ | ||
setEnabledPublishCodecs(codecs: Codec[]): void; | ||
@@ -177,0 +233,0 @@ /** @internal */ |
@@ -22,2 +22,3 @@ import { EventEmitter } from 'events'; | ||
private loggerOptions; | ||
private ddExtID; | ||
pendingCandidates: RTCIceCandidateInit[]; | ||
@@ -69,4 +70,5 @@ restartingIce: boolean; | ||
private setMungedSDP; | ||
private ensureVideoDDExtensionForSVC; | ||
} | ||
export {}; | ||
//# sourceMappingURL=PCTransport.d.ts.map |
import { TrackPublishedResponse } from '@livekit/protocol'; | ||
import { Track } from './Track'; | ||
import type { TrackPublication } from './TrackPublication'; | ||
import type { AudioCaptureOptions, CreateLocalTracksOptions, ScreenShareCaptureOptions, VideoCaptureOptions } from './options'; | ||
import type { AudioCaptureOptions, CreateLocalTracksOptions, ScreenShareCaptureOptions, VideoCaptureOptions, VideoCodec } from './options'; | ||
import type { AudioTrack } from './types'; | ||
@@ -29,3 +29,3 @@ export declare function mergeDefaultOptions(options?: CreateLocalTracksOptions, audioDefaults?: AudioCaptureOptions, videoDefaults?: VideoCaptureOptions): CreateLocalTracksOptions; | ||
export declare function screenCaptureToDisplayMediaStreamOptions(options: ScreenShareCaptureOptions): DisplayMediaStreamOptions; | ||
export declare function mimeTypeToVideoCodecString(mimeType: string): "vp8" | "h264" | "vp9" | "av1"; | ||
export declare function mimeTypeToVideoCodecString(mimeType: string): VideoCodec; | ||
export declare function getTrackPublicationInfo<T extends TrackPublication>(tracks: T[]): TrackPublishedResponse[]; | ||
@@ -32,0 +32,0 @@ export declare function getLogContextFromTrack(track: Track | TrackPublication): Record<string, unknown>; |
{ | ||
"name": "livekit-client", | ||
"version": "2.5.10", | ||
"version": "2.6.0", | ||
"description": "JavaScript/TypeScript client SDK for LiveKit", | ||
@@ -91,3 +91,3 @@ "main": "./dist/livekit-client.umd.js", | ||
"build:worker:watch": "rollup --watch --config rollup.config.worker.js --bundleConfigAsCjs", | ||
"build-docs": "typedoc", | ||
"build-docs": "typedoc && mkdir -p docs/assets/github && cp .github/*.png docs/assets/github/ && find docs -name '*.html' -type f -exec sed -i.bak 's|=\"/.github/|=\"assets/github/|g' {} + && find docs -name '*.bak' -delete", | ||
"proto": "protoc --es_out src/proto --es_opt target=ts -I./protocol ./protocol/livekit_rtc.proto ./protocol/livekit_models.proto", | ||
@@ -94,0 +94,0 @@ "examples:demo": "vite examples/demo -c vite.config.mjs", |
@@ -307,2 +307,52 @@ <!--BEGIN_BANNER_IMAGE--> | ||
### RPC | ||
Perform your own predefined method calls from one participant to another. | ||
This feature is especially powerful when used with [Agents](https://docs.livekit.io/agents), for instance to forward LLM function calls to your client application. | ||
#### Registering an RPC method | ||
The participant who implements the method and will receive its calls must first register support: | ||
```typescript | ||
room.localParticipant?.registerRpcMethod( | ||
// method name - can be any string that makes sense for your application | ||
'greet', | ||
// method handler - will be called when the method is invoked by a RemoteParticipant | ||
async (data: RpcInvocationData) => { | ||
console.log(`Received greeting from ${data.callerIdentity}: ${data.payload}`); | ||
return `Hello, ${data.callerIdentity}!`; | ||
} | ||
); | ||
``` | ||
In addition to the payload, your handler will also receive `responseTimeout`, which informs you the maximum time available to return a response. If you are unable to respond in time, the call will result in an error on the caller's side. | ||
#### Performing an RPC request | ||
The caller may then initiate an RPC call like so: | ||
```typescript | ||
try { | ||
const response = await room.localParticipant!.performRpc({ | ||
destinationIdentity: 'recipient-identity', | ||
method: 'greet', | ||
payload: 'Hello from RPC!', | ||
}); | ||
console.log('RPC response:', response); | ||
} catch (error) { | ||
console.error('RPC call failed:', error); | ||
} | ||
``` | ||
You may find it useful to adjust the `responseTimeout` parameter, which indicates the amount of time you will wait for a response. We recommend keeping this value as low as possible while still satisfying the constraints of your application. | ||
#### Errors | ||
LiveKit is a dynamic realtime environment and calls can fail for various reasons. | ||
You may throw errors of the type `RpcError` with a string `message` in an RPC method handler and they will be received on the caller's side with the message intact. Other errors will not be transmitted and will instead arrive to the caller as `1500` ("Application Error"). Other built-in errors are detailed in `RpcError`. | ||
## Examples | ||
@@ -314,2 +364,6 @@ | ||
### RPC Demo | ||
[examples/rpc](examples/rpc/) contains a demo webapp that uses the SDK to showcase the RPC capabilities. Run it with `pnpm install && pnpm dev` from the `examples/rpc` directory. | ||
## Browser Support | ||
@@ -316,0 +370,0 @@ |
@@ -42,2 +42,4 @@ import { Mutex } from '@livekit/mutex'; | ||
export { RpcError, type RpcInvocationData, type PerformRpcParams } from './room/rpc'; | ||
export * from './connectionHelper/ConnectionCheck'; | ||
@@ -44,0 +46,0 @@ export * from './connectionHelper/checks/Checker'; |
import { EventEmitter } from 'events'; | ||
import type { MediaDescription } from 'sdp-transform'; | ||
import type { MediaDescription, SessionDescription } from 'sdp-transform'; | ||
import { parse, write } from 'sdp-transform'; | ||
@@ -51,2 +51,4 @@ import { debounce } from 'ts-debounce'; | ||
private ddExtID = 0; | ||
pendingCandidates: RTCIceCandidateInit[] = []; | ||
@@ -292,3 +294,3 @@ | ||
if (isSVCCodec(trackbr.codec)) { | ||
ensureVideoDDExtensionForSVC(media); | ||
this.ensureVideoDDExtensionForSVC(media, sdpParsed); | ||
} | ||
@@ -508,2 +510,40 @@ | ||
} | ||
private ensureVideoDDExtensionForSVC( | ||
media: { | ||
type: string; | ||
port: number; | ||
protocol: string; | ||
payloads?: string | undefined; | ||
} & MediaDescription, | ||
sdp: SessionDescription, | ||
) { | ||
const ddFound = media.ext?.some((ext): boolean => { | ||
if (ext.uri === ddExtensionURI) { | ||
return true; | ||
} | ||
return false; | ||
}); | ||
if (!ddFound) { | ||
if (this.ddExtID === 0) { | ||
let maxID = 0; | ||
sdp.media.forEach((m) => { | ||
if (m.type !== 'video') { | ||
return; | ||
} | ||
m.ext?.forEach((ext) => { | ||
if (ext.value > maxID) { | ||
maxID = ext.value; | ||
} | ||
}); | ||
}); | ||
this.ddExtID = maxID + 1; | ||
} | ||
media.ext?.push({ | ||
value: this.ddExtID, | ||
uri: ddExtensionURI, | ||
}); | ||
} | ||
} | ||
} | ||
@@ -561,29 +601,2 @@ | ||
function ensureVideoDDExtensionForSVC( | ||
media: { | ||
type: string; | ||
port: number; | ||
protocol: string; | ||
payloads?: string | undefined; | ||
} & MediaDescription, | ||
) { | ||
let maxID = 0; | ||
const ddFound = media.ext?.some((ext): boolean => { | ||
if (ext.uri === ddExtensionURI) { | ||
return true; | ||
} | ||
if (ext.value > maxID) { | ||
maxID = ext.value; | ||
} | ||
return false; | ||
}); | ||
if (!ddFound) { | ||
media.ext?.push({ | ||
value: maxID + 1, | ||
uri: ddExtensionURI, | ||
}); | ||
} | ||
} | ||
function extractStereoAndNackAudioFromOffer(offer: RTCSessionDescriptionInit): { | ||
@@ -590,0 +603,0 @@ stereoMids: string[]; |
@@ -12,3 +12,2 @@ import { TrackPublishedResponse } from '@livekit/protocol'; | ||
type VideoCodec, | ||
videoCodecs, | ||
} from './options'; | ||
@@ -192,7 +191,3 @@ import type { AudioTrack } from './types'; | ||
export function mimeTypeToVideoCodecString(mimeType: string) { | ||
const codec = mimeType.split('/')[1].toLowerCase() as VideoCodec; | ||
if (!videoCodecs.includes(codec)) { | ||
throw Error(`Video codec not supported: ${codec}`); | ||
} | ||
return codec; | ||
return mimeType.split('/')[1].toLowerCase() as VideoCodec; | ||
} | ||
@@ -199,0 +194,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
5916256
296
53749
399