fix(voice): 浏览器语音默认走服务端 ASR
Web Speech 依赖 Google,国内浏览器常无法转文字;支持麦克风时改为录音后走自有 ASR,并补全网络异常时的降级匹配。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,10 +1,10 @@
|
|||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { transcribeOneShot } from '../voice/asrTransport';
|
import { transcribeOneShot } from '../voice/asrTransport';
|
||||||
import { mapMicError } from '../voice/audioAnalyser';
|
import { mapMicError } from '../voice/audioAnalyser';
|
||||||
import { shouldFallbackToServerAsr, shouldPreferServerAsr } from '../voice/capabilities';
|
import { shouldFallbackToServerAsr, shouldUseLiveSpeech } from '../voice/capabilities';
|
||||||
import { MicCapture } from '../voice/micCapture';
|
import { MicCapture } from '../voice/micCapture';
|
||||||
import { waitForMicRelease } from '../voice/micSession';
|
import { waitForMicRelease } from '../voice/micSession';
|
||||||
import { createLiveSpeechRecognition, isSpeechRecognitionSupported } from '../voice/speechRecognition';
|
import { createLiveSpeechRecognition } from '../voice/speechRecognition';
|
||||||
import type { VoiceSessionPhase } from '../voice/types';
|
import type { VoiceSessionPhase } from '../voice/types';
|
||||||
|
|
||||||
const MIN_RECORD_MS = 500;
|
const MIN_RECORD_MS = 500;
|
||||||
@@ -19,9 +19,7 @@ export function useVoiceSession({
|
|||||||
const [phase, setPhase] = useState<VoiceSessionPhase>('idle');
|
const [phase, setPhase] = useState<VoiceSessionPhase>('idle');
|
||||||
const [text, setText] = useState('');
|
const [text, setText] = useState('');
|
||||||
const [analyser, setAnalyser] = useState<AnalyserNode | null>(null);
|
const [analyser, setAnalyser] = useState<AnalyserNode | null>(null);
|
||||||
const [liveRecognition, setLiveRecognition] = useState(
|
const [liveRecognition, setLiveRecognition] = useState(shouldUseLiveSpeech());
|
||||||
isSpeechRecognitionSupported() && !shouldPreferServerAsr(),
|
|
||||||
);
|
|
||||||
|
|
||||||
const committedRef = useRef('');
|
const committedRef = useRef('');
|
||||||
const interimRef = useRef('');
|
const interimRef = useRef('');
|
||||||
@@ -155,7 +153,7 @@ export function useVoiceSession({
|
|||||||
if (sessionRef.current !== sessionId) return;
|
if (sessionRef.current !== sessionId) return;
|
||||||
|
|
||||||
startedAtRef.current = Date.now();
|
startedAtRef.current = Date.now();
|
||||||
const useLiveSpeech = isSpeechRecognitionSupported() && !shouldPreferServerAsr();
|
const useLiveSpeech = shouldUseLiveSpeech();
|
||||||
|
|
||||||
if (useLiveSpeech) {
|
if (useLiveSpeech) {
|
||||||
const recognition = createLiveSpeechRecognition({
|
const recognition = createLiveSpeechRecognition({
|
||||||
|
|||||||
@@ -2,16 +2,26 @@ import { isWechatBrowser } from '../utils/wechat';
|
|||||||
import { MicCapture } from './micCapture';
|
import { MicCapture } from './micCapture';
|
||||||
import { isSpeechRecognitionSupported } from './speechRecognition';
|
import { isSpeechRecognitionSupported } from './speechRecognition';
|
||||||
|
|
||||||
/** 微信内置浏览器 Web Speech 不可用,直接走服务端 ASR。 */
|
/**
|
||||||
|
* 优先服务端 ASR(录音后识别):
|
||||||
|
* - 微信内 Web Speech 不可用;
|
||||||
|
* - 普通浏览器若支持麦克风,也走自有 ASR(Web Speech 依赖 Google,国内常无结果)。
|
||||||
|
*/
|
||||||
export function shouldPreferServerAsr(): boolean {
|
export function shouldPreferServerAsr(): boolean {
|
||||||
return isWechatBrowser();
|
if (isWechatBrowser()) return true;
|
||||||
|
return MicCapture.isSupported();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Web Speech 出现这些错误时可改用服务端 ASR(录音 + 完成识别)。 */
|
/** 仍尝试 Web Speech 时,出现这些错误可降级为服务端 ASR。 */
|
||||||
export function shouldFallbackToServerAsr(errorMessage: string): boolean {
|
export function shouldFallbackToServerAsr(errorMessage: string): boolean {
|
||||||
if (shouldPreferServerAsr()) return false;
|
if (shouldPreferServerAsr()) return false;
|
||||||
if (!MicCapture.isSupported()) return false;
|
if (!MicCapture.isSupported()) return false;
|
||||||
return /network|service-not-allowed|语音识别失败|无法启动语音识别/i.test(errorMessage);
|
return /network|网络异常|service-not-allowed|语音识别失败|无法启动语音识别/i.test(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 是否使用浏览器 Web Speech 实时听写(仅在不走服务端 ASR 且 API 可用时)。 */
|
||||||
|
export function shouldUseLiveSpeech(): boolean {
|
||||||
|
return isSpeechRecognitionSupported() && !shouldPreferServerAsr();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Whether voice input may work in this browser (mic and/or live speech). */
|
/** Whether voice input may work in this browser (mic and/or live speech). */
|
||||||
|
|||||||
Reference in New Issue
Block a user