useMicrophone

用于采集麦克风音频的 React hook

useMicrophonegetUserMediaWeb Audio APIMediaRecorder 封装进同一个 hook。它负责打开和关闭麦克风音频流,暴露一个经过节流的音量 level(0–1,RMS),适合用于音量条,并可将当前音频流录制为 Blob,同时由 hook 管理对象 URL 的生命周期。

实时音频流控制(start / stop)与录音控制(startRecording / stopRecording / pauseRecording / resumeRecording)相互独立:你可以只显示音量条而不录音,也可以在不关闭麦克风的情况下开始或停止录音。

使用场景

  • 构建语音备忘录或听写界面,让用户在录音前和录音中都能看到实时输入电平
  • 添加「请说话」提示或麦克风校准界面 —— 需要音量条但不需要录音
  • 将短音频片段录制为 Blob 用于上传或本地播放

注意事项

  • SSR 安全:在服务端渲染期间返回 isSupported: false 和空操作的控制函数。服务端不会访问 navigator.mediaDevices
  • start()startRecording():录音采集的是已打开的音频流。请先调用 start();在没有活动流时调用 startRecording() 会设置 error 而不会开始录音。
  • 需要 HTTPS:在生产环境中,麦克风需要安全上下文(HTTPS)。浏览器会在首次 start() 时请求权限。
  • 对象 URL 生命周期audioUrl 由 hook 创建和释放 —— 它会在下一次录音时被替换,并在卸载时被释放,因此使用方无需自行调用 URL.revokeObjectURL
  • Mime 类型:录音格式会从浏览器支持的格式中自动选择(audio/webm;codecs=opusaudio/webmaudio/mp4audio/ogg;codecs=opus)。最终解析出的值通过 mimeType 暴露。
  • 相关 hooks:使用 useMediaDevices 枚举麦克风并传入 deviceId,或使用 useSpeechRecognition 进行语音转文字。

基本用法

Live Editor
function Demo() {
  const {
    isSupported,
    isActive,
    level,
    isRecording,
    isPaused,
    audioUrl,
    mimeType,
    error,
    start,
    stop,
    startRecording,
    stopRecording,
    pauseRecording,
    resumeRecording,
  } = useMicrophone();

  if (!isSupported) {
    return <div>此浏览器不支持麦克风</div>;
  }

  const levelPercent = Math.round(level * 100);

  return (
    <div>
      <div style={{ marginBottom: '16px' }}>
        <p>
          <strong>麦克风:</strong> {isActive ? '已打开' : '已关闭'}
          {' · '}
          <strong>录音:</strong>{' '}
          {isRecording ? (isPaused ? '已暂停' : '录音中...') : '空闲'}
        </p>

        <div
          style={{
            height: '16px',
            width: '100%',
            borderRadius: '4px',
            backgroundColor: 'var(--ifm-color-emphasis-200)',
            overflow: 'hidden',
          }}
        >
          <div
            style={{
              height: '100%',
              width: `${levelPercent}%`,
              backgroundColor:
                levelPercent > 70
                  ? 'var(--ifm-color-danger)'
                  : 'var(--ifm-color-success)',
              transition: 'width 80ms linear',
            }}
          />
        </div>
        <p style={{ fontSize: '13px', color: 'var(--ifm-color-content-secondary)' }}>
          输入电平: {levelPercent}%
        </p>
      </div>

      <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap', marginBottom: '12px' }}>
        <button onClick={() => start()} disabled={isActive}>
          打开麦克风
        </button>
        <button onClick={() => stop()} disabled={!isActive}>
          关闭麦克风
        </button>
        <button onClick={() => startRecording()} disabled={!isActive || isRecording}>
          录音
        </button>
        <button onClick={() => stopRecording()} disabled={!isRecording}>
          停止录音
        </button>
        <button onClick={() => pauseRecording()} disabled={!isRecording || isPaused}>
          暂停
        </button>
        <button onClick={() => resumeRecording()} disabled={!isPaused}>
          继续
        </button>
      </div>

      {audioUrl && (
        <div style={{ marginBottom: '12px' }}>
          <p style={{ fontSize: '13px', color: 'var(--ifm-color-content-secondary)' }}>
            录制的片段({mimeType || '默认格式'}):
          </p>
          <audio src={audioUrl} controls />
        </div>
      )}

      {error && (
        <p style={{ color: 'var(--ifm-color-danger)' }}>
          <strong>错误:</strong> {error.message}
        </p>
      )}
    </div>
  );
}
Result

常见用例

  • 语音备忘录:打开麦克风让用户看到实时电平,然后录制为 Blob 并回放或上传。
  • 音量监测:用 level 驱动音量条或波形,而无需录制任何内容。
  • 麦克风校准:让用户在开始前确认采集到的是正确的设备。

API

UseMicrophoneOptions

参数名描述类型默认值
deviceId指定要使用的麦克风设备 ID;激活状态下变化会自动重新获取流string-
constraints与默认音频约束合并的额外 MediaTrackConstraints;deviceId 优先MediaTrackConstraints-
levelInterval音量级别状态更新的节流间隔(毫秒)number100
mimeTypeMediaRecorder 的首选 mime 类型;不受支持时自动回退string-
autoStart挂载时自动打开麦克风booleanfalse

useMicrophone

Returns

UseMicrophoneReturn: 包含麦克风流、音量级别、录音控制等的对象

Arguments

参数名描述类型默认值
options可选配置UseMicrophoneOptions | undefined-