@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.js CHANGED
@@ -1834,28 +1834,44 @@ var SFUClient = class {
1834
1834
  "audio/webm",
1835
1835
  "audio/ogg;codecs=opus"
1836
1836
  ];
1837
- return candidates.find((type) => MediaRecorder.isTypeSupported(type)) || "";
1837
+ return candidates.find(
1838
+ (type) => MediaRecorder.isTypeSupported(type)
1839
+ ) || "";
1838
1840
  }
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");
1841
+ async startLiveTranscription() {
1842
+ if (this.liveTranscriptionActive) {
1843
+ return;
1844
+ }
1845
+ if (!this.room) {
1846
+ throw new Error("Cannot start live transcription without a room");
1847
+ }
1848
+ if (!this.authToken) {
1849
+ throw new Error(
1850
+ "Cannot start live transcription without an authenticated token"
1851
+ );
1852
+ }
1853
+ const audioTrack = this.localStream?.getAudioTracks()[0];
1854
+ if (!audioTrack || audioTrack.readyState !== "live") {
1855
+ throw new Error(
1856
+ "Cannot start live transcription without a live microphone track"
1857
+ );
1845
1858
  }
1846
1859
  const mimeType = this.getLiveTranscriptionMimeType();
1860
+ const stream = new MediaStream([audioTrack]);
1847
1861
  this.liveTranscriptionActive = true;
1848
1862
  this.liveTranscriptionSequence = 0;
1849
1863
  this.liveTranscriptionStartedAt = Date.now();
1850
- const stream = new MediaStream([audioTrack]);
1851
- this.liveTranscriptionLoopPromise = this.runLiveTranscriptionLoop(
1852
- stream,
1864
+ console.log("[Transcript] starting", {
1865
+ room: this.room,
1866
+ trackId: audioTrack.id,
1867
+ readyState: audioTrack.readyState,
1868
+ enabled: audioTrack.enabled,
1853
1869
  mimeType
1854
- ).finally(() => {
1870
+ });
1871
+ this.liveTranscriptionLoopPromise = this.runLiveTranscriptionLoop(stream, mimeType).finally(() => {
1855
1872
  this.liveTranscriptionRecorder = null;
1856
1873
  this.liveTranscriptionLoopPromise = null;
1857
1874
  });
1858
- void speakerName;
1859
1875
  await Promise.resolve();
1860
1876
  }
1861
1877
  async captureLiveChunk(stream, mimeType) {
@@ -1863,21 +1879,32 @@ var SFUClient = class {
1863
1879
  const chunks = [];
1864
1880
  const recorder = mimeType ? new MediaRecorder(stream, { mimeType }) : new MediaRecorder(stream);
1865
1881
  this.liveTranscriptionRecorder = recorder;
1866
- const timeout = setTimeout(() => {
1867
- if (recorder.state !== "inactive") recorder.stop();
1868
- }, 4500);
1882
+ const timeout = window.setTimeout(() => {
1883
+ if (recorder.state !== "inactive") {
1884
+ recorder.stop();
1885
+ }
1886
+ }, 1500);
1887
+ recorder.onstart = () => {
1888
+ console.log("[Transcript] MediaRecorder started", {
1889
+ mimeType: recorder.mimeType
1890
+ });
1891
+ };
1869
1892
  recorder.ondataavailable = (event) => {
1870
- if (event.data.size > 0) chunks.push(event.data);
1893
+ if (event.data.size > 0) {
1894
+ chunks.push(event.data);
1895
+ }
1871
1896
  };
1872
1897
  recorder.onerror = () => {
1873
- clearTimeout(timeout);
1898
+ window.clearTimeout(timeout);
1874
1899
  reject(new Error("Live transcription recorder failed"));
1875
1900
  };
1876
1901
  recorder.onstop = () => {
1877
- clearTimeout(timeout);
1902
+ window.clearTimeout(timeout);
1878
1903
  this.liveTranscriptionRecorder = null;
1879
1904
  resolve(
1880
- chunks.length ? new Blob(chunks, { type: recorder.mimeType || mimeType || "audio/webm" }) : null
1905
+ chunks.length ? new Blob(chunks, {
1906
+ type: recorder.mimeType || mimeType || "audio/webm"
1907
+ }) : null
1881
1908
  );
1882
1909
  };
1883
1910
  recorder.start();
@@ -1887,52 +1914,86 @@ var SFUClient = class {
1887
1914
  while (this.liveTranscriptionActive && stream.getAudioTracks()[0]?.readyState === "live") {
1888
1915
  try {
1889
1916
  const blob = await this.captureLiveChunk(stream, mimeType);
1890
- if (!this.liveTranscriptionActive) break;
1891
- if (!blob || blob.size === 0) continue;
1917
+ if (!this.liveTranscriptionActive) {
1918
+ break;
1919
+ }
1920
+ if (!blob || blob.size === 0) {
1921
+ continue;
1922
+ }
1892
1923
  const sequence = this.liveTranscriptionSequence++;
1893
- const offsetMs = Math.max(0, Date.now() - this.liveTranscriptionStartedAt);
1894
- await this.uploadLiveTranscriptionChunk(blob, sequence, offsetMs, mimeType);
1924
+ const offsetMs = Math.max(
1925
+ 0,
1926
+ Date.now() - this.liveTranscriptionStartedAt
1927
+ );
1928
+ await this.uploadLiveTranscriptionChunk(
1929
+ blob,
1930
+ sequence,
1931
+ offsetMs,
1932
+ blob.type || mimeType
1933
+ );
1895
1934
  } catch (error) {
1935
+ console.error(
1936
+ "[Transcript] chunk processing failed",
1937
+ error
1938
+ );
1896
1939
  this.onError(error);
1897
- await new Promise((resolve) => setTimeout(resolve, 750));
1940
+ await new Promise(
1941
+ (resolve) => setTimeout(resolve, 750)
1942
+ );
1898
1943
  }
1899
1944
  }
1900
1945
  }
1901
1946
  async uploadLiveTranscriptionChunk(blob, sequence, offsetMs, mimeType) {
1902
- if (!this.room || !this.authToken) return;
1947
+ if (!this.room || !this.authToken) {
1948
+ return;
1949
+ }
1903
1950
  const form = new FormData();
1904
1951
  form.append("sequence", String(sequence));
1905
1952
  form.append("offset_ms", String(offsetMs));
1906
1953
  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
- }
1954
+ form.append(
1955
+ "audio",
1956
+ blob,
1957
+ `live-${sequence}.${extension}`
1918
1958
  );
1959
+ const url = `${this.apiBase}/rooms/${encodeURIComponent(this.room)}/live-transcription`;
1960
+ console.log("[Transcript] POST", {
1961
+ url,
1962
+ sequence,
1963
+ size: blob.size,
1964
+ mimeType
1965
+ });
1966
+ const response = await fetch(url, {
1967
+ method: "POST",
1968
+ headers: {
1969
+ Authorization: `Bearer ${this.authToken}`,
1970
+ Accept: "application/json"
1971
+ },
1972
+ body: form
1973
+ });
1974
+ const responseText = await response.text();
1975
+ console.log("[Transcript] response", {
1976
+ status: response.status,
1977
+ body: responseText
1978
+ });
1919
1979
  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);
1980
+ throw new Error(
1981
+ `Live transcription request failed: ${response.status} ${responseText}`
1982
+ );
1927
1983
  }
1928
1984
  }
1929
1985
  stopLiveTranscription() {
1986
+ console.log("[Transcript] stopping");
1930
1987
  this.liveTranscriptionActive = false;
1931
1988
  try {
1932
- if (this.liveTranscriptionRecorder?.state !== "inactive") {
1933
- this.liveTranscriptionRecorder?.stop();
1989
+ if (this.liveTranscriptionRecorder && this.liveTranscriptionRecorder.state !== "inactive") {
1990
+ this.liveTranscriptionRecorder.stop();
1934
1991
  }
1935
- } catch {
1992
+ } catch (error) {
1993
+ console.warn(
1994
+ "[Transcript] recorder shutdown failed",
1995
+ error
1996
+ );
1936
1997
  }
1937
1998
  this.liveTranscriptionRecorder = null;
1938
1999
  }
@@ -3164,13 +3225,10 @@ var VideoSDKCore = class {
3164
3225
  throw new Error("SFU client is not connected");
3165
3226
  }
3166
3227
  const audioTrack = this.localStream?.getAudioTracks()[0];
3167
- if (!audioTrack) {
3228
+ if (!audioTrack || audioTrack.readyState !== "live") {
3168
3229
  throw new Error("Microphone audio track is not available");
3169
3230
  }
3170
- await this.sfuClient.startLiveTranscription(
3171
- audioTrack,
3172
- this.participantName
3173
- );
3231
+ await this.sfuClient.startLiveTranscription();
3174
3232
  }
3175
3233
  stopLiveTranscription() {
3176
3234
  this.sfuClient?.stopLiveTranscription();