@siact/sime-x-vue 0.0.16 → 0.0.18
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/sime-x-vue.umd.js
CHANGED
|
@@ -1778,8 +1778,27 @@
|
|
|
1778
1778
|
let initPromise = null;
|
|
1779
1779
|
let audioCtx = null;
|
|
1780
1780
|
let sentenceBuffer = "";
|
|
1781
|
-
const
|
|
1782
|
-
const
|
|
1781
|
+
const SENTENCE_DELIMITERS = /[。!?;\n!?;]/;
|
|
1782
|
+
const LEADING_WEAK_PUNCTUATION = /^[\s,、;:,.!?。]+/;
|
|
1783
|
+
const TRAILING_SENTENCE_PUNCTUATION = /[。!?.!?;;]$/;
|
|
1784
|
+
const findSentenceBoundary = (text) => {
|
|
1785
|
+
for (let i = 0; i < text.length; i++) {
|
|
1786
|
+
const char = text[i];
|
|
1787
|
+
if (SENTENCE_DELIMITERS.test(char)) {
|
|
1788
|
+
return i;
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
return -1;
|
|
1792
|
+
};
|
|
1793
|
+
const stripMarkdown = (text) => text.replace(/```[\s\S]*?```/g, "").replace(/\|[^\n]*\|/g, "").replace(/#{1,6}\s*/g, "").replace(/\*\*(.*?)\*\*/g, "$1").replace(/\*(.*?)\*/g, "$1").replace(/`([^`]*)`/g, "$1").replace(/\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/^[-*+]\s+/gm, "").replace(/^>\s+/gm, "").replace(/\s*\+\s*/g, "加").replace(/\s*-\s*/g, "减").replace(/\s*×\s*/g, "乘").replace(/\s*÷\s*/g, "除").replace(/\s*=\s*/g, "等于").replace(/(\d)\.(\d)/g, "$1点$2").replace(/\n{2,}/g, "。").replace(/\n/g, ",").trim();
|
|
1794
|
+
const normalizeSpeakText = (text, options) => {
|
|
1795
|
+
const clean = stripMarkdown(text).replace(LEADING_WEAK_PUNCTUATION, "").trim();
|
|
1796
|
+
if (!clean) return "";
|
|
1797
|
+
if (options?.isFinalChunk && !TRAILING_SENTENCE_PUNCTUATION.test(clean)) {
|
|
1798
|
+
return `${clean}。`;
|
|
1799
|
+
}
|
|
1800
|
+
return clean;
|
|
1801
|
+
};
|
|
1783
1802
|
const warmUpAudio = () => {
|
|
1784
1803
|
if (!audioCtx || audioCtx.state === "closed") {
|
|
1785
1804
|
try {
|
|
@@ -1848,7 +1867,7 @@
|
|
|
1848
1867
|
return initPromise;
|
|
1849
1868
|
};
|
|
1850
1869
|
const speak = async (text) => {
|
|
1851
|
-
const clean =
|
|
1870
|
+
const clean = normalizeSpeakText(text);
|
|
1852
1871
|
if (!clean.trim()) return;
|
|
1853
1872
|
hasPendingAudio.value = true;
|
|
1854
1873
|
const tts = await ensureInstance();
|
|
@@ -1862,17 +1881,20 @@
|
|
|
1862
1881
|
const feed = (delta) => {
|
|
1863
1882
|
sentenceBuffer += delta;
|
|
1864
1883
|
while (true) {
|
|
1865
|
-
const
|
|
1866
|
-
if (
|
|
1867
|
-
const sentence = sentenceBuffer.slice(0,
|
|
1868
|
-
sentenceBuffer = sentenceBuffer.slice(
|
|
1884
|
+
const boundaryIndex = findSentenceBoundary(sentenceBuffer);
|
|
1885
|
+
if (boundaryIndex === -1) break;
|
|
1886
|
+
const sentence = sentenceBuffer.slice(0, boundaryIndex + 1).trim();
|
|
1887
|
+
sentenceBuffer = sentenceBuffer.slice(boundaryIndex + 1);
|
|
1869
1888
|
if (sentence.length > 0) speak(sentence);
|
|
1870
1889
|
}
|
|
1871
1890
|
};
|
|
1872
1891
|
const flush = () => {
|
|
1873
1892
|
const remaining = sentenceBuffer.trim();
|
|
1874
1893
|
sentenceBuffer = "";
|
|
1875
|
-
if (remaining.length > 0)
|
|
1894
|
+
if (remaining.length > 0) {
|
|
1895
|
+
const clean = normalizeSpeakText(remaining, { isFinalChunk: true });
|
|
1896
|
+
if (clean) void speak(clean);
|
|
1897
|
+
}
|
|
1876
1898
|
};
|
|
1877
1899
|
const stop = () => {
|
|
1878
1900
|
sentenceBuffer = "";
|