@defcomm/meetingsdk 0.5.5 → 0.5.6
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/index.d.mts +60 -2
- package/dist/index.d.ts +60 -2
- package/dist/index.js +326 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +324 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -24,10 +24,12 @@ __export(index_exports, {
|
|
|
24
24
|
MeetingProvider: () => MeetingProvider,
|
|
25
25
|
MeetingState: () => MeetingState,
|
|
26
26
|
VideoSDKCore: () => VideoSDKCore,
|
|
27
|
+
useLiveTranscript: () => useLiveTranscript,
|
|
27
28
|
useLocalParticipant: () => useLocalParticipant,
|
|
28
29
|
useMeeting: () => useMeeting,
|
|
29
30
|
useMeetingContext: () => useMeetingContext,
|
|
30
31
|
useMeetingPreview: () => useMeetingPreview,
|
|
32
|
+
useNetworkQuality: () => useNetworkQuality,
|
|
31
33
|
useParticipants: () => useParticipants,
|
|
32
34
|
usePubSub: () => usePubSub,
|
|
33
35
|
useRemoteMedia: () => useRemoteMedia
|
|
@@ -227,6 +229,8 @@ var MeetingState = class {
|
|
|
227
229
|
this.presenterId = null;
|
|
228
230
|
this.activeSpeakerIds = /* @__PURE__ */ new Set();
|
|
229
231
|
this.recording = null;
|
|
232
|
+
this.liveTranscripts = [];
|
|
233
|
+
this.networkQuality = null;
|
|
230
234
|
this.listeners = /* @__PURE__ */ new Map();
|
|
231
235
|
}
|
|
232
236
|
// ---- reactive system ----
|
|
@@ -264,6 +268,21 @@ var MeetingState = class {
|
|
|
264
268
|
this.recording = null;
|
|
265
269
|
this.notify("recording");
|
|
266
270
|
}
|
|
271
|
+
addLiveTranscript(transcript) {
|
|
272
|
+
this.liveTranscripts = [...this.liveTranscripts.slice(-499), transcript];
|
|
273
|
+
this.notify("transcript");
|
|
274
|
+
}
|
|
275
|
+
getLiveTranscripts() {
|
|
276
|
+
return this.liveTranscripts;
|
|
277
|
+
}
|
|
278
|
+
clearLiveTranscripts() {
|
|
279
|
+
this.liveTranscripts = [];
|
|
280
|
+
this.notify("transcript");
|
|
281
|
+
}
|
|
282
|
+
setNetworkQuality(quality) {
|
|
283
|
+
this.networkQuality = quality;
|
|
284
|
+
this.notify("networkQuality");
|
|
285
|
+
}
|
|
267
286
|
// ---- participants ----
|
|
268
287
|
addParticipant(p) {
|
|
269
288
|
if (this.participants.has(p.id)) return false;
|
|
@@ -384,10 +403,14 @@ var MeetingState = class {
|
|
|
384
403
|
this.chatMessages.clear();
|
|
385
404
|
this.presenterId = null;
|
|
386
405
|
this.activeSpeakerIds = /* @__PURE__ */ new Set();
|
|
406
|
+
this.liveTranscripts = [];
|
|
407
|
+
this.networkQuality = null;
|
|
387
408
|
this.notify("participants");
|
|
388
409
|
this.notify("chat");
|
|
389
410
|
this.notify("presenter");
|
|
390
411
|
this.notify("activeSpeakers");
|
|
412
|
+
this.notify("transcript");
|
|
413
|
+
this.notify("networkQuality");
|
|
391
414
|
}
|
|
392
415
|
};
|
|
393
416
|
|
|
@@ -449,6 +472,12 @@ var SFUClient = class {
|
|
|
449
472
|
this.trackToSource = /* @__PURE__ */ new Map();
|
|
450
473
|
this.localTrackIds = /* @__PURE__ */ new Map();
|
|
451
474
|
this.subscriberStatsTimer = null;
|
|
475
|
+
this.liveTranscriptionActive = false;
|
|
476
|
+
this.liveTranscriptionSequence = 0;
|
|
477
|
+
this.liveTranscriptionStartedAt = 0;
|
|
478
|
+
this.liveTranscriptionRecorder = null;
|
|
479
|
+
this.liveTranscriptionLoopPromise = null;
|
|
480
|
+
this.networkProfile = null;
|
|
452
481
|
this.heartbeatTimer = null;
|
|
453
482
|
this.apiBase = options.apiBase || "https://api.example.com/api";
|
|
454
483
|
this.wsBase = options.wsBase || "wss://api.example.com/ws";
|
|
@@ -505,6 +534,10 @@ var SFUClient = class {
|
|
|
505
534
|
});
|
|
506
535
|
this.onRoomUpdate = options.onRoomUpdate || (() => {
|
|
507
536
|
});
|
|
537
|
+
this.onLiveTranscript = options.onLiveTranscript || (() => {
|
|
538
|
+
});
|
|
539
|
+
this.onNetworkQuality = options.onNetworkQuality || (() => {
|
|
540
|
+
});
|
|
508
541
|
this.onParticipantMediaState = options.onParticipantMediaState || (() => {
|
|
509
542
|
});
|
|
510
543
|
this.autoSubscribe = options.autoSubscribe !== false;
|
|
@@ -1099,6 +1132,40 @@ var SFUClient = class {
|
|
|
1099
1132
|
if (reaction?.id && reaction?.emoji) this.onReaction(reaction);
|
|
1100
1133
|
break;
|
|
1101
1134
|
}
|
|
1135
|
+
case "live_transcript": {
|
|
1136
|
+
const transcript = {
|
|
1137
|
+
transcript_id: String(payload.transcript_id),
|
|
1138
|
+
participant_id: String(payload.participant_id),
|
|
1139
|
+
speaker_name: payload.speaker_name ?? null,
|
|
1140
|
+
sequence: Number(payload.sequence ?? 0),
|
|
1141
|
+
text: String(payload.text ?? ""),
|
|
1142
|
+
offset_ms: payload.offset_ms == null ? null : Number(payload.offset_ms),
|
|
1143
|
+
start_ms: payload.start_ms == null ? null : Number(payload.start_ms),
|
|
1144
|
+
end_ms: payload.end_ms == null ? null : Number(payload.end_ms),
|
|
1145
|
+
timestamp: String(payload.timestamp ?? (/* @__PURE__ */ new Date()).toISOString())
|
|
1146
|
+
};
|
|
1147
|
+
if (transcript.text.trim()) this.onLiveTranscript(transcript);
|
|
1148
|
+
break;
|
|
1149
|
+
}
|
|
1150
|
+
case "network_quality": {
|
|
1151
|
+
const raw = payload.quality || payload;
|
|
1152
|
+
const quality = {
|
|
1153
|
+
participant_id: String(raw.participant_id ?? this.currentParticipantId ?? this.participantId),
|
|
1154
|
+
quality: String(raw.quality ?? "unknown"),
|
|
1155
|
+
score: Number(raw.score ?? 0),
|
|
1156
|
+
recommended_action: String(raw.recommended_action ?? "maintain"),
|
|
1157
|
+
packet_loss_percent: Number(raw.packet_loss_percent ?? 0),
|
|
1158
|
+
upload_kbps: Number(raw.upload_kbps ?? 0),
|
|
1159
|
+
forwarded_drop_percent: Number(raw.forwarded_drop_percent ?? 0),
|
|
1160
|
+
queued_packets: Number(raw.queued_packets ?? 0),
|
|
1161
|
+
packets_received: Number(raw.packets_received ?? 0),
|
|
1162
|
+
packets_lost: Number(raw.packets_lost ?? 0),
|
|
1163
|
+
observed_at: String(raw.observed_at ?? (/* @__PURE__ */ new Date()).toISOString())
|
|
1164
|
+
};
|
|
1165
|
+
this.onNetworkQuality(quality);
|
|
1166
|
+
void this.applyNetworkRecommendation(quality.recommended_action);
|
|
1167
|
+
break;
|
|
1168
|
+
}
|
|
1102
1169
|
case "error": {
|
|
1103
1170
|
const message2 = payload.message || "SFU signaling error";
|
|
1104
1171
|
if (this.state === "reconnecting" && message2.includes("participant session is stale")) {
|
|
@@ -1758,6 +1825,147 @@ var SFUClient = class {
|
|
|
1758
1825
|
}
|
|
1759
1826
|
});
|
|
1760
1827
|
}
|
|
1828
|
+
getLiveTranscriptionMimeType() {
|
|
1829
|
+
if (typeof MediaRecorder === "undefined") {
|
|
1830
|
+
throw new Error("MediaRecorder is not supported by this browser");
|
|
1831
|
+
}
|
|
1832
|
+
const candidates = [
|
|
1833
|
+
"audio/webm;codecs=opus",
|
|
1834
|
+
"audio/webm",
|
|
1835
|
+
"audio/ogg;codecs=opus"
|
|
1836
|
+
];
|
|
1837
|
+
return candidates.find((type) => MediaRecorder.isTypeSupported(type)) || "";
|
|
1838
|
+
}
|
|
1839
|
+
async startLiveTranscription(audioTrack, speakerName) {
|
|
1840
|
+
if (this.liveTranscriptionActive) return;
|
|
1841
|
+
if (!this.room) throw new Error("Cannot start live transcription without a room");
|
|
1842
|
+
if (!this.authToken) throw new Error("Cannot start live transcription without an authenticated token");
|
|
1843
|
+
if (!audioTrack || audioTrack.kind !== "audio") {
|
|
1844
|
+
throw new Error("A live microphone audio track is required");
|
|
1845
|
+
}
|
|
1846
|
+
const mimeType = this.getLiveTranscriptionMimeType();
|
|
1847
|
+
this.liveTranscriptionActive = true;
|
|
1848
|
+
this.liveTranscriptionSequence = 0;
|
|
1849
|
+
this.liveTranscriptionStartedAt = Date.now();
|
|
1850
|
+
const stream = new MediaStream([audioTrack]);
|
|
1851
|
+
this.liveTranscriptionLoopPromise = this.runLiveTranscriptionLoop(
|
|
1852
|
+
stream,
|
|
1853
|
+
mimeType
|
|
1854
|
+
).finally(() => {
|
|
1855
|
+
this.liveTranscriptionRecorder = null;
|
|
1856
|
+
this.liveTranscriptionLoopPromise = null;
|
|
1857
|
+
});
|
|
1858
|
+
void speakerName;
|
|
1859
|
+
await Promise.resolve();
|
|
1860
|
+
}
|
|
1861
|
+
async captureLiveChunk(stream, mimeType) {
|
|
1862
|
+
return new Promise((resolve, reject) => {
|
|
1863
|
+
const chunks = [];
|
|
1864
|
+
const recorder = mimeType ? new MediaRecorder(stream, { mimeType }) : new MediaRecorder(stream);
|
|
1865
|
+
this.liveTranscriptionRecorder = recorder;
|
|
1866
|
+
const timeout = setTimeout(() => {
|
|
1867
|
+
if (recorder.state !== "inactive") recorder.stop();
|
|
1868
|
+
}, 4500);
|
|
1869
|
+
recorder.ondataavailable = (event) => {
|
|
1870
|
+
if (event.data.size > 0) chunks.push(event.data);
|
|
1871
|
+
};
|
|
1872
|
+
recorder.onerror = () => {
|
|
1873
|
+
clearTimeout(timeout);
|
|
1874
|
+
reject(new Error("Live transcription recorder failed"));
|
|
1875
|
+
};
|
|
1876
|
+
recorder.onstop = () => {
|
|
1877
|
+
clearTimeout(timeout);
|
|
1878
|
+
this.liveTranscriptionRecorder = null;
|
|
1879
|
+
resolve(
|
|
1880
|
+
chunks.length ? new Blob(chunks, { type: recorder.mimeType || mimeType || "audio/webm" }) : null
|
|
1881
|
+
);
|
|
1882
|
+
};
|
|
1883
|
+
recorder.start();
|
|
1884
|
+
});
|
|
1885
|
+
}
|
|
1886
|
+
async runLiveTranscriptionLoop(stream, mimeType) {
|
|
1887
|
+
while (this.liveTranscriptionActive && stream.getAudioTracks()[0]?.readyState === "live") {
|
|
1888
|
+
try {
|
|
1889
|
+
const blob = await this.captureLiveChunk(stream, mimeType);
|
|
1890
|
+
if (!this.liveTranscriptionActive) break;
|
|
1891
|
+
if (!blob || blob.size === 0) continue;
|
|
1892
|
+
const sequence = this.liveTranscriptionSequence++;
|
|
1893
|
+
const offsetMs = Math.max(0, Date.now() - this.liveTranscriptionStartedAt);
|
|
1894
|
+
await this.uploadLiveTranscriptionChunk(blob, sequence, offsetMs, mimeType);
|
|
1895
|
+
} catch (error) {
|
|
1896
|
+
this.onError(error);
|
|
1897
|
+
await new Promise((resolve) => setTimeout(resolve, 750));
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
async uploadLiveTranscriptionChunk(blob, sequence, offsetMs, mimeType) {
|
|
1902
|
+
if (!this.room || !this.authToken) return;
|
|
1903
|
+
const form = new FormData();
|
|
1904
|
+
form.append("sequence", String(sequence));
|
|
1905
|
+
form.append("offset_ms", String(offsetMs));
|
|
1906
|
+
const extension = mimeType.includes("ogg") || blob.type.includes("ogg") ? "ogg" : "webm";
|
|
1907
|
+
form.append("audio", blob, `live-${sequence}.${extension}`);
|
|
1908
|
+
const response = await fetch(
|
|
1909
|
+
`${this.apiBase}/rooms/${encodeURIComponent(this.room)}/live-transcription`,
|
|
1910
|
+
{
|
|
1911
|
+
method: "POST",
|
|
1912
|
+
headers: {
|
|
1913
|
+
Authorization: `Bearer ${this.authToken}`,
|
|
1914
|
+
Accept: "application/json"
|
|
1915
|
+
},
|
|
1916
|
+
body: form
|
|
1917
|
+
}
|
|
1918
|
+
);
|
|
1919
|
+
if (!response.ok) {
|
|
1920
|
+
let detail = `Live transcription request failed: ${response.status}`;
|
|
1921
|
+
try {
|
|
1922
|
+
const body = await response.json();
|
|
1923
|
+
detail = body?.message || body?.detail || detail;
|
|
1924
|
+
} catch {
|
|
1925
|
+
}
|
|
1926
|
+
throw new Error(detail);
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
stopLiveTranscription() {
|
|
1930
|
+
this.liveTranscriptionActive = false;
|
|
1931
|
+
try {
|
|
1932
|
+
if (this.liveTranscriptionRecorder?.state !== "inactive") {
|
|
1933
|
+
this.liveTranscriptionRecorder?.stop();
|
|
1934
|
+
}
|
|
1935
|
+
} catch {
|
|
1936
|
+
}
|
|
1937
|
+
this.liveTranscriptionRecorder = null;
|
|
1938
|
+
}
|
|
1939
|
+
isLiveTranscriptionActive() {
|
|
1940
|
+
return this.liveTranscriptionActive;
|
|
1941
|
+
}
|
|
1942
|
+
async applyNetworkRecommendation(action) {
|
|
1943
|
+
if (!this.videoSender || this.networkProfile === action) return;
|
|
1944
|
+
const params = this.videoSender.getParameters();
|
|
1945
|
+
const encodings = params.encodings?.length ? params.encodings : [{}];
|
|
1946
|
+
const encoding = encodings[0];
|
|
1947
|
+
switch (action) {
|
|
1948
|
+
case "reduce_video":
|
|
1949
|
+
encoding.maxBitrate = 7e5;
|
|
1950
|
+
encoding.maxFramerate = 20;
|
|
1951
|
+
break;
|
|
1952
|
+
case "audio_priority":
|
|
1953
|
+
encoding.maxBitrate = 35e4;
|
|
1954
|
+
encoding.maxFramerate = 10;
|
|
1955
|
+
break;
|
|
1956
|
+
default:
|
|
1957
|
+
encoding.maxBitrate = 15e5;
|
|
1958
|
+
encoding.maxFramerate = 30;
|
|
1959
|
+
break;
|
|
1960
|
+
}
|
|
1961
|
+
params.encodings = encodings;
|
|
1962
|
+
try {
|
|
1963
|
+
await this.videoSender.setParameters(params);
|
|
1964
|
+
this.networkProfile = action;
|
|
1965
|
+
} catch (error) {
|
|
1966
|
+
this.onError(error);
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1761
1969
|
async startRecording() {
|
|
1762
1970
|
if (!this.send({ type: "start_recording" })) {
|
|
1763
1971
|
throw new Error("SFU signaling is not connected");
|
|
@@ -1890,6 +2098,7 @@ var SFUClient = class {
|
|
|
1890
2098
|
}
|
|
1891
2099
|
}
|
|
1892
2100
|
async leave() {
|
|
2101
|
+
this.stopLiveTranscription();
|
|
1893
2102
|
this.stopHeartbeat();
|
|
1894
2103
|
this.intentionalClose = true;
|
|
1895
2104
|
this.setState("leaving");
|
|
@@ -2298,6 +2507,14 @@ var VideoSDKCore = class {
|
|
|
2298
2507
|
console.warn(`[SFU] Reconnecting, attempt ${attempt}`);
|
|
2299
2508
|
},
|
|
2300
2509
|
// ADMISSION CONTROL
|
|
2510
|
+
onLiveTranscript: (transcript) => {
|
|
2511
|
+
this.state.addLiveTranscript(transcript);
|
|
2512
|
+
this.events.onLiveTranscript?.(transcript);
|
|
2513
|
+
},
|
|
2514
|
+
onNetworkQuality: (quality) => {
|
|
2515
|
+
this.state.setNetworkQuality(quality);
|
|
2516
|
+
this.events.onNetworkQuality?.(quality);
|
|
2517
|
+
},
|
|
2301
2518
|
onRoomUpdate: (payload) => {
|
|
2302
2519
|
const participants = payload?.participants || [];
|
|
2303
2520
|
const local = participants.find(
|
|
@@ -2942,6 +3159,28 @@ var VideoSDKCore = class {
|
|
|
2942
3159
|
}
|
|
2943
3160
|
}
|
|
2944
3161
|
}
|
|
3162
|
+
async startLiveTranscription() {
|
|
3163
|
+
if (!this.sfuClient) {
|
|
3164
|
+
throw new Error("SFU client is not connected");
|
|
3165
|
+
}
|
|
3166
|
+
const audioTrack = this.localStream?.getAudioTracks()[0];
|
|
3167
|
+
if (!audioTrack) {
|
|
3168
|
+
throw new Error("Microphone audio track is not available");
|
|
3169
|
+
}
|
|
3170
|
+
await this.sfuClient.startLiveTranscription(
|
|
3171
|
+
audioTrack,
|
|
3172
|
+
this.participantName
|
|
3173
|
+
);
|
|
3174
|
+
}
|
|
3175
|
+
stopLiveTranscription() {
|
|
3176
|
+
this.sfuClient?.stopLiveTranscription();
|
|
3177
|
+
}
|
|
3178
|
+
isLiveTranscriptionActive() {
|
|
3179
|
+
return this.sfuClient?.isLiveTranscriptionActive() ?? false;
|
|
3180
|
+
}
|
|
3181
|
+
getNetworkQuality() {
|
|
3182
|
+
return this.state.networkQuality;
|
|
3183
|
+
}
|
|
2945
3184
|
// CLEANUP
|
|
2946
3185
|
cleanupRemoteParticipant(participantId) {
|
|
2947
3186
|
this.activeSpeakerDetector.removeParticipant(participantId);
|
|
@@ -2990,6 +3229,8 @@ var VideoSDKCore = class {
|
|
|
2990
3229
|
this.room.id = null;
|
|
2991
3230
|
this.room.name = null;
|
|
2992
3231
|
this.state.localParticipant = null;
|
|
3232
|
+
this.state.clearLiveTranscripts();
|
|
3233
|
+
this.state.setNetworkQuality(null);
|
|
2993
3234
|
this.state.notify("localParticipant");
|
|
2994
3235
|
this.state.resetRemoteState();
|
|
2995
3236
|
this.events.onMeetingLeft?.();
|
|
@@ -3022,9 +3263,15 @@ var MeetingProvider = ({
|
|
|
3022
3263
|
const entryResponseListeners = (0, import_react2.useRef)(
|
|
3023
3264
|
/* @__PURE__ */ new Set()
|
|
3024
3265
|
);
|
|
3025
|
-
const joinRequestCanceledListeners = (0, import_react2.useRef)(
|
|
3026
|
-
|
|
3027
|
-
|
|
3266
|
+
const joinRequestCanceledListeners = (0, import_react2.useRef)(
|
|
3267
|
+
/* @__PURE__ */ new Set()
|
|
3268
|
+
);
|
|
3269
|
+
const participantRemovedListeners = (0, import_react2.useRef)(
|
|
3270
|
+
/* @__PURE__ */ new Set()
|
|
3271
|
+
);
|
|
3272
|
+
const participantPermissionsChangedListeners = (0, import_react2.useRef)(
|
|
3273
|
+
/* @__PURE__ */ new Set()
|
|
3274
|
+
);
|
|
3028
3275
|
const meetingLeftListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
|
|
3029
3276
|
const trackStateListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
|
|
3030
3277
|
const recordingStartedListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
|
|
@@ -3037,6 +3284,12 @@ var MeetingProvider = ({
|
|
|
3037
3284
|
const activeSpeakerListeners = (0, import_react2.useRef)(
|
|
3038
3285
|
/* @__PURE__ */ new Set()
|
|
3039
3286
|
);
|
|
3287
|
+
const liveTranscriptListeners = (0, import_react2.useRef)(
|
|
3288
|
+
/* @__PURE__ */ new Set()
|
|
3289
|
+
);
|
|
3290
|
+
const networkQualityListeners = (0, import_react2.useRef)(
|
|
3291
|
+
/* @__PURE__ */ new Set()
|
|
3292
|
+
);
|
|
3040
3293
|
const connectionStateListeners = (0, import_react2.useRef)(
|
|
3041
3294
|
/* @__PURE__ */ new Set()
|
|
3042
3295
|
);
|
|
@@ -3060,10 +3313,14 @@ var MeetingProvider = ({
|
|
|
3060
3313
|
joinRequestCanceledListeners.current.forEach((fn) => fn(requestId));
|
|
3061
3314
|
},
|
|
3062
3315
|
onParticipantRemoved: (participantId, removedBy) => {
|
|
3063
|
-
participantRemovedListeners.current.forEach(
|
|
3316
|
+
participantRemovedListeners.current.forEach(
|
|
3317
|
+
(fn) => fn(participantId, removedBy)
|
|
3318
|
+
);
|
|
3064
3319
|
},
|
|
3065
3320
|
onParticipantPermissionsChanged: (participantId, permissions) => {
|
|
3066
|
-
participantPermissionsChangedListeners.current.forEach(
|
|
3321
|
+
participantPermissionsChangedListeners.current.forEach(
|
|
3322
|
+
(fn) => fn(participantId, permissions)
|
|
3323
|
+
);
|
|
3067
3324
|
},
|
|
3068
3325
|
onMeetingLeft: () => {
|
|
3069
3326
|
meetingLeftListeners.current.forEach((fn) => fn());
|
|
@@ -3116,6 +3373,12 @@ var MeetingProvider = ({
|
|
|
3116
3373
|
);
|
|
3117
3374
|
pubSubListeners.current.get("REACTION")?.forEach((fn) => fn(message));
|
|
3118
3375
|
},
|
|
3376
|
+
onLiveTranscript: (transcript) => {
|
|
3377
|
+
liveTranscriptListeners.current.forEach((fn) => fn(transcript));
|
|
3378
|
+
},
|
|
3379
|
+
onNetworkQuality: (quality) => {
|
|
3380
|
+
networkQualityListeners.current.forEach((fn) => fn(quality));
|
|
3381
|
+
},
|
|
3119
3382
|
onConnectionStateChanged: (state) => {
|
|
3120
3383
|
connectionStateListeners.current.forEach(
|
|
3121
3384
|
(fn) => fn(state)
|
|
@@ -3151,6 +3414,16 @@ var MeetingProvider = ({
|
|
|
3151
3414
|
"chat",
|
|
3152
3415
|
(s) => s.getChatMessages()
|
|
3153
3416
|
);
|
|
3417
|
+
const liveTranscripts = useMeetingStore(
|
|
3418
|
+
sdk.state,
|
|
3419
|
+
"transcript",
|
|
3420
|
+
(s) => s.getLiveTranscripts()
|
|
3421
|
+
);
|
|
3422
|
+
const networkQuality = useMeetingStore(
|
|
3423
|
+
sdk.state,
|
|
3424
|
+
"networkQuality",
|
|
3425
|
+
(s) => s.networkQuality
|
|
3426
|
+
);
|
|
3154
3427
|
const value = (0, import_react2.useMemo)(() => {
|
|
3155
3428
|
return {
|
|
3156
3429
|
sdk,
|
|
@@ -3175,6 +3448,11 @@ var MeetingProvider = ({
|
|
|
3175
3448
|
messages,
|
|
3176
3449
|
presenterId,
|
|
3177
3450
|
activeSpeakerIds,
|
|
3451
|
+
liveTranscripts,
|
|
3452
|
+
networkQuality,
|
|
3453
|
+
startLiveTranscription: sdk.startLiveTranscription.bind(sdk),
|
|
3454
|
+
stopLiveTranscription: sdk.stopLiveTranscription.bind(sdk),
|
|
3455
|
+
isLiveTranscriptionActive: sdk.isLiveTranscriptionActive.bind(sdk),
|
|
3178
3456
|
recording,
|
|
3179
3457
|
usePubSub: (topic) => {
|
|
3180
3458
|
if (topic === "SECURE_CHAT") {
|
|
@@ -3293,6 +3571,14 @@ var MeetingProvider = ({
|
|
|
3293
3571
|
reactionListeners.current.add(cb);
|
|
3294
3572
|
return () => reactionListeners.current.delete(cb);
|
|
3295
3573
|
},
|
|
3574
|
+
onLiveTranscript: (cb) => {
|
|
3575
|
+
liveTranscriptListeners.current.add(cb);
|
|
3576
|
+
return () => liveTranscriptListeners.current.delete(cb);
|
|
3577
|
+
},
|
|
3578
|
+
onNetworkQuality: (cb) => {
|
|
3579
|
+
networkQualityListeners.current.add(cb);
|
|
3580
|
+
return () => networkQualityListeners.current.delete(cb);
|
|
3581
|
+
},
|
|
3296
3582
|
onConnectionStateChanged: (cb) => {
|
|
3297
3583
|
connectionStateListeners.current.add(cb);
|
|
3298
3584
|
return () => {
|
|
@@ -3315,6 +3601,8 @@ var MeetingProvider = ({
|
|
|
3315
3601
|
presenterId,
|
|
3316
3602
|
recording,
|
|
3317
3603
|
activeSpeakerIds,
|
|
3604
|
+
liveTranscripts,
|
|
3605
|
+
networkQuality,
|
|
3318
3606
|
reactionPubSubMessages
|
|
3319
3607
|
]);
|
|
3320
3608
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MeetingContext.Provider, { value, children });
|
|
@@ -3399,7 +3687,9 @@ var useMeeting = (handlers) => {
|
|
|
3399
3687
|
}, [handlers?.onParticipantRemoved]);
|
|
3400
3688
|
(0, import_react4.useEffect)(() => {
|
|
3401
3689
|
if (!handlers?.onParticipantPermissionsChanged) return;
|
|
3402
|
-
return ctx.onParticipantPermissionsChanged(
|
|
3690
|
+
return ctx.onParticipantPermissionsChanged(
|
|
3691
|
+
handlers.onParticipantPermissionsChanged
|
|
3692
|
+
);
|
|
3403
3693
|
}, [handlers?.onParticipantPermissionsChanged]);
|
|
3404
3694
|
(0, import_react4.useEffect)(() => {
|
|
3405
3695
|
if (!handlers?.onMeetingLeft) return;
|
|
@@ -3421,6 +3711,14 @@ var useMeeting = (handlers) => {
|
|
|
3421
3711
|
if (!handlers?.onConnectionStateChanged) return;
|
|
3422
3712
|
return ctx.onConnectionStateChanged(handlers.onConnectionStateChanged);
|
|
3423
3713
|
}, [handlers?.onConnectionStateChanged]);
|
|
3714
|
+
(0, import_react4.useEffect)(() => {
|
|
3715
|
+
if (!handlers?.onLiveTranscript) return;
|
|
3716
|
+
return ctx.onLiveTranscript(handlers.onLiveTranscript);
|
|
3717
|
+
}, [handlers?.onLiveTranscript]);
|
|
3718
|
+
(0, import_react4.useEffect)(() => {
|
|
3719
|
+
if (!handlers?.onNetworkQuality) return;
|
|
3720
|
+
return ctx.onNetworkQuality(handlers.onNetworkQuality);
|
|
3721
|
+
}, [handlers?.onNetworkQuality]);
|
|
3424
3722
|
(0, import_react4.useEffect)(() => {
|
|
3425
3723
|
if (!handlers?.onReaction) return;
|
|
3426
3724
|
return ctx.onReaction(handlers.onReaction);
|
|
@@ -3558,6 +3856,26 @@ function useMeetingPreview(roomId, participantId) {
|
|
|
3558
3856
|
};
|
|
3559
3857
|
}
|
|
3560
3858
|
|
|
3859
|
+
// src/react/useLiveTranscript.ts
|
|
3860
|
+
var useLiveTranscript = () => {
|
|
3861
|
+
const { sdk } = useMeetingContext();
|
|
3862
|
+
return useMeetingStore(
|
|
3863
|
+
sdk.state,
|
|
3864
|
+
"transcript",
|
|
3865
|
+
(state) => state.getLiveTranscripts()
|
|
3866
|
+
);
|
|
3867
|
+
};
|
|
3868
|
+
|
|
3869
|
+
// src/react/useNetworkQuality.ts
|
|
3870
|
+
var useNetworkQuality = () => {
|
|
3871
|
+
const { sdk } = useMeetingContext();
|
|
3872
|
+
return useMeetingStore(
|
|
3873
|
+
sdk.state,
|
|
3874
|
+
"networkQuality",
|
|
3875
|
+
(state) => state.networkQuality
|
|
3876
|
+
);
|
|
3877
|
+
};
|
|
3878
|
+
|
|
3561
3879
|
// src/react/usePubSub.ts
|
|
3562
3880
|
var import_react8 = require("react");
|
|
3563
3881
|
function usePubSub(topic, options) {
|
|
@@ -3577,10 +3895,12 @@ function usePubSub(topic, options) {
|
|
|
3577
3895
|
MeetingProvider,
|
|
3578
3896
|
MeetingState,
|
|
3579
3897
|
VideoSDKCore,
|
|
3898
|
+
useLiveTranscript,
|
|
3580
3899
|
useLocalParticipant,
|
|
3581
3900
|
useMeeting,
|
|
3582
3901
|
useMeetingContext,
|
|
3583
3902
|
useMeetingPreview,
|
|
3903
|
+
useNetworkQuality,
|
|
3584
3904
|
useParticipants,
|
|
3585
3905
|
usePubSub,
|
|
3586
3906
|
useRemoteMedia
|