first commit

This commit is contained in:
douboer
2026-03-21 18:57:10 +08:00
commit c49aa1a5e9
570 changed files with 107167 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
/* global module */
/**
* 终端播报长度配置拆成“总量”和“单段”两层:
* 1. 总量决定一轮回答最多取多少正文;
* 2. 单段决定每次送给 TTS 的请求大小,用来压低首段等待时延;
* 3. 单段限制必须保守落在 gateway 当前长度校验之内;
* 4. “分片长度”只控制单段字符窗口,实际仍会再受 UTF-8 byte 上限兜底。
*/
const DEFAULT_TTS_SPEAKABLE_MAX_CHARS = 500;
const MIN_TTS_SPEAKABLE_MAX_CHARS = 120;
const MAX_TTS_SPEAKABLE_MAX_CHARS = 1200;
const DEFAULT_TTS_SEGMENT_MAX_CHARS = 80;
const MIN_TTS_SEGMENT_MAX_CHARS = 40;
const MAX_TTS_SEGMENT_MAX_CHARS = 200;
const TTS_SEGMENT_MAX_CHARS = DEFAULT_TTS_SEGMENT_MAX_CHARS;
const TTS_SEGMENT_MAX_UTF8_BYTES = DEFAULT_TTS_SEGMENT_MAX_CHARS * 3;
function normalizeTtsSpeakableMaxChars(value) {
const parsed = Number(value);
if (!Number.isFinite(parsed)) {
return DEFAULT_TTS_SPEAKABLE_MAX_CHARS;
}
const normalized = Math.round(parsed);
if (normalized < MIN_TTS_SPEAKABLE_MAX_CHARS) {
return MIN_TTS_SPEAKABLE_MAX_CHARS;
}
if (normalized > MAX_TTS_SPEAKABLE_MAX_CHARS) {
return MAX_TTS_SPEAKABLE_MAX_CHARS;
}
return normalized;
}
function normalizeTtsSegmentMaxChars(value) {
const parsed = Number(value);
if (!Number.isFinite(parsed)) {
return DEFAULT_TTS_SEGMENT_MAX_CHARS;
}
const normalized = Math.round(parsed);
if (normalized < MIN_TTS_SEGMENT_MAX_CHARS) {
return MIN_TTS_SEGMENT_MAX_CHARS;
}
if (normalized > MAX_TTS_SEGMENT_MAX_CHARS) {
return MAX_TTS_SEGMENT_MAX_CHARS;
}
return normalized;
}
/**
* 总量截断只负责控制“这一轮最多保留多少正文”,并不直接对应单次网关请求。
* 对中文按 3 bytes/字估算,可让 500 字正文完整进入后续分段流程。
*/
function resolveTtsSpeakableUtf8ByteLimit(maxChars) {
const normalized = normalizeTtsSpeakableMaxChars(maxChars);
return Math.max(TTS_SEGMENT_MAX_UTF8_BYTES, Math.min(normalized * 3, MAX_TTS_SPEAKABLE_MAX_CHARS * 3));
}
/**
* 单段 byte 限制始终卡在安全阈值内:
* 1. 默认 80 字对应 240 bytes
* 2. 即使用户把分片长度调大,最终也不会超过 360 bytes
* 3. 这样可避免单段再次撞到网关 450 bytes 的校验。
*/
function resolveTtsSegmentUtf8ByteLimit(maxChars) {
const normalized = normalizeTtsSegmentMaxChars(maxChars);
return Math.max(TTS_SEGMENT_MAX_UTF8_BYTES, Math.min(normalized * 3, 360));
}
module.exports = {
DEFAULT_TTS_SPEAKABLE_MAX_CHARS,
MIN_TTS_SPEAKABLE_MAX_CHARS,
MAX_TTS_SPEAKABLE_MAX_CHARS,
DEFAULT_TTS_SEGMENT_MAX_CHARS,
MIN_TTS_SEGMENT_MAX_CHARS,
MAX_TTS_SEGMENT_MAX_CHARS,
TTS_SEGMENT_MAX_CHARS,
TTS_SEGMENT_MAX_UTF8_BYTES,
normalizeTtsSpeakableMaxChars,
normalizeTtsSegmentMaxChars,
resolveTtsSpeakableUtf8ByteLimit,
resolveTtsSegmentUtf8ByteLimit
};