跳至主要内容

useSpeechRecognition

用於 React 的響應式語音識別 API

支持實時語音識別、可配置选项、跨瀏覽器兼容性和 TypeScript 支持。非常适合语音控制应用程序、听写功能和无障碍增强。

基本用法

即時編輯器
function Demo() {
  const {
    isSupported,
    isListening,
    isFinal,
    result,
    error,
    start,
    stop,
    toggle,
  } = useSpeechRecognition();

  if (!isSupported) {
    return <div>此瀏覽器不支持語音識別</div>;
  }

  return (
    <div>
      <div style={{ marginBottom: '20px' }}>
        <p><strong>狀態:</strong> {isListening ? '正在監聽...' : '已停止'}</p>
        <p><strong>结果:</strong> {result || '未檢測到语音'}</p>
        <p><strong>最终结果:</strong> {isFinal ? '是' : '否'}</p>
        {error && <p style={{ color: 'var(--ifm-color-danger)' }}><strong>错误:</strong> {error.error}</p>}
      </div>
      
      <div style={{ display: 'flex', gap: '10px' }}>
        <button onClick={start} disabled={isListening}>
          开始
        </button>
        <button onClick={stop} disabled={!isListening}>
          停止
        </button>
        <button onClick={() => toggle()}>
          切换
        </button>
      </div>
    </div>
  );
}
結果

狀態: 已停止

结果: 未檢測到语音

最终结果:

自定义配置选项

即時編輯器
function Demo() {
  const {
    isSupported,
    isListening,
    result,
    start,
    stop,
  } = useSpeechRecognition({
    continuous: true,
    interimResults: true,
    lang: 'zh-CN',
    maxAlternatives: 1,
  });

  if (!isSupported) {
    return <div>不支持語音識別</div>;
  }

  return (
    <div>
      <div style={{ marginBottom: '20px' }}>
        <p><strong>识别结果:</strong></p>
        <div style={{ 
          padding: '10px', 
          border: '1px solid var(--ifm-color-emphasis-200)', 
          borderRadius: '4px',
          minHeight: '60px',
          backgroundColor: 'var(--ifm-background-surface-color)',
          color: 'var(--ifm-color-content)'
        }}>
          {result || '开始说话...'}
        </div>
      </div>
      
      <div style={{ display: 'flex', gap: '10px' }}>
        <button 
          onClick={start} 
          disabled={isListening}
          style={{ 
            backgroundColor: isListening ? 'var(--ifm-color-emphasis-300)' : 'var(--ifm-color-primary)',
            color: 'var(--ifm-color-white)',
            border: 'none',
            padding: '8px 16px',
            borderRadius: '4px',
            cursor: 'pointer'
          }}
        >
          {isListening ? '正在監聽...' : '开始识别'}
        </button>
        <button 
          onClick={stop} 
          disabled={!isListening}
          style={{ 
            backgroundColor: !isListening ? 'var(--ifm-color-emphasis-300)' : 'var(--ifm-color-danger)',
            color: 'var(--ifm-color-white)',
            border: 'none',
            padding: '8px 16px',
            borderRadius: '4px',
            cursor: 'pointer'
          }}
        >
          停止
        </button>
      </div>
    </div>
  );
}
結果

识别结果:

开始说话...

多语言支持

即時編輯器
function Demo() {
  const [selectedLang, setSelectedLang] = React.useState('zh-CN');
  
  const {
    isSupported,
    isListening,
    result,
    start,
    stop,
  } = useSpeechRecognition({
    lang: selectedLang,
    continuous: true,
    interimResults: true,
  });

  const languages = [
    { code: 'zh-CN', name: '中文 (简体)' },
    { code: 'en-US', name: '英語 (美國)' },
    { code: 'ja-JP', name: '日本語' },
    { code: 'ko-KR', name: '한국어' },
    { code: 'es-ES', name: 'Español' },
    { code: 'fr-FR', name: 'Français' },
  ];

  if (!isSupported) {
    return <div>不支持語音識別</div>;
  }

  return (
    <div>
      <div style={{ marginBottom: '20px' }}>
        <label>
          <strong>语言:</strong>
          <select 
            value={selectedLang} 
            onChange={(e) => setSelectedLang(e.target.value)}
            style={{ 
              marginLeft: '10px', 
              padding: '4px',
              backgroundColor: 'var(--ifm-background-color)',
              color: 'var(--ifm-color-content)',
              border: '1px solid var(--ifm-color-emphasis-300)',
              borderRadius: '4px'
            }}
            disabled={isListening}
          >
            {languages.map(lang => (
              <option key={lang.code} value={lang.code}>
                {lang.name}
              </option>
            ))}
          </select>
        </label>
      </div>
      
      <div style={{ marginBottom: '20px' }}>
        <div style={{ 
          padding: '10px', 
          border: '1px solid var(--ifm-color-emphasis-200)', 
          borderRadius: '4px',
          minHeight: '80px',
          backgroundColor: 'var(--ifm-background-surface-color)',
          color: 'var(--ifm-color-content)'
        }}>
          {result || `开始用${languages.find(l => l.code === selectedLang)?.name}说话...`}
        </div>
      </div>
      
      <div style={{ display: 'flex', gap: '10px' }}>
        <button onClick={() => start({ lang: selectedLang })} disabled={isListening}>
          开始 ({selectedLang})
        </button>
        <button onClick={stop} disabled={!isListening}>
          停止
        </button>
      </div>
    </div>
  );
}
結果
开始用中文 (简体)说话...

动态语言和模式切换

