因此,我编写了一个小型的js库,它将从用户的麦克风/音频输入设备中记录音频样本,并将它们转换为wav文件。由于现代浏览器不支持这一点,所以我使用了WebAudio API来实现这一点。
Recording.js:
var blobArray = [];
var audioContext;
var Float32BitSampleArray = [];
var record = async function() {
audioContext = new AudioContext(),
microphone = await navigator.mediaDevices.getUserMedia( {
audio: true
} );
var inputNode = audioContext.createMediaStreamSource( microphone );
await audioContext.audioWorklet.addModule( 'wavprocessor.js' );
var wavProcessingNode = new AudioWorkletNode( audioContext, 'wav-processor' );
inputNode.connect( wavProcessingNode );
wavProcessingNode.connect( audioContext.destination );
wavProcessingNode.port.onmessage = (e) => {
Float32BitSampleArray = Float32BitSampleArray.concat( e.data );
}
}
function buildWav() {
buildWavSpecification();
}
function appendData( index, view ) {
for( var i = 0; i < Float32BitSampleArray.length; i++ ) {
var s = Math.max( -1, Math.min( 1, Float32BitSampleArray[ i ] ) );
s = s < 0 ? s * 0x8000 : s * 0x7FFF;
view.setUint16( index + 2 * i, s, true );
}
}
function buildWavSpecification() {
var dataTypeSize = 16, // 16 bit PCM data
totalDataSize = ( dataTypeSize / 8 ) * Float32BitSampleArray.length,
sizeOfFileDescriptor = totalDataSize + 36,
numberOfChannels = 1,
sampleRate = 44100,
bytesPerSample = numberOfChannels * dataTypeSize / 8,
blockAlign = numberOfChannels * bytesPerSample,
bitsPerSample = bytesPerSample * 8,
byteRate = sampleRate * bytesPerSample,
buffer = new ArrayBuffer( 44 + totalDataSize ),
view = new DataView( buffer ),
format = 1;
function writeStringIntoBuffer( index, str ) {
for( var i = 0; i < str.length; i++ ) {
view.setUint8( index + i, str.charCodeAt( i ) );
}
}
function write32BitInt( index, val ) {
view.setUint32( index, val, true );
}
function write16BitInt( index, val ) {
view.setUint16( index, val, true );
}
writeStringIntoBuffer( 0, 'RIFF' );
write32BitInt( 4, sizeOfFileDescriptor );
writeStringIntoBuffer( 8, 'WAVE' );
writeStringIntoBuffer( 12, 'fmt ' );
write32BitInt( 16, 16 );
write16BitInt( 20, format );
write16BitInt( 22, numberOfChannels );
write32BitInt( 24, sampleRate );
write32BitInt( 28, byteRate );
write16BitInt( 32, blockAlign );
write16BitInt( 34, bitsPerSample );
writeStringIntoBuffer( 36, 'data' );
write32BitInt( 40, totalDataSize );
appendData( 44, view );
var blob = new Blob([ view ], { type: 'audio/wav' });
return blob;
}
var stop = function() {
// stop the recording
var blob = buildWav();
}波形处理器AudioWorkletProcessor (wavprocessor.js):
class WavProcessor extends AudioWorkletProcessor {
constructor() {
super();
this.buffer = [];
}
process( inputs, outputs, parameters ) {
this.pushData( inputs[ 0 ][ 0 ] );
this.port.postMessage( this.buffer );
this.buffer = [];
return true;
}
pushData( samples ) {
for( var i = 0; i < samples.length; i++ ) {
this.buffer.push( samples[ i ] );
}
}
}
registerProcessor('wav-processor', WavProcessor );现在这很好,但是我的问题是我是应该在AudioWorkletProcessor中构建wav文件,还是应该跨一个单独的工作线程来构建wav文件。现在,该文件正在浏览器的主线程中构建,在10秒内它将发送大约700 K的音频样本,因此Float32BitSampleArray内部有700 K的音频样本。我是从表演的角度来要求的。
用于构建wav文件的Stackoverflow文章:链接
发布于 2022-09-29 21:08:59
我想说的是,这取决于你如何定义性能。
如果您想要尽快完成它,那么在音频线程上执行它可能是最快的方法。
但是它可能会干扰在同一线程上计划的任何其他音频处理,并可能导致可听到的故障。为了避免这种情况,最好在其他地方进行后处理(也就是将PCM数据转换为WAV文件)。由于在主线程上执行时,它可能会干扰任何用户交互,所以我认为在Web工作人员中这样做是个好主意。
在过去,我不得不开发一种类似的方法,并采用了第二种方法。结果可作为npm软件包使用。也许这对你有用。可扩展媒体记录器
https://stackoverflow.com/questions/73891141
复制相似问题