@defcomm/meetingsdk 0.5.6 → 0.5.7

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.mjs CHANGED
@@ -1802,28 +1802,44 @@ var SFUClient = class {
1802
1802
  "audio/webm",
1803
1803
  "audio/ogg;codecs=opus"
1804
1804
  ];
1805
- return candidates.find((type) => MediaRecorder.isTypeSupported(type)) || "";
1805
+ return candidates.find(
1806
+ (type) => MediaRecorder.isTypeSupported(type)
1807
+ ) || "";
1806
1808
  }
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");
1809
+ async startLiveTranscription() {
1810
+ if (this.liveTranscriptionActive) {
1811
+ return;
1812
+ }
1813
+ if (!this.room) {
1814
+ throw new Error("Cannot start live transcription without a room");
1815
+ }
1816
+ if (!this.authToken) {
1817
+ throw new Error(
1818
+ "Cannot start live transcription without an authenticated token"
1819
+ );
1820
+ }
1821
+ const audioTrack = this.localStream?.getAudioTracks()[0];
1822
+ if (!audioTrack || audioTrack.readyState !== "live") {
1823
+ throw new Error(
1824
+ "Cannot start live transcription without a live microphone track"
1825
+ );
1813
1826
  }
1814
1827
  const mimeType = this.getLiveTranscriptionMimeType();
1828
+ const stream = new MediaStream([audioTrack]);
1815
1829
  this.liveTranscriptionActive = true;
1816
1830
  this.liveTranscriptionSequence = 0;
1817
1831
  this.liveTranscriptionStartedAt = Date.now();
1818
- const stream = new MediaStream([audioTrack]);
1819
- this.liveTranscriptionLoopPromise = this.runLiveTranscriptionLoop(
1820
- stream,
1832
+ console.log("[Transcript] starting", {
1833
+ room: this.room,
1834
+ trackId: audioTrack.id,
1835
+ readyState: audioTrack.readyState,
1836
+ enabled: audioTrack.enabled,
1821
1837
  mimeType
1822
- ).finally(() => {
1838
+ });
1839
+ this.liveTranscriptionLoopPromise = this.runLiveTranscriptionLoop(stream, mimeType).finally(() => {
1823
1840
  this.liveTranscriptionRecorder = null;
1824
1841
  this.liveTranscriptionLoopPromise = null;
1825
1842
  });
1826
- void speakerName;
1827
1843
  await Promise.resolve();
1828
1844
  }
1829
1845
  async captureLiveChunk(stream, mimeType) {
@@ -1831,21 +1847,32 @@ var SFUClient = class {
1831
1847
  const chunks = [];
1832
1848
  const recorder = mimeType ? new MediaRecorder(stream, { mimeType }) : new MediaRecorder(stream);
1833
1849
  this.liveTranscriptionRecorder = recorder;
1834
- const timeout = setTimeout(() => {
1835
- if (recorder.state !== "inactive") recorder.stop();
1836
- }, 4500);
1850
+ const timeout = window.setTimeout(() => {
1851
+ if (recorder.state !== "inactive") {
1852
+ recorder.stop();
1853
+ }
1854
+ }, 1500);
1855
+ recorder.onstart = () => {
1856
+ console.log("[Transcript] MediaRecorder started", {
1857
+ mimeType: recorder.mimeType
1858
+ });
1859
+ };
1837
1860
  recorder.ondataavailable = (event) => {
1838
- if (event.data.size > 0) chunks.push(event.data);
1861
+ if (event.data.size > 0) {
1862
+ chunks.push(event.data);
1863
+ }
1839
1864
  };
1840
1865
  recorder.onerror = () => {
1841
- clearTimeout(timeout);
1866
+ window.clearTimeout(timeout);
1842
1867
  reject(new Error("Live transcription recorder failed"));
1843
1868
  };
1844
1869
  recorder.onstop = () => {
1845
- clearTimeout(timeout);
1870
+ window.clearTimeout(timeout);
1846
1871
  this.liveTranscriptionRecorder = null;
1847
1872
  resolve(
1848
- chunks.length ? new Blob(chunks, { type: recorder.mimeType || mimeType || "audio/webm" }) : null
1873
+ chunks.length ? new Blob(chunks, {
1874
+ type: recorder.mimeType || mimeType || "audio/webm"
1875
+ }) : null
1849
1876
  );
1850
1877
  };
1851
1878
  recorder.start();
@@ -1855,52 +1882,86 @@ var SFUClient = class {
1855
1882
  while (this.liveTranscriptionActive && stream.getAudioTracks()[0]?.readyState === "live") {
1856
1883
  try {
1857
1884
  const blob = await this.captureLiveChunk(stream, mimeType);
1858
- if (!this.liveTranscriptionActive) break;
1859
- if (!blob || blob.size === 0) continue;
1885
+ if (!this.liveTranscriptionActive) {
1886
+ break;
1887
+ }
1888
+ if (!blob || blob.size === 0) {
1889
+ continue;
1890
+ }
1860
1891
  const sequence = this.liveTranscriptionSequence++;
1861
- const offsetMs = Math.max(0, Date.now() - this.liveTranscriptionStartedAt);
1862
- await this.uploadLiveTranscriptionChunk(blob, sequence, offsetMs, mimeType);
1892
+ const offsetMs = Math.max(
1893
+ 0,
1894
+ Date.now() - this.liveTranscriptionStartedAt
1895
+ );
1896
+ await this.uploadLiveTranscriptionChunk(
1897
+ blob,
1898
+ sequence,
1899
+ offsetMs,
1900
+ blob.type || mimeType
1901
+ );
1863
1902
  } catch (error) {
1903
+ console.error(
1904
+ "[Transcript] chunk processing failed",
1905
+ error
1906
+ );
1864
1907
  this.onError(error);
1865
- await new Promise((resolve) => setTimeout(resolve, 750));
1908
+ await new Promise(
1909
+ (resolve) => setTimeout(resolve, 750)
1910
+ );
1866
1911
  }
1867
1912
  }
1868
1913
  }
1869
1914
  async uploadLiveTranscriptionChunk(blob, sequence, offsetMs, mimeType) {
1870
- if (!this.room || !this.authToken) return;
1915
+ if (!this.room || !this.authToken) {
1916
+ return;
1917
+ }
1871
1918
  const form = new FormData();
1872
1919
  form.append("sequence", String(sequence));
1873
1920
  form.append("offset_ms", String(offsetMs));
1874
1921
  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
- }
1922
+ form.append(
1923
+ "audio",
1924
+ blob,
1925
+ `live-${sequence}.${extension}`
1886
1926
  );
1927
+ const url = `${this.apiBase}/rooms/${encodeURIComponent(this.room)}/live-transcription`;
1928
+ console.log("[Transcript] POST", {
1929
+ url,
1930
+ sequence,
1931
+ size: blob.size,
1932
+ mimeType
1933
+ });
1934
+ const response = await fetch(url, {
1935
+ method: "POST",
1936
+ headers: {
1937
+ Authorization: `Bearer ${this.authToken}`,
1938
+ Accept: "application/json"
1939
+ },
1940
+ body: form
1941
+ });
1942
+ const responseText = await response.text();
1943
+ console.log("[Transcript] response", {
1944
+ status: response.status,
1945
+ body: responseText
1946
+ });
1887
1947
  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);
1948
+ throw new Error(
1949
+ `Live transcription request failed: ${response.status} ${responseText}`
1950
+ );
1895
1951
  }
1896
1952
  }
1897
1953
  stopLiveTranscription() {
1954
+ console.log("[Transcript] stopping");
1898
1955
  this.liveTranscriptionActive = false;
1899
1956
  try {
1900
- if (this.liveTranscriptionRecorder?.state !== "inactive") {
1901
- this.liveTranscriptionRecorder?.stop();
1957
+ if (this.liveTranscriptionRecorder && this.liveTranscriptionRecorder.state !== "inactive") {
1958
+ this.liveTranscriptionRecorder.stop();
1902
1959
  }
1903
- } catch {
1960
+ } catch (error) {
1961
+ console.warn(
1962
+ "[Transcript] recorder shutdown failed",
1963
+ error
1964
+ );
1904
1965
  }
1905
1966
  this.liveTranscriptionRecorder = null;
1906
1967
  }
@@ -3132,13 +3193,10 @@ var VideoSDKCore = class {
3132
3193
  throw new Error("SFU client is not connected");
3133
3194
  }
3134
3195
  const audioTrack = this.localStream?.getAudioTracks()[0];
3135
- if (!audioTrack) {
3196
+ if (!audioTrack || audioTrack.readyState !== "live") {
3136
3197
  throw new Error("Microphone audio track is not available");
3137
3198
  }
3138
- await this.sfuClient.startLiveTranscription(
3139
- audioTrack,
3140
- this.participantName
3141
- );
3199
+ await this.sfuClient.startLiveTranscription();
3142
3200
  }
3143
3201
  stopLiveTranscription() {
3144
3202
  this.sfuClient?.stopLiveTranscription();