fix(conversation): 修复实时会话 TTS/回复被离屏 WS 抢占
- 列表预热仅预取消息缓存,避免后台 WebSocket 覆盖服务端连接 - RealtimeSession UI 回调按 owner 独占,防止 offscreen 覆盖聊天页 - 列表页聚焦时再 prewarm,会话页 TTS 入队优先 base64 - 管线下发 TTS 同时带 audio_base64 与 audio_url;协议说明同步 - 移除 TTS 排查用前后端调试日志,保留错误/告警 - 补充 WS / RealtimeSession / entry-warmup / 播放器相关单测 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -94,6 +94,12 @@ export function usePlayer(): UsePlayerResult {
|
||||
|
||||
const acquired = await audioFocus.acquireForPlayback();
|
||||
if (!acquired) {
|
||||
/**
|
||||
* 录音占用时 acquire 失败且队列尚未 shift;若用户进入会话前焦点已在
|
||||
* `recorder`,可能不会再次触发 `onOwnerChange('recorder')`,旧的
|
||||
* `wasBlockedByRecorderRef` 不会被置位,录音结束后也不会重试 playNext。
|
||||
*/
|
||||
wasBlockedByRecorderRef.current = true;
|
||||
setStatus('idle');
|
||||
return;
|
||||
}
|
||||
@@ -172,14 +178,17 @@ export function usePlayer(): UsePlayerResult {
|
||||
|
||||
if (owner === null && wasBlockedByRecorderRef.current) {
|
||||
wasBlockedByRecorderRef.current = false;
|
||||
if (queueRef.current.length > 0 && status === 'idle') {
|
||||
playNext();
|
||||
if (
|
||||
queueRef.current.length > 0 &&
|
||||
playbackActiveUriRef.current === null
|
||||
) {
|
||||
void playNext();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return unsub;
|
||||
}, [status, currentSource, playNext]);
|
||||
}, [currentSource, playNext]);
|
||||
|
||||
const enqueue = useCallback(
|
||||
async (item: PlaybackItem) => {
|
||||
|
||||
Reference in New Issue
Block a user