@absolutejs/voice 0.0.22-beta.591 → 0.0.22-beta.593
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 +21 -2
- package/dist/testing/index.js +21 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3753,7 +3753,8 @@ var normalizeText2 = (text) => text.trim().replace(/\s+/g, " ");
|
|
|
3753
3753
|
var getAudioChunkDurationMs = (chunk) => chunk.byteLength / (DEFAULT_FORMAT.sampleRateHz * DEFAULT_FORMAT.channels * 2) * 1000;
|
|
3754
3754
|
var getBufferedAudioDurationMs = (chunks) => chunks.reduce((total, chunk) => total + getAudioChunkDurationMs(chunk), 0);
|
|
3755
3755
|
var STREAM_SENTENCE_BOUNDARY = /[.!?\u2026]['")\]]*\s/;
|
|
3756
|
-
var
|
|
3756
|
+
var STREAM_CLAUSE_BOUNDARY = /[,;:]\s/g;
|
|
3757
|
+
var MAX_TTS_CHUNK_CHARS = 320;
|
|
3757
3758
|
var nextSpeakableBoundary = (buffer) => {
|
|
3758
3759
|
const match = STREAM_SENTENCE_BOUNDARY.exec(buffer);
|
|
3759
3760
|
return match ? match.index + match[0].length : -1;
|
|
@@ -3762,6 +3763,12 @@ var softCutBoundary = (buffer) => {
|
|
|
3762
3763
|
if (buffer.length < MAX_TTS_CHUNK_CHARS)
|
|
3763
3764
|
return -1;
|
|
3764
3765
|
const window2 = buffer.slice(0, MAX_TTS_CHUNK_CHARS);
|
|
3766
|
+
let lastClause = -1;
|
|
3767
|
+
for (const match of window2.matchAll(STREAM_CLAUSE_BOUNDARY)) {
|
|
3768
|
+
lastClause = match.index + match[0].length;
|
|
3769
|
+
}
|
|
3770
|
+
if (lastClause > 0)
|
|
3771
|
+
return lastClause;
|
|
3765
3772
|
const lastSpace = window2.lastIndexOf(" ");
|
|
3766
3773
|
return lastSpace > 0 ? lastSpace + 1 : MAX_TTS_CHUNK_CHARS;
|
|
3767
3774
|
};
|
|
@@ -6282,9 +6289,21 @@ var createVoiceSession = (options) => {
|
|
|
6282
6289
|
amdFirstAudioAt = Date.now();
|
|
6283
6290
|
}
|
|
6284
6291
|
speechDetected = true;
|
|
6285
|
-
clearSilenceTimer();
|
|
6286
6292
|
kickCallSilenceWatchdog();
|
|
6287
6293
|
backchannelDriver?.noteSpeech();
|
|
6294
|
+
const latest = await readSession();
|
|
6295
|
+
const sttQuietMs = latest.currentTurn.lastTranscriptAt !== undefined ? Date.now() - latest.currentTurn.lastTranscriptAt : Number.POSITIVE_INFINITY;
|
|
6296
|
+
const hasTurnTextDespiteNoise = Boolean(buildTurnText(latest.currentTurn.transcripts, latest.currentTurn.partialText, {
|
|
6297
|
+
partialEndedAtMs: latest.currentTurn.partialEndedAt,
|
|
6298
|
+
partialStartedAtMs: latest.currentTurn.partialStartedAt
|
|
6299
|
+
}));
|
|
6300
|
+
if (hasTurnTextDespiteNoise && sttQuietMs >= turnDetection.silenceMs) {
|
|
6301
|
+
if (!silenceTimer) {
|
|
6302
|
+
scheduleSilenceCommit(0);
|
|
6303
|
+
}
|
|
6304
|
+
} else {
|
|
6305
|
+
clearSilenceTimer();
|
|
6306
|
+
}
|
|
6288
6307
|
} else if (speechDetected) {
|
|
6289
6308
|
backchannelDriver?.noteSilence();
|
|
6290
6309
|
const currentSession = await readSession();
|
package/dist/testing/index.js
CHANGED
|
@@ -5980,7 +5980,8 @@ var normalizeText2 = (text) => text.trim().replace(/\s+/g, " ");
|
|
|
5980
5980
|
var getAudioChunkDurationMs = (chunk) => chunk.byteLength / (DEFAULT_FORMAT.sampleRateHz * DEFAULT_FORMAT.channels * 2) * 1000;
|
|
5981
5981
|
var getBufferedAudioDurationMs = (chunks) => chunks.reduce((total, chunk) => total + getAudioChunkDurationMs(chunk), 0);
|
|
5982
5982
|
var STREAM_SENTENCE_BOUNDARY = /[.!?\u2026]['")\]]*\s/;
|
|
5983
|
-
var
|
|
5983
|
+
var STREAM_CLAUSE_BOUNDARY = /[,;:]\s/g;
|
|
5984
|
+
var MAX_TTS_CHUNK_CHARS = 320;
|
|
5984
5985
|
var nextSpeakableBoundary = (buffer) => {
|
|
5985
5986
|
const match = STREAM_SENTENCE_BOUNDARY.exec(buffer);
|
|
5986
5987
|
return match ? match.index + match[0].length : -1;
|
|
@@ -5989,6 +5990,12 @@ var softCutBoundary = (buffer) => {
|
|
|
5989
5990
|
if (buffer.length < MAX_TTS_CHUNK_CHARS)
|
|
5990
5991
|
return -1;
|
|
5991
5992
|
const window2 = buffer.slice(0, MAX_TTS_CHUNK_CHARS);
|
|
5993
|
+
let lastClause = -1;
|
|
5994
|
+
for (const match of window2.matchAll(STREAM_CLAUSE_BOUNDARY)) {
|
|
5995
|
+
lastClause = match.index + match[0].length;
|
|
5996
|
+
}
|
|
5997
|
+
if (lastClause > 0)
|
|
5998
|
+
return lastClause;
|
|
5992
5999
|
const lastSpace = window2.lastIndexOf(" ");
|
|
5993
6000
|
return lastSpace > 0 ? lastSpace + 1 : MAX_TTS_CHUNK_CHARS;
|
|
5994
6001
|
};
|
|
@@ -8509,9 +8516,21 @@ var createVoiceSession = (options) => {
|
|
|
8509
8516
|
amdFirstAudioAt = Date.now();
|
|
8510
8517
|
}
|
|
8511
8518
|
speechDetected = true;
|
|
8512
|
-
clearSilenceTimer();
|
|
8513
8519
|
kickCallSilenceWatchdog();
|
|
8514
8520
|
backchannelDriver?.noteSpeech();
|
|
8521
|
+
const latest = await readSession();
|
|
8522
|
+
const sttQuietMs = latest.currentTurn.lastTranscriptAt !== undefined ? Date.now() - latest.currentTurn.lastTranscriptAt : Number.POSITIVE_INFINITY;
|
|
8523
|
+
const hasTurnTextDespiteNoise = Boolean(buildTurnText(latest.currentTurn.transcripts, latest.currentTurn.partialText, {
|
|
8524
|
+
partialEndedAtMs: latest.currentTurn.partialEndedAt,
|
|
8525
|
+
partialStartedAtMs: latest.currentTurn.partialStartedAt
|
|
8526
|
+
}));
|
|
8527
|
+
if (hasTurnTextDespiteNoise && sttQuietMs >= turnDetection.silenceMs) {
|
|
8528
|
+
if (!silenceTimer) {
|
|
8529
|
+
scheduleSilenceCommit(0);
|
|
8530
|
+
}
|
|
8531
|
+
} else {
|
|
8532
|
+
clearSilenceTimer();
|
|
8533
|
+
}
|
|
8515
8534
|
} else if (speechDetected) {
|
|
8516
8535
|
backchannelDriver?.noteSilence();
|
|
8517
8536
|
const currentSession = await readSession();
|