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

如何在ReactJS中使用JavaScript将BlobUrl转换为MP3?

在React中将M4A格式BlobUrl转换为MP3格式

浏览器原生不支持将M4A编码为MP3,需要借助第三方音频处理库实现,下面提供两种常用方案:

方案一:使用lamejs(轻量,仅支持MP3编码)

lamejs是轻量级MP3编码库,适合仅需转码MP3的场景。

步骤1:安装依赖

npm install lamejs
# 或
yarn add lamejs

步骤2:编写转换函数

先将BlobUrl转换为AudioBuffer,再编码为MP3 Blob:

import lamejs from 'lamejs';

// 将BlobUrl转换为MP3 Blob的函数
const convertM4AToMP3 = async (blobUrl: string): Promise<Blob> => {
  // 1. 从BlobUrl获取M4A Blob
  const response = await fetch(blobUrl);
  const m4aBlob = await response.blob();
  
  // 2. 解码Blob为AudioBuffer
  const arrayBuffer = await m4aBlob.arrayBuffer();
  const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)();
  const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
  
  // 3. 提取PCM数据并转换格式
  const channelData = audioBuffer.getChannelData(0); // 取单声道,双声道需处理两个通道
  const sampleRate = audioBuffer.sampleRate;
  const pcmData = new Int16Array(channelData.length);
  
  for (let i = 0; i < channelData.length; i++) {
    const normalizedValue = Math.max(-1, Math.min(1, channelData[i]));
    pcmData[i] = normalizedValue < 0 ? normalizedValue * 0x8000 : normalizedValue * 0x7FFF;
  }
  
  // 4. 编码为MP3
  const mp3Encoder = new lamejs.Mp3Encoder(1, sampleRate, 128); // 单声道、采样率、比特率
  const mp3Data = mp3Encoder.encodeBuffer(pcmData);
  const finalMp3Data = mp3Encoder.flush();
  
  // 5. 生成MP3 Blob
  return new Blob([mp3Data, finalMp3Data], { type: 'audio/mp3' });
};

步骤3:结合现有代码使用

修改上传逻辑,先转码再上传:

const audioUpload = async (user: IUser) => {
  if (!mediaBlobUrl) return;
  
  try {
    const mp3Blob = await convertM4AToMP3(mediaBlobUrl);
    const mp3File = new File([mp3Blob], `recorded-audio-${Date.now()}.mp3`, { type: 'audio/mp3' });
    const uploadResult = await uploadImage(mp3File, user);
    
    if (uploadResult) {
      // 这里可添加上传成功后的逻辑,比如保存文件引用到数据库
      // saveMedia(uploadResult.fbReference, user);
    }
  } catch (error) {
    console.error('转码或上传失败:', error);
  }
};

方案二:使用ffmpeg.wasm(功能全面,支持多格式转换)

如果需要复杂音频处理(如调整参数、多格式兼容),可使用ffmpeg.wasm,但体积较大,需考虑加载性能。

步骤1:安装依赖

npm install @ffmpeg/ffmpeg @ffmpeg/core
# 或
yarn add @ffmpeg/ffmpeg @ffmpeg/core

步骤2:编写转换函数

import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg';

const ffmpeg = createFFmpeg({ log: false });

const convertM4AToMP3WithFFmpeg = async (blobUrl: string): Promise<Blob> => {
  if (!ffmpeg.isLoaded()) {
    await ffmpeg.load();
  }
  
  // 1. 读取M4A Blob
  const m4aBlob = await fetch(blobUrl).then(res => res.blob());
  
  // 2. 写入ffmpeg虚拟文件系统
  ffmpeg.FS('writeFile', 'input.m4a', await fetchFile(m4aBlob));
  
  // 3. 执行转码命令
  await ffmpeg.run('-i', 'input.m4a', '-codec:a', 'libmp3lame', '-q:a', '2', 'output.mp3');
  
  // 4. 读取转码后的MP3文件
  const mp3Data = ffmpeg.FS('readFile', 'output.mp3');
  const mp3Blob = new Blob([mp3Data.buffer], { type: 'audio/mp3' });
  
  // 清理虚拟文件
  ffmpeg.FS('unlink', 'input.m4a');
  ffmpeg.FS('unlink', 'output.mp3');
  
  return mp3Blob;
};

步骤3:结合现有代码使用

const audioUpload = async (user: IUser) => {
  if (!mediaBlobUrl) return;
  
  try {
    const mp3Blob = await convertM4AToMP3WithFFmpeg(mediaBlobUrl);
    const mp3File = new File([mp3Blob], `recorded-audio-${Date.now()}.mp3`, { type: 'audio/mp3' });
    await uploadImage(mp3File, user);
    // 后续逻辑...
  } catch (error) {
    console.error('转码失败:', error);
  }
};

注意事项

  • 浏览器AudioContext需在用户交互(如点击按钮)中激活,否则会报错,确保转换函数在用户触发的事件内调用。
  • lamejs仅支持单/双声道PCM编码,多声道需额外处理。
  • ffmpeg.wasm首次加载会下载核心库,建议添加加载状态提示优化体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 20:01:06