@formant/data-sdk 0.0.101 → 0.0.103

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.
@@ -19034,6 +19034,13 @@ class Device {
19034
19034
  throw new Error(`Already created realtime connection to device ${this.id}`);
19035
19035
  }
19036
19036
  }
19037
+ async sendRealtimeMessage(message, config = {
19038
+ channelLabel: "stream.reliable"
19039
+ }) {
19040
+ const client = defined(this.rtcClient, "Realtime connection has not been started");
19041
+ const devicePeer = await this.getRemotePeer();
19042
+ client.send(defined(devicePeer).id, message, config);
19043
+ }
19037
19044
  addRealtimeListener(listener) {
19038
19045
  this.realtimeListeners.push(listener);
19039
19046
  }
@@ -19907,6 +19914,140 @@ class KeyValue {
19907
19914
  }
19908
19915
  }
19909
19916
  }
19917
+ function stringToArrayBuffer(input) {
19918
+ return Uint8Array.from(atob(input), (_) => _.charCodeAt(0));
19919
+ }
19920
+ function fork(_) {
19921
+ return void 0;
19922
+ }
19923
+ function browser() {
19924
+ const { userAgent } = navigator;
19925
+ if (userAgent.includes("Firefox/")) {
19926
+ return "Firefox";
19927
+ } else if (userAgent.includes("Edg/")) {
19928
+ return "Edge";
19929
+ } else if (userAgent.includes("Chrome/")) {
19930
+ return "Chrome";
19931
+ } else if (userAgent.includes("Safari/")) {
19932
+ return "Safari";
19933
+ } else if (userAgent.includes("MSIE/") || userAgent.includes("Trident/")) {
19934
+ return "IE";
19935
+ } else {
19936
+ return "Other";
19937
+ }
19938
+ }
19939
+ const rtcAudioChunkStreamType = "audio-chunk";
19940
+ class AudioPlayer {
19941
+ constructor(device, stream) {
19942
+ __publicField(this, "muted", false);
19943
+ __publicField(this, "hasReceivedData", false);
19944
+ __publicField(this, "audioContext");
19945
+ __publicField(this, "chunks", []);
19946
+ __publicField(this, "isPlaying", false);
19947
+ __publicField(this, "startTime", 0);
19948
+ __publicField(this, "lastChunkOffset", 0);
19949
+ __publicField(this, "bufferSize", 3);
19950
+ __publicField(this, "receive", async (msg) => {
19951
+ var _a;
19952
+ const data = (_a = msg.payload.audioChunk) == null ? void 0 : _a.chunk_data;
19953
+ if (!data) {
19954
+ return;
19955
+ }
19956
+ if (!this.hasReceivedData) {
19957
+ this.hasReceivedData = true;
19958
+ }
19959
+ const { audioContext, muted } = this;
19960
+ if (!audioContext || msg.header.stream.streamType !== rtcAudioChunkStreamType || muted !== false) {
19961
+ return;
19962
+ }
19963
+ const arrayBuffer = stringToArrayBuffer(data);
19964
+ try {
19965
+ await audioContext.decodeAudioData(arrayBuffer.buffer, this.scheduleChunk);
19966
+ } catch (error) {
19967
+ console.warn("Error decoding audio buffer, changing audioWireFormat on agent", { error });
19968
+ this.changeAudioWireFormat("wav");
19969
+ }
19970
+ });
19971
+ __publicField(this, "scheduleChunk", (buffer) => {
19972
+ const { audioContext } = this;
19973
+ if (!audioContext) {
19974
+ return;
19975
+ }
19976
+ if (this.chunks.length > this.bufferSize || this.isPlaying === false) {
19977
+ this.chunks.forEach((c) => {
19978
+ c.stop();
19979
+ });
19980
+ this.isPlaying = false;
19981
+ this.chunks = [];
19982
+ }
19983
+ const chunk = this.createChunk(buffer);
19984
+ if (!chunk) {
19985
+ return;
19986
+ }
19987
+ if (!chunk.buffer) {
19988
+ return;
19989
+ }
19990
+ if (this.isPlaying === false) {
19991
+ this.startTime = audioContext.currentTime;
19992
+ this.lastChunkOffset = 0;
19993
+ this.isPlaying = true;
19994
+ }
19995
+ chunk.start(this.startTime + this.lastChunkOffset, 0, buffer.duration);
19996
+ this.lastChunkOffset += chunk.buffer.duration;
19997
+ this.chunks.push(chunk);
19998
+ });
19999
+ this.device = device;
20000
+ this.stream = stream;
20001
+ this.device.startListeningToRealtimeDataStream(stream);
20002
+ this.device.addRealtimeListener((_peerId, msg) => {
20003
+ this.receive(msg);
20004
+ });
20005
+ if (browser() === "Safari" || browser() === "IE") {
20006
+ this.changeAudioWireFormat("wav");
20007
+ } else {
20008
+ this.changeAudioWireFormat("opus");
20009
+ }
20010
+ const AudioContext = window.AudioContext || window.webkitAudioContext;
20011
+ this.audioContext = new AudioContext();
20012
+ }
20013
+ async play() {
20014
+ var _a, _b;
20015
+ if (((_a = this.audioContext) == null ? void 0 : _a.state) === "suspended") {
20016
+ await ((_b = this.audioContext) == null ? void 0 : _b.resume());
20017
+ }
20018
+ this.muted = false;
20019
+ }
20020
+ async pause() {
20021
+ await this.audioContext.suspend();
20022
+ this.muted = true;
20023
+ }
20024
+ destroy() {
20025
+ this.device.stopListeningToRealtimeDataStream(this.stream);
20026
+ }
20027
+ createChunk(buffer) {
20028
+ const { audioContext } = this;
20029
+ if (!audioContext) {
20030
+ return;
20031
+ }
20032
+ const source = audioContext.createBufferSource();
20033
+ source.buffer = buffer;
20034
+ source.connect(audioContext.destination);
20035
+ source.loop = false;
20036
+ source.onended = (_) => {
20037
+ this.chunks.splice(this.chunks.indexOf(source), 1);
20038
+ if (this.chunks.length === 0) {
20039
+ this.isPlaying = false;
20040
+ }
20041
+ };
20042
+ return source;
20043
+ }
20044
+ changeAudioWireFormat(newFormat) {
20045
+ const { stream } = this;
20046
+ fork((async () => {
20047
+ await this.device.changeStreamAudioType(stream.name, newFormat);
20048
+ })());
20049
+ }
20050
+ }
19910
20051
  const accessLevels = ["viewer", "operator", "administrator"];
