@lvce-editor/renderer-process 30.42.2 → 30.43.0

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.
@@ -10069,8 +10069,33 @@ const setupLevelMeter = (audioCtx, stream) => {
10069
10069
  source.connect(analyser);
10070
10070
  return analyser;
10071
10071
  };
10072
+ const isSpeechStoppedEvent = data => {
10073
+ if (typeof data !== 'string') {
10074
+ return false;
10075
+ }
10076
+ try {
10077
+ const event = JSON.parse(data);
10078
+ return event?.type === 'input_audio_buffer.speech_stopped';
10079
+ } catch {
10080
+ return false;
10081
+ }
10082
+ };
10083
+ const startInputAudioRecorder = (micStream, audioDebugPort) => {
10084
+ if (!audioDebugPort) {
10085
+ return undefined;
10086
+ }
10087
+ const recorder = new MediaRecorder(micStream);
10088
+ recorder.ondataavailable = event => {
10089
+ if (event.data.size > 0) {
10090
+ audioDebugPort.postMessage(event.data);
10091
+ }
10092
+ };
10093
+ recorder.start();
10094
+ return recorder;
10095
+ };
10072
10096
  const startWebRtcAudioStream = async options => {
10073
10097
  const {
10098
+ audioDebugPort,
10074
10099
  elementLocator,
10075
10100
  port,
10076
10101
  trackAudioData,
@@ -10103,6 +10128,7 @@ const startWebRtcAudioStream = async options => {
10103
10128
  const micStream = await navigator.mediaDevices.getUserMedia({
10104
10129
  audio: true
10105
10130
  });
10131
+ const inputAudioRecorder = startInputAudioRecorder(micStream, audioDebugPort);
10106
10132
  if (trackAudioData && audioCtx) {
10107
10133
  micAnalyzer = setupLevelMeter(audioCtx, micStream);
10108
10134
  }
@@ -10110,6 +10136,9 @@ const startWebRtcAudioStream = async options => {
10110
10136
  const dc = pc.createDataChannel('oai-events');
10111
10137
  dc.addEventListener('message', e => {
10112
10138
  port.postMessage(e.data);
10139
+ if (inputAudioRecorder?.state === 'recording' && isSpeechStoppedEvent(e.data)) {
10140
+ inputAudioRecorder.requestData();
10141
+ }
10113
10142
  });
10114
10143
  port.onmessage = event => {
10115
10144
  const {
@@ -10126,8 +10155,10 @@ const startWebRtcAudioStream = async options => {
10126
10155
  await pc.setLocalDescription(offer);
10127
10156
  pcs[uid] = {
10128
10157
  audioCtx,
10158
+ audioDebugPort,
10129
10159
  connection: pc,
10130
10160
  dataChannel: dc,
10161
+ inputAudioRecorder,
10131
10162
  micAnalyzer,
10132
10163
  micStream,
10133
10164
  port,
@@ -10164,8 +10195,10 @@ const stopWebRtcAudioStream = async uid => {
10164
10195
  // TODO use disposableMap maybe?
10165
10196
  const {
10166
10197
  audioCtx,
10198
+ audioDebugPort,
10167
10199
  connection,
10168
10200
  dataChannel,
10201
+ inputAudioRecorder,
10169
10202
  micStream,
10170
10203
  port,
10171
10204
  remoteAudio
@@ -10174,10 +10207,15 @@ const stopWebRtcAudioStream = async uid => {
10174
10207
  connection.ontrack = null;
10175
10208
  connection.close();
10176
10209
  dataChannel.close();
10210
+ if (inputAudioRecorder && inputAudioRecorder.state !== 'inactive') {
10211
+ inputAudioRecorder.ondataavailable = null;
10212
+ inputAudioRecorder.stop();
10213
+ }
10177
10214
  for (const t of micStream.getTracks()) {
10178
10215
  t.stop();
10179
10216
  }
10180
10217
  port.close();
10218
+ audioDebugPort?.close();
10181
10219
  remoteAudio.srcObject = null;
10182
10220
  if (audioCtx) {
10183
10221
  await audioCtx.close();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/renderer-process",
3
- "version": "30.42.2",
3
+ "version": "30.43.0",
4
4
  "keywords": [
5
5
  "lvce-editor",
6
6
  "renderer-process"