You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

react-speech-kit语音转文字后自动调用speak方法重复触发问题求助

解决方案

重复调用问题修复方法

  • 根因1:onEnd回调被重复绑定/多次触发,没有做并发控制
    修复:新增执行锁标记运行状态,避免同一时间重复发起请求和调用speak
  • 根因2:回调函数未用useCallback包裹,组件重渲染时重复向语音识别实例注册新的onEnd回调,导致同一次识别结束触发多次逻辑
    修复:用useCallback包裹onEnd函数,明确标注依赖项
  • 根因3:未清空之前的语音播放队列,多次调用speak会叠加播放任务,看起来像重复播放同一段文本
    修复:调用speak前先执行cancel方法清空现有播放队列

完整修复代码示例

import { useCallback, useRef, useState } from 'react';
import { useSpeechRecognition, useSpeechSynthesis } from 'react-speech-kit';

function VoiceComponent() {
  const [value, setValue] = useState('');
  const [response, setResponse] = useState('');
  // 执行锁:true表示正在处理请求/播放,阻止重复触发
  const isProcessingRef = useRef(false);
  const { speak, cancel } = useSpeechSynthesis();
  const { listen, stop } = useSpeechRecognition({
    onResult: (result) => {
      setValue(result);
    },
    // 用useCallback包裹避免重复绑定回调
    onEnd: useCallback(() => {
      if (isProcessingRef.current) return;
      isProcessingRef.current = true;

      fetch(`http://api/Main?id=test&lang=kor&req=${encodeURIComponent(value)}`, {})
        .then((res) => res.json())
        .then(
          (result) => {
            setResponse(result.res);
            // 先清空历史播放队列再播放新内容
            cancel();
            speak({ text: result.res });
          },
          (error) => {
            console.log(error);
          }
        )
        .finally(() => {
          // 处理完成后释放锁
          isProcessingRef.current = false;
        });
    }, [value, cancel, speak])
  });

  // 其余组件业务逻辑
  return <div>你的组件UI</div>
}

补充说明

上述代码对请求参数加了encodeURIComponent转义,避免语音识别结果包含特殊字符时请求参数异常。

内容的提问来源于stack exchange,提问作者naoval luthfi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 17:54:01