19911
20052
  const viewer = "viewer";
19912
20053
  const operator = "operator";
@@ -19958,4 +20099,7 @@ const moduleName = urlParams.get("module");
19958
20099
  if (moduleName) {
19959
20100
  Authentication.listenForRefresh();
19960
20101
  }
19961
- export { App, Authentication, BinaryRequestDataChannel, CaptureStream, DataChannel, Device, Fleet, KeyValue, Manipulator, PeerDevice, SessionType, TextRequestDataChannel, accessLevels, administrator, aggregateLevels, annotationTypes, eventTypes, healthStatuses, interventionTypes, operator, severities, videoMimeTypes, viewer };
20102
+ var IRtcSendConfiguration = dist.exports.IRtcSendConfiguration;
20103
+ var IRtcStreamMessage = dist.exports.IRtcStreamMessage;
20104
+ var IRtcStreamPayload = dist.exports.IRtcStreamPayload;
20105
+ export { App, AudioPlayer, Authentication, BinaryRequestDataChannel, CaptureStream, DataChannel, Device, Fleet, IRtcSendConfiguration, IRtcStreamMessage, IRtcStreamPayload, KeyValue, Manipulator, PeerDevice, SessionType, TextRequestDataChannel, accessLevels, administrator, aggregateLevels, annotationTypes, eventTypes, healthStatuses, interventionTypes, operator, severities, videoMimeTypes, viewer };