Compare commits

..

No commits in common. "9360d598b0ffaeb4b5e46a54e1b3b0c24130452f" and "55502295ca51ddf680f822e4464cd04114718b59" have entirely different histories.

View File

@ -14,10 +14,8 @@ const SILENCE_TIMEOUT_MS = 5000;
const MIN_VALID_DURATION_SEC = 0.5;
// 播报超时保护毫秒如果FINISHED回调未触发自动恢复状态
const BROADCAST_TIMEOUT_MS = 60000;
const APPID = "i-sfyrkdr0ubepa";
const APP_KEY = "72vpdansbpg8nxjbxzhp";
// 打断词列表:识别到这些词时自动打断播报
const INTERRUPT_KEYWORDS = ["稍等一下", "停一下", "抱歉打断一下", "不好意思", "对不起", "停", "闭嘴"];
const APPID = "i-sfqpfp8qayj8e";
const APP_KEY = "rdjqhnp5q50e010wvw0z";
/**
*
@ -31,17 +29,6 @@ const hasSubstantialContent = (text: string): boolean => {
return cleaned.length > 0;
};
/**
*
*/
const containsInterruptKeyword = (text: string): boolean => {
const cleaned = text.replace(
/[\s\u3000.,!?;:,。!?;:、…—\-_·""''()\[\]【】《》<>]/g,
"",
);
return INTERRUPT_KEYWORDS.some((keyword) => cleaned.includes(keyword));
};
enum ReadyState {
UNINSTANTIATED = -1,
CONNECTING = 0,
@ -154,8 +141,6 @@ export function useDigitalHuman(options?: {
// 播报超时保护计时器
let broadcastTimeoutId: ReturnType<typeof setTimeout> | null = null;
// 打断词检测时间戳用于忽略打断后延迟到达的ASR结果
let lastInterruptTime = 0;
const clearBroadcastTimeout = () => {
if (broadcastTimeoutId !== null) {
@ -179,23 +164,19 @@ export function useDigitalHuman(options?: {
};
/**
*
* RTC模式下保持麦克风开启ASR识别打断词
* +
*/
const enterBroadcasting = () => {
isBroadcasting.value = true;
setPickPhase("broadcasting", "数字人开始播报");
startBroadcastTimeout();
// RTC模式播报期间保持麦克风开启允许ASR识别打断词
// RTC模式播报期间禁用拾音
if (audioMode.value === "rtc") {
humanInstanceRef.value?.muteMicrophone?.(false);
isMuted.value = false;
canTransfer.value = true;
const resumed = silenceDetector.resume();
if (!resumed) {
startSilenceDetection();
}
console.info("[播报] RTC模式麦克风保持开启允许ASR识别打断词");
humanInstanceRef.value?.muteMicrophone?.(true);
isMuted.value = true;
canTransfer.value = false;
silenceDetector.pause();
console.info("[播报] RTC模式麦克风已静音静音检测器已暂停");
}
console.info("[播报] 开始播报等待FINISHED信号");
};
@ -325,15 +306,9 @@ export function useDigitalHuman(options?: {
type,
} = JSON.parse(content.body);
if (type === "QUERY") {
// 播报期间检测打断词识别到打断词后仅中断播报并恢复拾音不调用LLM接口
// 播报期间忽略ASR结果双重守卫麦克风已静音但防止残余回调
if (pickPhase.value === "broadcasting") {
const hasInterrupt = containsInterruptKeyword(subtitleContent);
if (hasInterrupt) {
console.info(`[打断词检测] 播报中识别到打断词: "${subtitleContent}"自动打断仅中断播报不调用LLM`);
interrupt();
} else {
console.info(`[打断词检测] 播报中收到ASR结果: "${subtitleContent}",非打断词,忽略`);
}
console.info("[状态机] 播报中收到ASR结果忽略");
break;
}
@ -346,13 +321,6 @@ export function useDigitalHuman(options?: {
// idle 状态下收到 QUERY必须验证内容有实质才允许状态转换
// 环境噪音可能触发 ASR 产生空白/标点内容的 QUERY不应进入识别
if (pickPhase.value === "idle") {
// 忽略打断后3秒内到达的延迟ASR结果避免打断词被当作新输入
if (Date.now() - lastInterruptTime < 3000) {
console.info(
"[状态机] 打断后延迟到达的ASR结果忽略",
);
break;
}
const hasSubstance = hasSubstantialContent(subtitleContent);
if (!hasSubstance) {
console.info(
@ -528,8 +496,8 @@ export function useDigitalHuman(options?: {
token: token.value,
wrapperId: "human-wrapper",
connectParams: {
ttsPer: "20007751",
figureId: "4000821",
ttsPer: "5135",
figureId: "4000288",
resolutionHeight: 1920,
resolutionWidth: 1080,
inactiveDisconnectSec: 300,
@ -622,8 +590,6 @@ export function useDigitalHuman(options?: {
console.info("发送打断");
clearBroadcastTimeout();
await humanInstanceRef.value?.interrupt?.();
// 记录打断时间戳用于忽略打断后延迟到达的ASR结果
lastInterruptTime = Date.now();
// 打断后播报结束,恢复状态
if (isBroadcasting.value) {
isBroadcasting.value = false;