在React中如何读取.wav音频文件的时间序列数据与采样率
实现方案
方案1:原生Web Audio API实现(无第三方依赖)
不需要引入额外库,直接用浏览器内置API即可实现和librosa.load对齐的输出,具体逻辑和React侧的示例代码如下:
- 第一步:通过上传事件拿到.wav格式的File对象,读取为ArrayBuffer
- 第二步:用AudioContext解码ArrayBuffer得到AudioBuffer实例,该实例自带采样率属性和各通道的原始音频数据
- 第三步:如果需要对齐librosa默认的单通道输出逻辑,可将多通道音频的采样点取平均值合并为单通道,最终输出的是归一化到
[-1, 1]区间的Float32数组,和librosa返回格式完全一致
import { useState } from 'react'; function WavUploader() { const [audioCtx, setAudioCtx] = useState(null); const handleUpload = async (e) => { const file = e.target.files[0]; if (!file || file.type !== 'audio/wav') return; // AudioContext必须在用户交互事件中初始化,否则会被浏览器安全策略拦截 const ctx = audioCtx || new (window.AudioContext || window.webkitAudioContext)(); if (!audioCtx) setAudioCtx(ctx); // 读取并解码音频文件 const arrBuffer = await file.arrayBuffer(); const audioBuffer = await ctx.decodeAudioData(arrBuffer); // 提取采样率,和librosa返回的samplingrate完全对应 const samplingrate = audioBuffer.sampleRate; // 提取时间序列数据,对齐librosa默认单通道输出 let signaldata; const channelNum = audioBuffer.numberOfChannels; if (channelNum === 1) { signaldata = audioBuffer.getChannelData(0); } else { // 多通道合并为单通道,对所有通道同位置采样点取平均值 const channels = Array.from({length: channelNum}, (_, i) => audioBuffer.getChannelData(i)); const frameLen = audioBuffer.length; signaldata = new Float32Array(frameLen); for (let i = 0; i < frameLen; i++) { let sum = 0; for (let ch = 0; ch < channelNum; ch++) { sum += channels[ch][i]; } signaldata[i] = sum / channelNum; } } // 此处拿到的signaldata、samplingrate和librosa.load返回值完全对齐 console.log('采样率:', samplingrate); console.log('时间序列长度:', signaldata.length); }; return <input type="file" accept="audio/wav" onChange={handleUpload} />; }
方案2:第三方库实现(适配更多librosa能力)
如果后续还需要用到STFT、MFCC等librosa常用的音频处理能力,可以使用librosa-js库,API和Python版librosa几乎完全对齐,调用方式非常简洁:
import * as librosa from 'librosa-js'; // 拿到上传的wav文件对象后直接调用load方法即可 const { signal, sampleRate } = await librosa.load(file);
该库底层也是基于Web Audio API封装,和原生实现的核心逻辑一致,额外做了多场景的边界兼容处理。
内容的提问来源于stack exchange,提问作者Aditya Dawadikar
相关产品推荐
相关产品推荐

