@defcomm/meetingsdk 0.5.4 → 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 +328 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +326 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
|
|
13
13
|
// src/config/ws.ts
|
|
14
14
|
var SDK_CONFIG = {
|
|
15
|
-
apiBase: "https://
|
|
16
|
-
wsBase: "wss://
|
|
15
|
+
apiBase: "https://meetingsdk.defcomm.ng/api",
|
|
16
|
+
wsBase: "wss://meetingsdk.defcomm.ng/ws",
|
|
17
17
|
// Public STUN/TURN servers (fallback)
|
|
18
18
|
iceServers: [
|
|
19
19
|
{ urls: ["stun:stun.l.google.com:19302"] },
|
|
@@ -197,6 +197,8 @@ var MeetingState = class {
|
|
|
197
197
|
this.presenterId = null;
|
|
198
198
|
this.activeSpeakerIds = /* @__PURE__ */ new Set();
|
|
199
199
|
this.recording = null;
|
|
200
|
+
this.liveTranscripts = [];
|
|
201
|
+
this.networkQuality = null;
|
|
200
202
|
this.listeners = /* @__PURE__ */ new Map();
|
|
201
203
|
}
|
|
202
204
|
// ---- reactive system ----
|
|
@@ -234,6 +236,21 @@ var MeetingState = class {
|
|
|
234
236
|
this.recording = null;
|
|
235
237
|
this.notify("recording");
|
|
236
238
|
}
|
|
239
|
+
addLiveTranscript(transcript) {
|
|
240
|
+
this.liveTranscripts = [...this.liveTranscripts.slice(-499), transcript];
|
|
241
|
+
this.notify("transcript");
|
|
242
|
+
}
|
|
243
|
+
getLiveTranscripts() {
|
|
244
|
+
return this.liveTranscripts;
|
|
245
|
+
}
|
|
246
|
+
clearLiveTranscripts() {
|
|
247
|
+
this.liveTranscripts = [];
|
|
248
|
+
this.notify("transcript");
|
|
249
|
+
}
|
|
250
|
+
setNetworkQuality(quality) {
|
|
251
|
+
this.networkQuality = quality;
|
|
252
|
+
this.notify("networkQuality");
|
|
253
|
+
}
|
|
237
254
|
// ---- participants ----
|
|
238
255
|
addParticipant(p) {
|
|
239
256
|
if (this.participants.has(p.id)) return false;
|
|
@@ -354,10 +371,14 @@ var MeetingState = class {
|
|
|
354
371
|
this.chatMessages.clear();
|
|
355
372
|
this.presenterId = null;
|
|
356
373
|
this.activeSpeakerIds = /* @__PURE__ */ new Set();
|
|
374
|
+
this.liveTranscripts = [];
|
|
375
|
+
this.networkQuality = null;
|
|
357
376
|
this.notify("participants");
|
|
358
377
|
this.notify("chat");
|
|
359
378
|
this.notify("presenter");
|
|
360
379
|
this.notify("activeSpeakers");
|
|
380
|
+
this.notify("transcript");
|
|
381
|
+
this.notify("networkQuality");
|
|
361
382
|
}
|
|
362
383
|
};
|
|
363
384
|
|
|
@@ -419,6 +440,12 @@ var SFUClient = class {
|
|
|
419
440
|
this.trackToSource = /* @__PURE__ */ new Map();
|
|
420
441
|
this.localTrackIds = /* @__PURE__ */ new Map();
|
|
421
442
|
this.subscriberStatsTimer = null;
|
|
443
|
+
this.liveTranscriptionActive = false;
|
|
444
|
+
this.liveTranscriptionSequence = 0;
|
|
445
|
+
this.liveTranscriptionStartedAt = 0;
|
|
446
|
+
this.liveTranscriptionRecorder = null;
|
|
447
|
+
this.liveTranscriptionLoopPromise = null;
|
|
448
|
+
this.networkProfile = null;
|
|
422
449
|
this.heartbeatTimer = null;
|
|
423
450
|
this.apiBase = options.apiBase || "https://api.example.com/api";
|
|
424
451
|
this.wsBase = options.wsBase || "wss://api.example.com/ws";
|
|
@@ -475,6 +502,10 @@ var SFUClient = class {
|
|
|
475
502
|
});
|
|
476
503
|
this.onRoomUpdate = options.onRoomUpdate || (() => {
|
|
477
504
|
});
|
|
505
|
+
this.onLiveTranscript = options.onLiveTranscript || (() => {
|
|
506
|
+
});
|
|
507
|
+
this.onNetworkQuality = options.onNetworkQuality || (() => {
|
|
508
|
+
});
|
|
478
509
|
this.onParticipantMediaState = options.onParticipantMediaState || (() => {
|
|
479
510
|
});
|
|
480
511
|
this.autoSubscribe = options.autoSubscribe !== false;
|
|
@@ -1069,6 +1100,40 @@ var SFUClient = class {
|
|
|
1069
1100
|
if (reaction?.id && reaction?.emoji) this.onReaction(reaction);
|
|
1070
1101
|
break;
|
|
1071
1102
|
}
|
|
1103
|
+
case "live_transcript": {
|
|
1104
|
+
const transcript = {
|
|
1105
|
+
transcript_id: String(payload.transcript_id),
|
|
1106
|
+
participant_id: String(payload.participant_id),
|
|
1107
|
+
speaker_name: payload.speaker_name ?? null,
|
|
1108
|
+
sequence: Number(payload.sequence ?? 0),
|
|
1109
|
+
text: String(payload.text ?? ""),
|
|
1110
|
+
offset_ms: payload.offset_ms == null ? null : Number(payload.offset_ms),
|
|
1111
|
+
start_ms: payload.start_ms == null ? null : Number(payload.start_ms),
|
|
1112
|
+
end_ms: payload.end_ms == null ? null : Number(payload.end_ms),
|
|
1113
|
+
timestamp: String(payload.timestamp ?? (/* @__PURE__ */ new Date()).toISOString())
|
|
1114
|
+
};
|
|
1115
|
+
if (transcript.text.trim()) this.onLiveTranscript(transcript);
|
|
1116
|
+
break;
|
|
1117
|
+
}
|
|
1118
|
+
case "network_quality": {
|
|
1119
|
+
const raw = payload.quality || payload;
|
|
1120
|
+
const quality = {
|
|
1121
|
+
participant_id: String(raw.participant_id ?? this.currentParticipantId ?? this.participantId),
|
|
1122
|
+
quality: String(raw.quality ?? "unknown"),
|
|
1123
|
+
score: Number(raw.score ?? 0),
|
|
1124
|
+
recommended_action: String(raw.recommended_action ?? "maintain"),
|
|
1125
|
+
packet_loss_percent: Number(raw.packet_loss_percent ?? 0),
|
|
1126
|
+
upload_kbps: Number(raw.upload_kbps ?? 0),
|
|
1127
|
+
forwarded_drop_percent: Number(raw.forwarded_drop_percent ?? 0),
|
|
1128
|
+
queued_packets: Number(raw.queued_packets ?? 0),
|
|
1129
|
+
packets_received: Number(raw.packets_received ?? 0),
|
|
1130
|
+
packets_lost: Number(raw.packets_lost ?? 0),
|
|
1131
|
+
observed_at: String(raw.observed_at ?? (/* @__PURE__ */ new Date()).toISOString())
|
|
1132
|
+
};
|
|
1133
|
+
this.onNetworkQuality(quality);
|
|
1134
|
+
void this.applyNetworkRecommendation(quality.recommended_action);
|
|
1135
|
+
break;
|
|
1136
|
+
}
|
|
1072
1137
|
case "error": {
|
|
1073
1138
|
const message2 = payload.message || "SFU signaling error";
|
|
1074
1139
|
if (this.state === "reconnecting" && message2.includes("participant session is stale")) {
|
|
@@ -1728,6 +1793,147 @@ var SFUClient = class {
|
|
|
1728
1793
|
}
|
|
1729
1794
|
});
|
|
1730
1795
|
}
|
|
1796
|
+
getLiveTranscriptionMimeType() {
|
|
1797
|
+
if (typeof MediaRecorder === "undefined") {
|
|
1798
|
+
throw new Error("MediaRecorder is not supported by this browser");
|
|
1799
|
+
}
|
|
1800
|
+
const candidates = [
|
|
1801
|
+
"audio/webm;codecs=opus",
|
|
1802
|
+
"audio/webm",
|
|
1803
|
+
"audio/ogg;codecs=opus"
|
|
1804
|
+
];
|
|
1805
|
+
return candidates.find((type) => MediaRecorder.isTypeSupported(type)) || "";
|
|
1806
|
+
}
|
|
1807
|
+
async startLiveTranscription(audioTrack, speakerName) {
|
|
1808
|
+
if (this.liveTranscriptionActive) return;
|
|
1809
|
+
if (!this.room) throw new Error("Cannot start live transcription without a room");
|
|
1810
|
+
if (!this.authToken) throw new Error("Cannot start live transcription without an authenticated token");
|
|
1811
|
+
if (!audioTrack || audioTrack.kind !== "audio") {
|
|
1812
|
+
throw new Error("A live microphone audio track is required");
|
|
1813
|
+
}
|
|
1814
|
+
const mimeType = this.getLiveTranscriptionMimeType();
|
|
1815
|
+
this.liveTranscriptionActive = true;
|
|
1816
|
+
this.liveTranscriptionSequence = 0;
|
|
1817
|
+
this.liveTranscriptionStartedAt = Date.now();
|
|
1818
|
+
const stream = new MediaStream([audioTrack]);
|
|
1819
|
+
this.liveTranscriptionLoopPromise = this.runLiveTranscriptionLoop(
|
|
1820
|
+
stream,
|
|
1821
|
+
mimeType
|
|
1822
|
+
).finally(() => {
|
|
1823
|
+
this.liveTranscriptionRecorder = null;
|
|
1824
|
+
this.liveTranscriptionLoopPromise = null;
|
|
1825
|
+
});
|
|
1826
|
+
void speakerName;
|
|
1827
|
+
await Promise.resolve();
|
|
1828
|
+
}
|
|
1829
|
+
async captureLiveChunk(stream, mimeType) {
|
|
1830
|
+
return new Promise((resolve, reject) => {
|
|
1831
|
+
const chunks = [];
|
|
1832
|
+
const recorder = mimeType ? new MediaRecorder(stream, { mimeType }) : new MediaRecorder(stream);
|
|
1833
|
+
this.liveTranscriptionRecorder = recorder;
|
|
1834
|
+
const timeout = setTimeout(() => {
|
|
1835
|
+
if (recorder.state !== "inactive") recorder.stop();
|
|
1836
|
+
}, 4500);
|
|
1837
|
+
recorder.ondataavailable = (event) => {
|
|
1838
|
+
if (event.data.size > 0) chunks.push(event.data);
|
|
1839
|
+
};
|
|
1840
|
+
recorder.onerror = () => {
|
|
1841
|
+
clearTimeout(timeout);
|
|
1842
|
+
reject(new Error("Live transcription recorder failed"));
|
|
1843
|
+
};
|
|
1844
|
+
recorder.onstop = () => {
|
|
1845
|
+
clearTimeout(timeout);
|
|
1846
|
+
this.liveTranscriptionRecorder = null;
|
|
1847
|
+
resolve(
|
|
1848
|
+
chunks.length ? new Blob(chunks, { type: recorder.mimeType || mimeType || "audio/webm" }) : null
|
|
1849
|
+
);
|
|
1850
|
+
};
|
|
1851
|
+
recorder.start();
|
|
1852
|
+
});
|
|
1853
|
+
}
|
|
1854
|
+
async runLiveTranscriptionLoop(stream, mimeType) {
|
|
1855
|
+
while (this.liveTranscriptionActive && stream.getAudioTracks()[0]?.readyState === "live") {
|
|
1856
|
+
try {
|
|
1857
|
+
const blob = await this.captureLiveChunk(stream, mimeType);
|
|
1858
|
+
if (!this.liveTranscriptionActive) break;
|
|
1859
|
+
if (!blob || blob.size === 0) continue;
|
|
1860
|
+
const sequence = this.liveTranscriptionSequence++;
|
|
1861
|
+
const offsetMs = Math.max(0, Date.now() - this.liveTranscriptionStartedAt);
|
|
1862
|
+
await this.uploadLiveTranscriptionChunk(blob, sequence, offsetMs, mimeType);
|
|
1863
|
+
} catch (error) {
|
|
1864
|
+
this.onError(error);
|
|
1865
|
+
await new Promise((resolve) => setTimeout(resolve, 750));
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
async uploadLiveTranscriptionChunk(blob, sequence, offsetMs, mimeType) {
|
|
1870
|
+
if (!this.room || !this.authToken) return;
|
|
1871
|
+
const form = new FormData();
|
|
1872
|
+
form.append("sequence", String(sequence));
|
|
1873
|
+
form.append("offset_ms", String(offsetMs));
|
|
1874
|
+
const extension = mimeType.includes("ogg") || blob.type.includes("ogg") ? "ogg" : "webm";
|
|
1875
|
+
form.append("audio", blob, `live-${sequence}.${extension}`);
|
|
1876
|
+
const response = await fetch(
|
|
1877
|
+
`${this.apiBase}/rooms/${encodeURIComponent(this.room)}/live-transcription`,
|
|
1878
|
+
{
|
|
1879
|
+
method: "POST",
|
|
1880
|
+
headers: {
|
|
1881
|
+
Authorization: `Bearer ${this.authToken}`,
|
|
1882
|
+
Accept: "application/json"
|
|
1883
|
+
},
|
|
1884
|
+
body: form
|
|
1885
|
+
}
|
|
1886
|
+
);
|
|
1887
|
+
if (!response.ok) {
|
|
1888
|
+
let detail = `Live transcription request failed: ${response.status}`;
|
|
1889
|
+
try {
|
|
1890
|
+
const body = await response.json();
|
|
1891
|
+
detail = body?.message || body?.detail || detail;
|
|
1892
|
+
} catch {
|
|
1893
|
+
}
|
|
1894
|
+
throw new Error(detail);
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
stopLiveTranscription() {
|
|
1898
|
+
this.liveTranscriptionActive = false;
|
|
1899
|
+
try {
|
|
1900
|
+
if (this.liveTranscriptionRecorder?.state !== "inactive") {
|
|
1901
|
+
this.liveTranscriptionRecorder?.stop();
|
|
1902
|
+
}
|
|
1903
|
+
} catch {
|
|
1904
|
+
}
|
|
1905
|
+
this.liveTranscriptionRecorder = null;
|
|
1906
|
+
}
|
|
1907
|
+
isLiveTranscriptionActive() {
|
|
1908
|
+
return this.liveTranscriptionActive;
|
|
1909
|
+
}
|
|
1910
|
+
async applyNetworkRecommendation(action) {
|
|
1911
|
+
if (!this.videoSender || this.networkProfile === action) return;
|
|
1912
|
+
const params = this.videoSender.getParameters();
|
|
1913
|
+
const encodings = params.encodings?.length ? params.encodings : [{}];
|
|
1914
|
+
const encoding = encodings[0];
|
|
1915
|
+
switch (action) {
|
|
1916
|
+
case "reduce_video":
|
|
1917
|
+
encoding.maxBitrate = 7e5;
|
|
1918
|
+
encoding.maxFramerate = 20;
|
|
1919
|
+
break;
|
|
1920
|
+
case "audio_priority":
|
|
1921
|
+
encoding.maxBitrate = 35e4;
|
|
1922
|
+
encoding.maxFramerate = 10;
|
|
1923
|
+
break;
|
|
1924
|
+
default:
|
|
1925
|
+
encoding.maxBitrate = 15e5;
|
|
1926
|
+
encoding.maxFramerate = 30;
|
|
1927
|
+
break;
|
|
1928
|
+
}
|
|
1929
|
+
params.encodings = encodings;
|
|
1930
|
+
try {
|
|
1931
|
+
await this.videoSender.setParameters(params);
|
|
1932
|
+
this.networkProfile = action;
|
|
1933
|
+
} catch (error) {
|
|
1934
|
+
this.onError(error);
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1731
1937
|
async startRecording() {
|
|
1732
1938
|
if (!this.send({ type: "start_recording" })) {
|
|
1733
1939
|
throw new Error("SFU signaling is not connected");
|
|
@@ -1860,6 +2066,7 @@ var SFUClient = class {
|
|
|
1860
2066
|
}
|
|
1861
2067
|
}
|
|
1862
2068
|
async leave() {
|
|
2069
|
+
this.stopLiveTranscription();
|
|
1863
2070
|
this.stopHeartbeat();
|
|
1864
2071
|
this.intentionalClose = true;
|
|
1865
2072
|
this.setState("leaving");
|
|
@@ -2268,6 +2475,14 @@ var VideoSDKCore = class {
|
|
|
2268
2475
|
console.warn(`[SFU] Reconnecting, attempt ${attempt}`);
|
|
2269
2476
|
},
|
|
2270
2477
|
// ADMISSION CONTROL
|
|
2478
|
+
onLiveTranscript: (transcript) => {
|
|
2479
|
+
this.state.addLiveTranscript(transcript);
|
|
2480
|
+
this.events.onLiveTranscript?.(transcript);
|
|
2481
|
+
},
|
|
2482
|
+
onNetworkQuality: (quality) => {
|
|
2483
|
+
this.state.setNetworkQuality(quality);
|
|
2484
|
+
this.events.onNetworkQuality?.(quality);
|
|
2485
|
+
},
|
|
2271
2486
|
onRoomUpdate: (payload) => {
|
|
2272
2487
|
const participants = payload?.participants || [];
|
|
2273
2488
|
const local = participants.find(
|
|
@@ -2912,6 +3127,28 @@ var VideoSDKCore = class {
|
|
|
2912
3127
|
}
|
|
2913
3128
|
}
|
|
2914
3129
|
}
|
|
3130
|
+
async startLiveTranscription() {
|
|
3131
|
+
if (!this.sfuClient) {
|
|
3132
|
+
throw new Error("SFU client is not connected");
|
|
3133
|
+
}
|
|
3134
|
+
const audioTrack = this.localStream?.getAudioTracks()[0];
|
|
3135
|
+
if (!audioTrack) {
|
|
3136
|
+
throw new Error("Microphone audio track is not available");
|
|
3137
|
+
}
|
|
3138
|
+
await this.sfuClient.startLiveTranscription(
|
|
3139
|
+
audioTrack,
|
|
3140
|
+
this.participantName
|
|
3141
|
+
);
|
|
3142
|
+
}
|
|
3143
|
+
stopLiveTranscription() {
|
|
3144
|
+
this.sfuClient?.stopLiveTranscription();
|
|
3145
|
+
}
|
|
3146
|
+
isLiveTranscriptionActive() {
|
|
3147
|
+
return this.sfuClient?.isLiveTranscriptionActive() ?? false;
|
|
3148
|
+
}
|
|
3149
|
+
getNetworkQuality() {
|
|
3150
|
+
return this.state.networkQuality;
|
|
3151
|
+
}
|
|
2915
3152
|
// CLEANUP
|
|
2916
3153
|
cleanupRemoteParticipant(participantId) {
|
|
2917
3154
|
this.activeSpeakerDetector.removeParticipant(participantId);
|
|
@@ -2960,6 +3197,8 @@ var VideoSDKCore = class {
|
|
|
2960
3197
|
this.room.id = null;
|
|
2961
3198
|
this.room.name = null;
|
|
2962
3199
|
this.state.localParticipant = null;
|
|
3200
|
+
this.state.clearLiveTranscripts();
|
|
3201
|
+
this.state.setNetworkQuality(null);
|
|
2963
3202
|
this.state.notify("localParticipant");
|
|
2964
3203
|
this.state.resetRemoteState();
|
|
2965
3204
|
this.events.onMeetingLeft?.();
|
|
@@ -2992,9 +3231,15 @@ var MeetingProvider = ({
|
|
|
2992
3231
|
const entryResponseListeners = useRef(
|
|
2993
3232
|
/* @__PURE__ */ new Set()
|
|
2994
3233
|
);
|
|
2995
|
-
const joinRequestCanceledListeners = useRef(
|
|
2996
|
-
|
|
2997
|
-
|
|
3234
|
+
const joinRequestCanceledListeners = useRef(
|
|
3235
|
+
/* @__PURE__ */ new Set()
|
|
3236
|
+
);
|
|
3237
|
+
const participantRemovedListeners = useRef(
|
|
3238
|
+
/* @__PURE__ */ new Set()
|
|
3239
|
+
);
|
|
3240
|
+
const participantPermissionsChangedListeners = useRef(
|
|
3241
|
+
/* @__PURE__ */ new Set()
|
|
3242
|
+
);
|
|
2998
3243
|
const meetingLeftListeners = useRef(/* @__PURE__ */ new Set());
|
|
2999
3244
|
const trackStateListeners = useRef(/* @__PURE__ */ new Set());
|
|
3000
3245
|
const recordingStartedListeners = useRef(/* @__PURE__ */ new Set());
|
|
@@ -3007,6 +3252,12 @@ var MeetingProvider = ({
|
|
|
3007
3252
|
const activeSpeakerListeners = useRef(
|
|
3008
3253
|
/* @__PURE__ */ new Set()
|
|
3009
3254
|
);
|
|
3255
|
+
const liveTranscriptListeners = useRef(
|
|
3256
|
+
/* @__PURE__ */ new Set()
|
|
3257
|
+
);
|
|
3258
|
+
const networkQualityListeners = useRef(
|
|
3259
|
+
/* @__PURE__ */ new Set()
|
|
3260
|
+
);
|
|
3010
3261
|
const connectionStateListeners = useRef(
|
|
3011
3262
|
/* @__PURE__ */ new Set()
|
|
3012
3263
|
);
|
|
@@ -3030,10 +3281,14 @@ var MeetingProvider = ({
|
|
|
3030
3281
|
joinRequestCanceledListeners.current.forEach((fn) => fn(requestId));
|
|
3031
3282
|
},
|
|
3032
3283
|
onParticipantRemoved: (participantId, removedBy) => {
|
|
3033
|
-
participantRemovedListeners.current.forEach(
|
|
3284
|
+
participantRemovedListeners.current.forEach(
|
|
3285
|
+
(fn) => fn(participantId, removedBy)
|
|
3286
|
+
);
|
|
3034
3287
|
},
|
|
3035
3288
|
onParticipantPermissionsChanged: (participantId, permissions) => {
|
|
3036
|
-
participantPermissionsChangedListeners.current.forEach(
|
|
3289
|
+
participantPermissionsChangedListeners.current.forEach(
|
|
3290
|
+
(fn) => fn(participantId, permissions)
|
|
3291
|
+
);
|
|
3037
3292
|
},
|
|
3038
3293
|
onMeetingLeft: () => {
|
|
3039
3294
|
meetingLeftListeners.current.forEach((fn) => fn());
|
|
@@ -3086,6 +3341,12 @@ var MeetingProvider = ({
|
|
|
3086
3341
|
);
|
|
3087
3342
|
pubSubListeners.current.get("REACTION")?.forEach((fn) => fn(message));
|
|
3088
3343
|
},
|
|
3344
|
+
onLiveTranscript: (transcript) => {
|
|
3345
|
+
liveTranscriptListeners.current.forEach((fn) => fn(transcript));
|
|
3346
|
+
},
|
|
3347
|
+
onNetworkQuality: (quality) => {
|
|
3348
|
+
networkQualityListeners.current.forEach((fn) => fn(quality));
|
|
3349
|
+
},
|
|
3089
3350
|
onConnectionStateChanged: (state) => {
|
|
3090
3351
|
connectionStateListeners.current.forEach(
|
|
3091
3352
|
(fn) => fn(state)
|
|
@@ -3121,6 +3382,16 @@ var MeetingProvider = ({
|
|
|
3121
3382
|
"chat",
|
|
3122
3383
|
(s) => s.getChatMessages()
|
|
3123
3384
|
);
|
|
3385
|
+
const liveTranscripts = useMeetingStore(
|
|
3386
|
+
sdk.state,
|
|
3387
|
+
"transcript",
|
|
3388
|
+
(s) => s.getLiveTranscripts()
|
|
3389
|
+
);
|
|
3390
|
+
const networkQuality = useMeetingStore(
|
|
3391
|
+
sdk.state,
|
|
3392
|
+
"networkQuality",
|
|
3393
|
+
(s) => s.networkQuality
|
|
3394
|
+
);
|
|
3124
3395
|
const value = useMemo(() => {
|
|
3125
3396
|
return {
|
|
3126
3397
|
sdk,
|
|
@@ -3145,6 +3416,11 @@ var MeetingProvider = ({
|
|
|
3145
3416
|
messages,
|
|
3146
3417
|
presenterId,
|
|
3147
3418
|
activeSpeakerIds,
|
|
3419
|
+
liveTranscripts,
|
|
3420
|
+
networkQuality,
|
|
3421
|
+
startLiveTranscription: sdk.startLiveTranscription.bind(sdk),
|
|
3422
|
+
stopLiveTranscription: sdk.stopLiveTranscription.bind(sdk),
|
|
3423
|
+
isLiveTranscriptionActive: sdk.isLiveTranscriptionActive.bind(sdk),
|
|
3148
3424
|
recording,
|
|
3149
3425
|
usePubSub: (topic) => {
|
|
3150
3426
|
if (topic === "SECURE_CHAT") {
|
|
@@ -3263,6 +3539,14 @@ var MeetingProvider = ({
|
|
|
3263
3539
|
reactionListeners.current.add(cb);
|
|
3264
3540
|
return () => reactionListeners.current.delete(cb);
|
|
3265
3541
|
},
|
|
3542
|
+
onLiveTranscript: (cb) => {
|
|
3543
|
+
liveTranscriptListeners.current.add(cb);
|
|
3544
|
+
return () => liveTranscriptListeners.current.delete(cb);
|
|
3545
|
+
},
|
|
3546
|
+
onNetworkQuality: (cb) => {
|
|
3547
|
+
networkQualityListeners.current.add(cb);
|
|
3548
|
+
return () => networkQualityListeners.current.delete(cb);
|
|
3549
|
+
},
|
|
3266
3550
|
onConnectionStateChanged: (cb) => {
|
|
3267
3551
|
connectionStateListeners.current.add(cb);
|
|
3268
3552
|
return () => {
|
|
@@ -3285,6 +3569,8 @@ var MeetingProvider = ({
|
|
|
3285
3569
|
presenterId,
|
|
3286
3570
|
recording,
|
|
3287
3571
|
activeSpeakerIds,
|
|
3572
|
+
liveTranscripts,
|
|
3573
|
+
networkQuality,
|
|
3288
3574
|
reactionPubSubMessages
|
|
3289
3575
|
]);
|
|
3290
3576
|
return /* @__PURE__ */ jsx(MeetingContext.Provider, { value, children });
|
|
@@ -3369,7 +3655,9 @@ var useMeeting = (handlers) => {
|
|
|
3369
3655
|
}, [handlers?.onParticipantRemoved]);
|
|
3370
3656
|
useEffect3(() => {
|
|
3371
3657
|
if (!handlers?.onParticipantPermissionsChanged) return;
|
|
3372
|
-
return ctx.onParticipantPermissionsChanged(
|
|
3658
|
+
return ctx.onParticipantPermissionsChanged(
|
|
3659
|
+
handlers.onParticipantPermissionsChanged
|
|
3660
|
+
);
|
|
3373
3661
|
}, [handlers?.onParticipantPermissionsChanged]);
|
|
3374
3662
|
useEffect3(() => {
|
|
3375
3663
|
if (!handlers?.onMeetingLeft) return;
|
|
@@ -3391,6 +3679,14 @@ var useMeeting = (handlers) => {
|
|
|
3391
3679
|
if (!handlers?.onConnectionStateChanged) return;
|
|
3392
3680
|
return ctx.onConnectionStateChanged(handlers.onConnectionStateChanged);
|
|
3393
3681
|
}, [handlers?.onConnectionStateChanged]);
|
|
3682
|
+
useEffect3(() => {
|
|
3683
|
+
if (!handlers?.onLiveTranscript) return;
|
|
3684
|
+
return ctx.onLiveTranscript(handlers.onLiveTranscript);
|
|
3685
|
+
}, [handlers?.onLiveTranscript]);
|
|
3686
|
+
useEffect3(() => {
|
|
3687
|
+
if (!handlers?.onNetworkQuality) return;
|
|
3688
|
+
return ctx.onNetworkQuality(handlers.onNetworkQuality);
|
|
3689
|
+
}, [handlers?.onNetworkQuality]);
|
|
3394
3690
|
useEffect3(() => {
|
|
3395
3691
|
if (!handlers?.onReaction) return;
|
|
3396
3692
|
return ctx.onReaction(handlers.onReaction);
|
|
@@ -3528,6 +3824,26 @@ function useMeetingPreview(roomId, participantId) {
|
|
|
3528
3824
|
};
|
|
3529
3825
|
}
|
|
3530
3826
|
|
|
3827
|
+
// src/react/useLiveTranscript.ts
|
|
3828
|
+
var useLiveTranscript = () => {
|
|
3829
|
+
const { sdk } = useMeetingContext();
|
|
3830
|
+
return useMeetingStore(
|
|
3831
|
+
sdk.state,
|
|
3832
|
+
"transcript",
|
|
3833
|
+
(state) => state.getLiveTranscripts()
|
|
3834
|
+
);
|
|
3835
|
+
};
|
|
3836
|
+
|
|
3837
|
+
// src/react/useNetworkQuality.ts
|
|
3838
|
+
var useNetworkQuality = () => {
|
|
3839
|
+
const { sdk } = useMeetingContext();
|
|
3840
|
+
return useMeetingStore(
|
|
3841
|
+
sdk.state,
|
|
3842
|
+
"networkQuality",
|
|
3843
|
+
(state) => state.networkQuality
|
|
3844
|
+
);
|
|
3845
|
+
};
|
|
3846
|
+
|
|
3531
3847
|
// src/react/usePubSub.ts
|
|
3532
3848
|
import { useEffect as useEffect7 } from "react";
|
|
3533
3849
|
function usePubSub(topic, options) {
|
|
@@ -3546,10 +3862,12 @@ export {
|
|
|
3546
3862
|
MeetingProvider,
|
|
3547
3863
|
MeetingState,
|
|
3548
3864
|
VideoSDKCore,
|
|
3865
|
+
useLiveTranscript,
|
|
3549
3866
|
useLocalParticipant,
|
|
3550
3867
|
useMeeting,
|
|
3551
3868
|
useMeetingContext,
|
|
3552
3869
|
useMeetingPreview,
|
|
3870
|
+
useNetworkQuality,
|
|
3553
3871
|
useParticipants,
|
|
3554
3872
|
usePubSub,
|
|
3555
3873
|
useRemoteMedia
|