即時編輯器
function DynamicOptionsDemo() {
  const {
    isSupported,
    isListening,
    result,
    start,
    stop,
  } = useSpeechRecognition();

  const quickOptions = [
    { 
      language: 'zh-CN', 
      name: '中文 (连续)', 
      flag: '🇨🇳', 
      continuous: true,
      color: 'var(--ifm-color-primary)'
    },
    { 
      language: 'zh-CN', 
      name: '中文 (单次)', 
      flag: '🇨🇳', 
      continuous: false,
      color: 'var(--ifm-color-secondary)'
    },
    { 
      language: 'en-US', 
      name: '英語 (連續)', 
      flag: '🇺🇸', 
      continuous: true,
      color: 'var(--ifm-color-success)'
    },
    { 
      language: 'en-US', 
      name: '英語 (單次)', 
      flag: '🇺🇸', 
      continuous: false,
      color: 'var(--ifm-color-warning)'
    },
  ];

  if (!isSupported) {
    return <div>不支持語音識別</div>;
  }

  return (
    <div>
      <div style={{ marginBottom: '20px' }}>
        <p><strong>快速开始不同语言和模式:</strong></p>
        <div style={{ 
          display: 'grid', 
          gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))',
          gap: '10px',
          marginBottom: '16px'
        }}>
          {quickOptions.map((option, index) => (
            <button
              key={index}
              onClick={() => start({ lang: option.language, continuous: option.continuous })}
              disabled={isListening}
              style={{
                padding: '12px 8px',
                border: '1px solid var(--ifm-color-emphasis-300)',
                backgroundColor: isListening ? 'var(--ifm-color-emphasis-300)' : option.color,
                color: 'var(--ifm-color-white)',
                borderRadius: '6px',
                cursor: isListening ? 'not-allowed' : 'pointer',
                fontSize: '13px',
                display: 'flex',
                flexDirection: 'column',
                alignItems: 'center',
                gap: '4px',
                textAlign: 'center'
              }}
            >
              <span style={{ fontSize: '18px' }}>{option.flag}</span>
              <span>{option.name}</span>
            </button>
          ))}
        </div>
        
        {isListening && (
          <button
            onClick={stop}
            style={{
              padding: '8px 16px',
              border: 'none',
              backgroundColor: 'var(--ifm-color-danger)',
              color: 'var(--ifm-color-white)',
              borderRadius: '4px',
              cursor: 'pointer',
              width: '100%'
            }}
          >
            停止監聽
          </button>
        )}
      </div>
      
      <div style={{ 
        padding: '16px', 
        border: '1px solid var(--ifm-color-emphasis-200)', 
        borderRadius: '6px',
        minHeight: '80px',
        backgroundColor: 'var(--ifm-background-surface-color)',
        color: 'var(--ifm-color-content)'
      }}>
        <strong>结果:</strong> {result || '点击任意按钮开始说话...'}
      </div>
      
      <div style={{ 
        marginTop: '12px',
        padding: '12px',
        backgroundColor: 'var(--ifm-background-surface-color)',
        borderRadius: '4px',
        fontSize: '14px',
        color: 'var(--ifm-color-content-secondary)'
      }}>
        <strong>提示:</strong> 连续模式会持续監聽直到您停止,
        而单次模式在檢測到一个短语后会自动停止。
      </div>
    </div>
  );
}
結果

快速开始不同语言和模式:

结果: 点击任意按钮开始说话...
提示: 连续模式会持续監聽直到您停止, 而单次模式在檢測到一个短语后会自动停止。

注意事项

  • 需要 HTTPS: 此 API 在生产环境中需要 HTTPS
  • 用户交互: 某些瀏覽器可能需要用户交互才能开始語音識別
  • 权限: 瀏覽器会在首次使用时请求麦克风权限
  • 隐私: 语音数据可能会发送到云服务进行處理
  • 准确性: 结果可能因麦克风质量、环境噪音和口音而有所不同

常见用例

  • 语音命令: 实现语音控制界面
  • 听写: 为表单添加语音转文本功能
  • 无障碍: 为行动不便的用户提供语音输入
  • 搜索: 启用语音搜索功能
  • 笔记: 創建语音备忘录应用程序

API

UseSpeechRecognitionOptions

參數名描述類型預設值
continuous控制是否为每次识别返回连续结果,或仅返回单个结果boolean-
interimResults控制是否应返回临时结果(true)或不返回(false)。临时结果是尚未最终确定的结果boolean-
lang语音识别的语言string-
maxAlternatives表示每个结果返回的最大备选项数量的数字number-

useSpeechRecognition

Returns

{ readonly isSupported: boolean; readonly isListening: boolean; readonly isFinal: boolean; readonly recognition: SpeechRecognition | undefined; readonly result: string; readonly error: SpeechRecognitionErrorEvent | undefined; readonly toggle: (value?: boolean | undefined, startOptions?: Partial<UseSpeechRecognitionOptions> | undefined) => void; readonly start: (startOptions?: Partial<UseSpeechRecognitionOptions> | undefined) => void; readonly stop: () => void; }: 包含以下元素的對象:

  • 是否支持語音識別。
  • 是否正在監聽。
  • 識別結果是否為最終結果。
  • SpeechRecognition 實例。
  • 識別結果文本。
  • 錯誤信息。
  • 切換監聽狀態的函數。
  • 開始監聽的函數。
  • 停止監聽的函數。

Arguments

參數名描述類型預設值
options可选的语音识别配置参数UseSpeechRecognitionOptions | undefined-
Squarespace
Squarespace makes your marketing, customer management, and checkout flow effortless—all on a single platform.
Get Started