livekit-client 2.1.1 → 2.1.2
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/livekit-client.esm.mjs +159 -7
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.umd.js +1 -1
- package/dist/livekit-client.umd.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +2 -1
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +5 -2
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/events.d.ts +20 -1
- package/dist/src/room/events.d.ts.map +1 -1
- package/dist/src/room/participant/Participant.d.ts +2 -1
- package/dist/src/room/participant/Participant.d.ts.map +1 -1
- package/dist/src/room/track/RemoteTrack.d.ts +1 -0
- package/dist/src/room/track/RemoteTrack.d.ts.map +1 -1
- package/dist/src/room/track/Track.d.ts +4 -0
- package/dist/src/room/track/Track.d.ts.map +1 -1
- package/dist/src/room/track/TrackPublication.d.ts +3 -1
- package/dist/src/room/track/TrackPublication.d.ts.map +1 -1
- package/dist/src/room/types.d.ts +8 -0
- package/dist/src/room/types.d.ts.map +1 -1
- package/dist/src/room/utils.d.ts +3 -1
- package/dist/src/room/utils.d.ts.map +1 -1
- package/dist/ts4.2/src/index.d.ts +1 -1
- package/dist/ts4.2/src/room/RTCEngine.d.ts +2 -1
- package/dist/ts4.2/src/room/Room.d.ts +5 -2
- package/dist/ts4.2/src/room/events.d.ts +20 -1
- package/dist/ts4.2/src/room/participant/Participant.d.ts +2 -1
- package/dist/ts4.2/src/room/track/RemoteTrack.d.ts +1 -0
- package/dist/ts4.2/src/room/track/Track.d.ts +4 -0
- package/dist/ts4.2/src/room/track/TrackPublication.d.ts +3 -1
- package/dist/ts4.2/src/room/types.d.ts +8 -0
- package/dist/ts4.2/src/room/utils.d.ts +3 -1
- package/package.json +8 -8
- package/src/index.ts +1 -1
- package/src/room/RTCEngine.ts +4 -0
- package/src/room/Room.ts +27 -1
- package/src/room/events.ts +23 -0
- package/src/room/participant/Participant.ts +5 -1
- package/src/room/track/RemoteTrack.ts +13 -0
- package/src/room/track/Track.ts +9 -0
- package/src/room/track/TrackPublication.ts +3 -1
- package/src/room/types.ts +9 -0
- package/src/room/utils.ts +17 -2
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "livekit-client",
|
3
|
-
"version": "2.1.
|
3
|
+
"version": "2.1.2",
|
4
4
|
"description": "JavaScript/TypeScript client SDK for LiveKit",
|
5
5
|
"main": "./dist/livekit-client.umd.js",
|
6
6
|
"unpkg": "./dist/livekit-client.umd.js",
|
@@ -36,7 +36,7 @@
|
|
36
36
|
"author": "David Zhao <david@davidzhao.com>",
|
37
37
|
"license": "Apache-2.0",
|
38
38
|
"dependencies": {
|
39
|
-
"@livekit/protocol": "1.
|
39
|
+
"@livekit/protocol": "1.15.0",
|
40
40
|
"events": "^3.3.0",
|
41
41
|
"loglevel": "^1.8.0",
|
42
42
|
"sdp-transform": "^2.14.1",
|
@@ -46,8 +46,8 @@
|
|
46
46
|
"webrtc-adapter": "^8.1.1"
|
47
47
|
},
|
48
48
|
"devDependencies": {
|
49
|
-
"@babel/core": "7.24.
|
50
|
-
"@babel/preset-env": "7.24.
|
49
|
+
"@babel/core": "7.24.5",
|
50
|
+
"@babel/preset-env": "7.24.5",
|
51
51
|
"@bufbuild/protoc-gen-es": "^1.3.0",
|
52
52
|
"@changesets/cli": "2.27.1",
|
53
53
|
"@livekit/changesets-changelog-github": "^0.0.4",
|
@@ -73,15 +73,15 @@
|
|
73
73
|
"gh-pages": "6.1.1",
|
74
74
|
"jsdom": "^24.0.0",
|
75
75
|
"prettier": "^3.0.0",
|
76
|
-
"rollup": "4.
|
76
|
+
"rollup": "4.17.2",
|
77
77
|
"rollup-plugin-delete": "^2.0.0",
|
78
78
|
"rollup-plugin-re": "1.0.7",
|
79
79
|
"rollup-plugin-typescript2": "0.36.0",
|
80
80
|
"size-limit": "^8.2.4",
|
81
|
-
"typedoc": "0.25.
|
81
|
+
"typedoc": "0.25.13",
|
82
82
|
"typedoc-plugin-no-inherit": "1.4.0",
|
83
|
-
"typescript": "5.4.
|
84
|
-
"vite": "5.
|
83
|
+
"typescript": "5.4.5",
|
84
|
+
"vite": "5.2.10",
|
85
85
|
"vitest": "^1.0.0"
|
86
86
|
},
|
87
87
|
"scripts": {
|
package/src/index.ts
CHANGED
@@ -44,7 +44,7 @@ export { facingModeFromDeviceLabel, facingModeFromLocalTrack } from './room/trac
|
|
44
44
|
export * from './room/track/options';
|
45
45
|
export * from './room/track/processor/types';
|
46
46
|
export * from './room/track/types';
|
47
|
-
export type { DataPublishOptions, SimulationScenario } from './room/types';
|
47
|
+
export type { DataPublishOptions, SimulationScenario, TranscriptionSegment } from './room/types';
|
48
48
|
export * from './version';
|
49
49
|
export {
|
50
50
|
ConnectionQuality,
|
package/src/room/RTCEngine.ts
CHANGED
@@ -23,6 +23,7 @@ import {
|
|
23
23
|
TrackInfo,
|
24
24
|
type TrackPublishedResponse,
|
25
25
|
TrackUnpublishedResponse,
|
26
|
+
Transcription,
|
26
27
|
UpdateSubscription,
|
27
28
|
UserPacket,
|
28
29
|
} from '@livekit/protocol';
|
@@ -634,6 +635,8 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
634
635
|
this.emit(EngineEvent.ActiveSpeakersUpdate, dp.value.value.speakers);
|
635
636
|
} else if (dp.value?.case === 'user') {
|
636
637
|
this.emit(EngineEvent.DataPacketReceived, dp.value.value, dp.kind);
|
638
|
+
} else if (dp.value?.case === 'transcription') {
|
639
|
+
this.emit(EngineEvent.TranscriptionReceived, dp.value.value);
|
637
640
|
}
|
638
641
|
} finally {
|
639
642
|
unlock();
|
@@ -1357,6 +1360,7 @@ export type EngineEventCallbacks = {
|
|
1357
1360
|
) => void;
|
1358
1361
|
activeSpeakersUpdate: (speakers: Array<SpeakerInfo>) => void;
|
1359
1362
|
dataPacketReceived: (userPacket: UserPacket, kind: DataPacket_Kind) => void;
|
1363
|
+
transcriptionReceived: (transcription: Transcription) => void;
|
1360
1364
|
transportsCreated: (publisher: PCTransport, subscriber: PCTransport) => void;
|
1361
1365
|
/** @internal */
|
1362
1366
|
trackSenderAdded: (track: Track, sender: RTCRtpSender) => void;
|
package/src/room/Room.ts
CHANGED
@@ -18,6 +18,8 @@ import {
|
|
18
18
|
TrackInfo,
|
19
19
|
TrackSource,
|
20
20
|
TrackType,
|
21
|
+
Transcription as TranscriptionModel,
|
22
|
+
TranscriptionSegment as TranscriptionSegmentModel,
|
21
23
|
UserPacket,
|
22
24
|
protoInt64,
|
23
25
|
} from '@livekit/protocol';
|
@@ -61,11 +63,12 @@ import type { TrackPublication } from './track/TrackPublication';
|
|
61
63
|
import type { TrackProcessor } from './track/processor/types';
|
62
64
|
import type { AdaptiveStreamSettings } from './track/types';
|
63
65
|
import { getNewAudioContext, sourceToKind } from './track/utils';
|
64
|
-
import type { SimulationOptions, SimulationScenario } from './types';
|
66
|
+
import type { SimulationOptions, SimulationScenario, TranscriptionSegment } from './types';
|
65
67
|
import {
|
66
68
|
Future,
|
67
69
|
Mutex,
|
68
70
|
createDummyVideoStreamTrack,
|
71
|
+
extractTranscriptionSegments,
|
69
72
|
getEmptyAudioStreamTrack,
|
70
73
|
isBrowserSupported,
|
71
74
|
isCloud,
|
@@ -330,6 +333,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
330
333
|
})
|
331
334
|
.on(EngineEvent.ActiveSpeakersUpdate, this.handleActiveSpeakersUpdate)
|
332
335
|
.on(EngineEvent.DataPacketReceived, this.handleDataPacket)
|
336
|
+
.on(EngineEvent.TranscriptionReceived, this.handleTranscription)
|
333
337
|
.on(EngineEvent.Resuming, () => {
|
334
338
|
this.clearConnectionReconcile();
|
335
339
|
this.isResuming = true;
|
@@ -1471,6 +1475,23 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
1471
1475
|
participant?.emit(ParticipantEvent.DataReceived, userPacket.payload, kind);
|
1472
1476
|
};
|
1473
1477
|
|
1478
|
+
bufferedSegments: Map<string, TranscriptionSegmentModel> = new Map();
|
1479
|
+
|
1480
|
+
private handleTranscription = (transcription: TranscriptionModel) => {
|
1481
|
+
// find the participant
|
1482
|
+
const participant =
|
1483
|
+
transcription.participantIdentity === this.localParticipant.identity
|
1484
|
+
? this.localParticipant
|
1485
|
+
: this.remoteParticipants.get(transcription.participantIdentity);
|
1486
|
+
const publication = participant?.trackPublications.get(transcription.trackId);
|
1487
|
+
|
1488
|
+
const segments = extractTranscriptionSegments(transcription);
|
1489
|
+
|
1490
|
+
publication?.emit(TrackEvent.TranscriptionReceived, segments);
|
1491
|
+
participant?.emit(ParticipantEvent.TranscriptionReceived, segments, publication);
|
1492
|
+
this.emit(RoomEvent.TranscriptionReceived, segments, participant, publication);
|
1493
|
+
};
|
1494
|
+
|
1474
1495
|
private handleAudioPlaybackStarted = () => {
|
1475
1496
|
if (this.canPlaybackAudio) {
|
1476
1497
|
return;
|
@@ -2071,6 +2092,11 @@ export type RoomEventCallbacks = {
|
|
2071
2092
|
kind?: DataPacket_Kind,
|
2072
2093
|
topic?: string,
|
2073
2094
|
) => void;
|
2095
|
+
transcriptionReceived: (
|
2096
|
+
transcription: TranscriptionSegment[],
|
2097
|
+
participant?: Participant,
|
2098
|
+
publication?: TrackPublication,
|
2099
|
+
) => void;
|
2074
2100
|
connectionQualityChanged: (quality: ConnectionQuality, participant: Participant) => void;
|
2075
2101
|
mediaDevicesError: (error: Error) => void;
|
2076
2102
|
trackStreamStateChanged: (
|
package/src/room/events.ts
CHANGED
@@ -197,6 +197,12 @@ export enum RoomEvent {
|
|
197
197
|
*/
|
198
198
|
DataReceived = 'dataReceived',
|
199
199
|
|
200
|
+
/**
|
201
|
+
* Transcription received from a participant's track.
|
202
|
+
* @beta
|
203
|
+
*/
|
204
|
+
TranscriptionReceived = 'transcriptionReceived',
|
205
|
+
|
200
206
|
/**
|
201
207
|
* Connection quality was changed for a Participant. It'll receive updates
|
202
208
|
* from the local participant, as well as any [[RemoteParticipant]]s that we are
|
@@ -402,6 +408,12 @@ export enum ParticipantEvent {
|
|
402
408
|
*/
|
403
409
|
DataReceived = 'dataReceived',
|
404
410
|
|
411
|
+
/**
|
412
|
+
* Transcription received from this participant as data source.
|
413
|
+
* @beta
|
414
|
+
*/
|
415
|
+
TranscriptionReceived = 'transcriptionReceived',
|
416
|
+
|
405
417
|
/**
|
406
418
|
* Has speaking status changed for the current participant
|
407
419
|
*
|
@@ -479,6 +491,7 @@ export enum EngineEvent {
|
|
479
491
|
MediaTrackAdded = 'mediaTrackAdded',
|
480
492
|
ActiveSpeakersUpdate = 'activeSpeakersUpdate',
|
481
493
|
DataPacketReceived = 'dataPacketReceived',
|
494
|
+
TranscriptionReceived = 'transcriptionReceived',
|
482
495
|
RTPVideoMapUpdate = 'rtpVideoMapUpdate',
|
483
496
|
DCBufferStatusChanged = 'dcBufferStatusChanged',
|
484
497
|
ParticipantUpdate = 'participantUpdate',
|
@@ -562,4 +575,14 @@ export enum TrackEvent {
|
|
562
575
|
* @internal
|
563
576
|
*/
|
564
577
|
AudioTrackFeatureUpdate = 'audioTrackFeatureUpdate',
|
578
|
+
|
579
|
+
/**
|
580
|
+
* @beta
|
581
|
+
*/
|
582
|
+
TranscriptionReceived = 'transcriptionReceived',
|
583
|
+
|
584
|
+
/**
|
585
|
+
* @experimental
|
586
|
+
*/
|
587
|
+
TimeSyncUpdate = 'timeSyncUpdate',
|
565
588
|
}
|
@@ -16,7 +16,7 @@ import type RemoteTrack from '../track/RemoteTrack';
|
|
16
16
|
import type RemoteTrackPublication from '../track/RemoteTrackPublication';
|
17
17
|
import { Track } from '../track/Track';
|
18
18
|
import type { TrackPublication } from '../track/TrackPublication';
|
19
|
-
import type { LoggerOptions } from '../types';
|
19
|
+
import type { LoggerOptions, TranscriptionSegment } from '../types';
|
20
20
|
|
21
21
|
export enum ConnectionQuality {
|
22
22
|
Excellent = 'excellent',
|
@@ -329,6 +329,10 @@ export type ParticipantEventCallbacks = {
|
|
329
329
|
participantMetadataChanged: (prevMetadata: string | undefined, participant?: any) => void;
|
330
330
|
participantNameChanged: (name: string) => void;
|
331
331
|
dataReceived: (payload: Uint8Array, kind: DataPacket_Kind) => void;
|
332
|
+
transcriptionReceived: (
|
333
|
+
transcription: TranscriptionSegment[],
|
334
|
+
publication?: TrackPublication,
|
335
|
+
) => void;
|
332
336
|
isSpeakingChanged: (speaking: boolean) => void;
|
333
337
|
connectionQualityChanged: (connectionQuality: ConnectionQuality) => void;
|
334
338
|
trackStreamStateChanged: (
|
@@ -77,7 +77,20 @@ export default abstract class RemoteTrack<
|
|
77
77
|
if (!this.monitorInterval) {
|
78
78
|
this.monitorInterval = setInterval(() => this.monitorReceiver(), monitorFrequency);
|
79
79
|
}
|
80
|
+
this.registerTimeSyncUpdate();
|
80
81
|
}
|
81
82
|
|
82
83
|
protected abstract monitorReceiver(): void;
|
84
|
+
|
85
|
+
registerTimeSyncUpdate() {
|
86
|
+
const loop = () => {
|
87
|
+
this.timeSyncHandle = requestAnimationFrame(() => loop());
|
88
|
+
const newTime = this.receiver?.getSynchronizationSources()[0]?.rtpTimestamp;
|
89
|
+
if (newTime && this.rtpTimestamp !== newTime) {
|
90
|
+
this.emit(TrackEvent.TimeSyncUpdate, newTime);
|
91
|
+
this.rtpTimestamp = newTime;
|
92
|
+
}
|
93
|
+
};
|
94
|
+
loop();
|
95
|
+
}
|
83
96
|
}
|
package/src/room/track/Track.ts
CHANGED
@@ -53,6 +53,9 @@ export abstract class Track<
|
|
53
53
|
*/
|
54
54
|
streamState: Track.StreamState = Track.StreamState.Active;
|
55
55
|
|
56
|
+
/** @internal */
|
57
|
+
rtpTimestamp: number | undefined;
|
58
|
+
|
56
59
|
protected _mediaStreamTrack: MediaStreamTrack;
|
57
60
|
|
58
61
|
protected _mediaStreamID: string;
|
@@ -63,6 +66,8 @@ export abstract class Track<
|
|
63
66
|
|
64
67
|
private loggerContextCb: LoggerOptions['loggerContextCb'];
|
65
68
|
|
69
|
+
protected timeSyncHandle: number | undefined;
|
70
|
+
|
66
71
|
protected _currentBitrate: number = 0;
|
67
72
|
|
68
73
|
protected monitorInterval?: ReturnType<typeof setInterval>;
|
@@ -255,6 +260,9 @@ export abstract class Track<
|
|
255
260
|
if (this.monitorInterval) {
|
256
261
|
clearInterval(this.monitorInterval);
|
257
262
|
}
|
263
|
+
if (this.timeSyncHandle) {
|
264
|
+
cancelAnimationFrame(this.timeSyncHandle);
|
265
|
+
}
|
258
266
|
}
|
259
267
|
|
260
268
|
/** @internal */
|
@@ -517,4 +525,5 @@ export type TrackEventCallbacks = {
|
|
517
525
|
upstreamResumed: (track: any) => void;
|
518
526
|
trackProcessorUpdate: (processor?: TrackProcessor<Track.Kind, any>) => void;
|
519
527
|
audioTrackFeatureUpdate: (track: any, feature: AudioTrackFeature, enabled: boolean) => void;
|
528
|
+
timeSyncUpdate: (timestamp: number) => void;
|
520
529
|
};
|
@@ -9,7 +9,7 @@ import { EventEmitter } from 'events';
|
|
9
9
|
import type TypedEventEmitter from 'typed-emitter';
|
10
10
|
import log, { LoggerNames, getLogger } from '../../logger';
|
11
11
|
import { TrackEvent } from '../events';
|
12
|
-
import type { LoggerOptions } from '../types';
|
12
|
+
import type { LoggerOptions, TranscriptionSegment } from '../types';
|
13
13
|
import LocalAudioTrack from './LocalAudioTrack';
|
14
14
|
import LocalVideoTrack from './LocalVideoTrack';
|
15
15
|
import RemoteAudioTrack from './RemoteAudioTrack';
|
@@ -174,4 +174,6 @@ export type PublicationEventCallbacks = {
|
|
174
174
|
prevStatus: TrackPublication.SubscriptionStatus,
|
175
175
|
) => void;
|
176
176
|
subscriptionFailed: (error: SubscriptionError) => void;
|
177
|
+
transcriptionReceived: (transcription: TranscriptionSegment[]) => void;
|
178
|
+
timeSyncUpdate: (timestamp: number) => void;
|
177
179
|
};
|
package/src/room/types.ts
CHANGED
@@ -55,3 +55,12 @@ export type LoggerOptions = {
|
|
55
55
|
loggerName?: string;
|
56
56
|
loggerContextCb?: () => Record<string, unknown>;
|
57
57
|
};
|
58
|
+
|
59
|
+
export interface TranscriptionSegment {
|
60
|
+
id: string;
|
61
|
+
text: string;
|
62
|
+
language: string;
|
63
|
+
startTime: number;
|
64
|
+
endTime: number;
|
65
|
+
final: boolean;
|
66
|
+
}
|
package/src/room/utils.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { ClientInfo, ClientInfo_SDK } from '@livekit/protocol';
|
1
|
+
import { ClientInfo, ClientInfo_SDK, Transcription as TranscriptionModel } from '@livekit/protocol';
|
2
2
|
import { getBrowser } from '../utils/browserParser';
|
3
3
|
import { protocolVersion, version } from '../version';
|
4
4
|
import CriticalTimers from './timers';
|
@@ -6,7 +6,7 @@ import type LocalAudioTrack from './track/LocalAudioTrack';
|
|
6
6
|
import type RemoteAudioTrack from './track/RemoteAudioTrack';
|
7
7
|
import { VideoCodec, videoCodecs } from './track/options';
|
8
8
|
import { getNewAudioContext } from './track/utils';
|
9
|
-
import type { LiveKitReactNativeInfo } from './types';
|
9
|
+
import type { LiveKitReactNativeInfo, TranscriptionSegment } from './types';
|
10
10
|
|
11
11
|
const separator = '|';
|
12
12
|
export const ddExtensionURI =
|
@@ -527,3 +527,18 @@ export function toHttpUrl(url: string): string {
|
|
527
527
|
}
|
528
528
|
return url;
|
529
529
|
}
|
530
|
+
|
531
|
+
export function extractTranscriptionSegments(
|
532
|
+
transcription: TranscriptionModel,
|
533
|
+
): TranscriptionSegment[] {
|
534
|
+
return transcription.segments.map(({ id, text, language, startTime, endTime, final }) => {
|
535
|
+
return {
|
536
|
+
id,
|
537
|
+
text,
|
538
|
+
startTime: Number.parseInt(startTime.toString()),
|
539
|
+
endTime: Number.parseInt(endTime.toString()),
|
540
|
+
final,
|
541
|
+
language,
|
542
|
+
};
|
543
|
+
});
|
544
|
+
}
|