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

React Web App在Safari及iPhone Chrome上无法捕获用户音频的问题

React Web App音频录制异常问题

我的React Web App前端音频录制捕获功能在Windows、Mac及Android的Chrome浏览器中可正常运行,但以下场景存在异常:

  • iPhone设备上的Chrome浏览器
  • Mac OS及iPhone设备上的Safari浏览器

相关核心代码如下:

const [mediaRecorder, setMediaRecorder] = useState(null);
const [hasStarted, setHasStarted] = useState(false);
const [chatStatus, setChatStatus] = useState(false);
const id = useRef(uuid());
const audioChunksRef = useRef([]);

const startRecording = async () => {
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      const mediaRecorder = new MediaRecorder(stream);

      mediaRecorder.ondataavailable = (event) => {
        audioChunksRef.current.push(event.data);
      };

      mediaRecorder.start();
      setMediaRecorder(mediaRecorder);
      setIsRecording(true);
    } catch (error) {
      console.error('Error starting recording:', error);
    }
};

const stopRecording = async () => {
    if (mediaRecorder) {
      mediaRecorder.onstop = async () => {
        const audioBlob = new Blob(audioChunksRef.current, {
          type: 'audio/mp3',
        });
        const formData = new FormData();
        formData.append('audio', audioBlob, 'audio_recording.mp3');
        formData.append('id', id.current);

        const response = await fetch(`${URL}/upload-audio`, {
          method: 'POST',
          body: formData,
          credentials: 'include',
        }).catch((error) => {
          console.error('Fetch error:', error);
          throw error;
        });
        const { lastMessage, chatStatus } = await response.json();
        console.log(lastMessage);
        setResponseText(lastMessage);
        setChatStatus(chatStatus);
        audioChunksRef.current = [];
        mediaRecorder.stream.getTracks().forEach((track) => track.stop());
        setMediaRecorder(null);
      };
      mediaRecorder.stop();
      setIsRecording(false);
    }
};

问题分析与修复方案

1. 格式兼容性问题

Safari(包括iPhone Chrome,其内核基于Safari)对audio/mp3支持有限,MediaRecorder默认生成的是audio/mp4(AAC编码)格式,强行指定mp3会导致录制失败或文件损坏。

修改Blob的MIME类型和文件名:

const audioBlob = new Blob(audioChunksRef.current, {
  type: 'audio/mp4',
});
formData.append('audio', audioBlob, 'audio_recording.mp4');

2. MediaRecorder初始化参数优化

Safari对MediaRecorder的构造参数要求更严格,需显式指定兼容的编码格式:

const mediaRecorder = new MediaRecorder(stream, {
  mimeType: 'audio/mp4;codecs=mp4a.40.2'
});

3. onstop事件绑定时机调整

Safari要求onstop事件必须在start()之前绑定,否则可能无法触发。重构startRecording函数,提前绑定事件:

const startRecording = async () => {
  try {
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
    const mediaRecorder = new MediaRecorder(stream, {
      mimeType: 'audio/mp4;codecs=mp4a.40.2'
    });

    // 先绑定onstop事件,再启动录制
    mediaRecorder.onstop = async () => {
      const audioBlob = new Blob(audioChunksRef.current, {
        type: 'audio/mp4',
      });
      const formData = new FormData();
      formData.append('audio', audioBlob, 'audio_recording.mp4');
      formData.append('id', id.current);

      try {
        const response = await fetch(`${URL}/upload-audio`, {
          method: 'POST',
          body: formData,
          credentials: 'include',
        });
        const { lastMessage, chatStatus } = await response.json();
        console.log(lastMessage);
        setResponseText(lastMessage);
        setChatStatus(chatStatus);
      } catch (error) {
        console.error('Fetch error:', error);
      } finally {
        audioChunksRef.current = [];
        stream.getTracks().forEach(track => track.stop());
        setMediaRecorder(null);
      }
    };

    mediaRecorder.ondataavailable = (event) => {
      audioChunksRef.current.push(event.data);
    };

    mediaRecorder.start();
    setMediaRecorder(mediaRecorder);
    setIsRecording(true);
  } catch (error) {
    console.error('Error starting recording:', error);
  }
};

4. 权限触发要求

Safari和iPhone Chrome要求媒体权限请求必须由用户主动交互(如点击按钮)触发,确保startRecording直接绑定到按钮的onClick事件,避免异步延迟或间接调用。

5. 测试验证

修改后在目标浏览器测试:

  • 确认录制能正常启动
  • 停止后生成有效的音频文件
  • 服务器能正确接收并解析音频

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 00:56:26