@sdata/web-vue 3.22.1 → 3.22.3
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/es/sender/use-speech.d.ts +1 -1
- package/es/sender/use-speech.js +53 -30
- package/json/web-types.json +1 -1
- package/package.json +1 -1
|
@@ -12,7 +12,7 @@ interface UseSpeechOptions {
|
|
|
12
12
|
export declare function useSpeech(allowSpeech: MaybeRefOrGetter<SenderAllowSpeech | undefined>, options: UseSpeechOptions): {
|
|
13
13
|
available: import("vue").ComputedRef<boolean>;
|
|
14
14
|
recording: import("vue").ComputedRef<boolean>;
|
|
15
|
-
requesting: import("vue").
|
|
15
|
+
requesting: import("vue").ComputedRef<boolean>;
|
|
16
16
|
statusText: import("vue").ComputedRef<string>;
|
|
17
17
|
trigger: (breakRecording?: boolean) => Promise<void>;
|
|
18
18
|
};
|
package/es/sender/use-speech.js
CHANGED
|
@@ -13,6 +13,7 @@ class SdSenderAudioProcessor extends AudioWorkletProcessor {
|
|
|
13
13
|
this.bufferSize = Math.max(128, options.processorOptions?.bufferSize || ${DEFAULT_BUFFER_SIZE});
|
|
14
14
|
this.buffer = new Float32Array(this.bufferSize);
|
|
15
15
|
this.offset = 0;
|
|
16
|
+
this.stopped = false;
|
|
16
17
|
this.port.onmessage = (event) => {
|
|
17
18
|
if (event.data?.type !== 'flush') return;
|
|
18
19
|
if (this.offset > 0) {
|
|
@@ -20,11 +21,13 @@ class SdSenderAudioProcessor extends AudioWorkletProcessor {
|
|
|
20
21
|
this.port.postMessage(chunk.buffer, [chunk.buffer]);
|
|
21
22
|
this.offset = 0;
|
|
22
23
|
}
|
|
24
|
+
this.stopped = true;
|
|
23
25
|
this.port.postMessage({ type: 'flushed' });
|
|
24
26
|
};
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
process(inputs) {
|
|
30
|
+
if (this.stopped) return false;
|
|
28
31
|
const channels = inputs[0];
|
|
29
32
|
if (!channels?.length) return true;
|
|
30
33
|
const frames = channels[0].length;
|
|
@@ -55,6 +58,7 @@ function useSpeech(allowSpeech, options) {
|
|
|
55
58
|
const supported = shallowRef(false);
|
|
56
59
|
const internalRecording = shallowRef(false);
|
|
57
60
|
const requesting = shallowRef(false);
|
|
61
|
+
const stopping = shallowRef(false);
|
|
58
62
|
const captureError = shallowRef();
|
|
59
63
|
const stream = shallowRef();
|
|
60
64
|
const audioContext = shallowRef();
|
|
@@ -65,7 +69,8 @@ function useSpeech(allowSpeech, options) {
|
|
|
65
69
|
const chunks = shallowRef(0);
|
|
66
70
|
const sequence = shallowRef(0);
|
|
67
71
|
let generatedWorkletUrl;
|
|
68
|
-
let
|
|
72
|
+
let resolveWorkletStop;
|
|
73
|
+
let workletStopRequested = false;
|
|
69
74
|
let workletReady = false;
|
|
70
75
|
let disposed = false;
|
|
71
76
|
const recording = computed(() => controlled.value && typeof config.value === "object" ? Boolean(config.value.recording) : internalRecording.value);
|
|
@@ -122,25 +127,36 @@ function useSpeech(allowSpeech, options) {
|
|
|
122
127
|
else reject(errorEvent.error);
|
|
123
128
|
};
|
|
124
129
|
});
|
|
125
|
-
const
|
|
130
|
+
const stopWorklet = () => new Promise((resolve) => {
|
|
126
131
|
var _workletNode$value;
|
|
127
132
|
const port = (_workletNode$value = workletNode.value) === null || _workletNode$value === void 0 ? void 0 : _workletNode$value.port;
|
|
128
|
-
if (!port) {
|
|
133
|
+
if (!port || workletStopRequested) {
|
|
129
134
|
resolve();
|
|
130
135
|
return;
|
|
131
136
|
}
|
|
132
|
-
|
|
133
|
-
|
|
137
|
+
workletStopRequested = true;
|
|
138
|
+
let settled = false;
|
|
139
|
+
const finish = () => {
|
|
140
|
+
if (settled) return;
|
|
141
|
+
settled = true;
|
|
134
142
|
window.clearTimeout(timeout);
|
|
135
|
-
|
|
143
|
+
resolveWorkletStop = void 0;
|
|
136
144
|
resolve();
|
|
137
145
|
};
|
|
146
|
+
const timeout = window.setTimeout(finish, 100);
|
|
147
|
+
resolveWorkletStop = finish;
|
|
138
148
|
port.postMessage({ type: "flush" });
|
|
139
149
|
});
|
|
140
150
|
const releaseResources = function() {
|
|
141
151
|
var _ref = _asyncToGenerator(function* () {
|
|
142
|
-
var
|
|
143
|
-
|
|
152
|
+
var _sourceNode$value, _stream$value, _audioContext$value;
|
|
153
|
+
const currentWorkletNode = workletNode.value;
|
|
154
|
+
yield stopWorklet();
|
|
155
|
+
if (currentWorkletNode) {
|
|
156
|
+
currentWorkletNode.port.onmessage = null;
|
|
157
|
+
currentWorkletNode.port.close();
|
|
158
|
+
currentWorkletNode.disconnect();
|
|
159
|
+
}
|
|
144
160
|
(_sourceNode$value = sourceNode.value) === null || _sourceNode$value === void 0 || _sourceNode$value.disconnect();
|
|
145
161
|
(_stream$value = stream.value) === null || _stream$value === void 0 || _stream$value.getTracks().forEach((track) => track.stop());
|
|
146
162
|
if (((_audioContext$value = audioContext.value) === null || _audioContext$value === void 0 ? void 0 : _audioContext$value.state) === "running") yield audioContext.value.suspend();
|
|
@@ -166,25 +182,30 @@ function useSpeech(allowSpeech, options) {
|
|
|
166
182
|
}();
|
|
167
183
|
const stopCapture = function() {
|
|
168
184
|
var _ref3 = _asyncToGenerator(function* (reason = "manual") {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
185
|
+
if (!internalRecording.value || stopping.value) return;
|
|
186
|
+
stopping.value = true;
|
|
187
|
+
try {
|
|
188
|
+
var _socket$value, _config$value$onRecor, _config$value;
|
|
189
|
+
yield stopWorklet();
|
|
190
|
+
const endedAt = performance.now();
|
|
191
|
+
internalRecording.value = false;
|
|
192
|
+
if (((_socket$value = socket.value) === null || _socket$value === void 0 ? void 0 : _socket$value.readyState) === WebSocket.OPEN && typeof config.value === "object" && config.value.sendMetadata !== false) socket.value.send(JSON.stringify({
|
|
193
|
+
type: "end",
|
|
194
|
+
reason
|
|
195
|
+
}));
|
|
196
|
+
yield releaseResources();
|
|
197
|
+
if (typeof config.value === "object") (_config$value$onRecor = (_config$value = config.value).onRecordingChange) === null || _config$value$onRecor === void 0 || _config$value$onRecor.call(_config$value, false);
|
|
198
|
+
options.onEnd({
|
|
199
|
+
source: "capture",
|
|
200
|
+
reason,
|
|
201
|
+
startedAt: startedAt.value,
|
|
202
|
+
endedAt,
|
|
203
|
+
duration: endedAt - startedAt.value,
|
|
204
|
+
chunks: chunks.value
|
|
205
|
+
});
|
|
206
|
+
} finally {
|
|
207
|
+
stopping.value = false;
|
|
208
|
+
}
|
|
188
209
|
});
|
|
189
210
|
return function stopCapture() {
|
|
190
211
|
return _ref3.apply(this, arguments);
|
|
@@ -192,7 +213,7 @@ function useSpeech(allowSpeech, options) {
|
|
|
192
213
|
}();
|
|
193
214
|
const startCapture = function() {
|
|
194
215
|
var _ref4 = _asyncToGenerator(function* () {
|
|
195
|
-
if (requesting.value || internalRecording.value || !available.value) return;
|
|
216
|
+
if (requesting.value || stopping.value || internalRecording.value || !available.value) return;
|
|
196
217
|
requesting.value = true;
|
|
197
218
|
captureError.value = void 0;
|
|
198
219
|
let phase = "permission";
|
|
@@ -240,12 +261,13 @@ function useSpeech(allowSpeech, options) {
|
|
|
240
261
|
channelCount: 1,
|
|
241
262
|
processorOptions: _objectSpread2(_objectSpread2({}, speechConfig === null || speechConfig === void 0 ? void 0 : speechConfig.processorOptions), {}, { bufferSize })
|
|
242
263
|
});
|
|
264
|
+
workletStopRequested = false;
|
|
243
265
|
workletNode.value = nextWorkletNode;
|
|
244
266
|
sourceNode.value = nextAudioContext.createMediaStreamSource(stream.value);
|
|
245
267
|
nextWorkletNode.port.onmessage = (event) => {
|
|
246
268
|
var _socket$value2;
|
|
247
269
|
if (!(event.data instanceof ArrayBuffer) && "type" in event.data) {
|
|
248
|
-
if (event.data.type === "flushed")
|
|
270
|
+
if (event.data.type === "flushed") resolveWorkletStop === null || resolveWorkletStop === void 0 || resolveWorkletStop();
|
|
249
271
|
return;
|
|
250
272
|
}
|
|
251
273
|
if (!internalRecording.value) return;
|
|
@@ -300,6 +322,7 @@ function useSpeech(allowSpeech, options) {
|
|
|
300
322
|
}();
|
|
301
323
|
const trigger = function() {
|
|
302
324
|
var _ref5 = _asyncToGenerator(function* (breakRecording = false) {
|
|
325
|
+
if (requesting.value || stopping.value) return;
|
|
303
326
|
if (breakRecording && !recording.value) return;
|
|
304
327
|
if (controlled.value && typeof config.value === "object") {
|
|
305
328
|
var _config$value$onRecor2, _config$value2;
|
|
@@ -349,7 +372,7 @@ function useSpeech(allowSpeech, options) {
|
|
|
349
372
|
return {
|
|
350
373
|
available,
|
|
351
374
|
recording,
|
|
352
|
-
requesting,
|
|
375
|
+
requesting: computed(() => requesting.value || stopping.value),
|
|
353
376
|
statusText,
|
|
354
377
|
trigger
|
|
355
378
|
};
|
package/json/web-types.json
CHANGED