无损转换Blob为WAV文件,不压缩数据

8
我正在录制演讲并将其转换为可下载的WAV文件。我正在使用Angular6和MediaRecorder。首先,我获取blob,然后从blob中获取.wav文件。问题在于,WAV文件(可以播放且听起来不错)在过程中失去了很多属性,因此不是有效的WAV文件。它仍然是一个WebM文件。为了进一步处理,我需要真正有效且高质量的WAV文件。最终,我得到了大约20KB的文件,而不是大约300KB的更大文件。
我的代码如下:
//convert Blob to File. Pass the blob and the file title as arguments
var blobToFile = (theBlob: Blob, fileName:string): File => {
  var b: any = theBlob;
  //Add properties to the blob
  b.lastModifiedDate = new Date();
  b.name = fileName;
  return <File>theBlob;
}

var browser = <any>navigator;  
var headers = new Headers();  
var audioCtx = new AudioContext();
var chunks =[];
var constraints = { audio: true, video: false }; 

var promisifiedOldGUM = function(constraints, successCallback, errorCallback) {
  var getUserMedia = (browser.getUserMedia || browser.webkitGetUserMedia || browser.mozGetUserMedia || browser.msGetUserMedia);

  // Some browsers just don't implement it - return a rejected promise with an error to keep a consistent interface
  if(!getUserMedia) {
    return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
  }

  // Otherwise, wrap the call to the old navigator.getUserMedia with a Promise
  return new Promise(function(successCallback, errorCallback) {
    getUserMedia.call(browser, constraints, successCallback, errorCallback);
  });

}
if (browser.mediaDevices.getUserMedia) {
  browser.mediaDevices.getUserMedia(constraints).then((stream) => { 
  this.mediaRecorder = new MediaRecorder(stream);        

this.mediaRecorder.onstop  = function(){
        var last_bit= chunks[chunks.length-1];
        var blob = new Blob([last_bit], { 'type' : 'audio/wav' });
        var audioURL = window.URL.createObjectURL(blob);
        //convert Blob to file 
        var file = blobToFile(blob, "my-recording.wav"); 

        var link = document.createElement("a");
        link.href = audioURL;
        link.download = 'audio_recording_' + new Date().getTime() + '.wav';
        link.innerHTML = "download file";
        document.body.appendChild(link);  
};     

typings.d.ts文件中,MediaRecorder的设置如下:

declare class MediaRecorder extends EventTarget {

// readonly mimeType: string;
readonly MimeType: 'audio/x-wav';  // 'audio/vnd.wav';
readonly state: 'inactive' | 'recording' | 'paused';
readonly stream: MediaStream;
ignoreMutedMedia: boolean;
videoBitsPerSecond: number;
audioBitsPerSecond: 16000//number;

ondataavailable: (event : MediaRecorderDataAvailableEvent) => void;
onerror: (event: MediaRecorderErrorEvent) => void;
onpause: () => void;
onresume: () => void;
onstart: () => void;
onstop: () => void;

constructor(stream: MediaStream);

start();

stop();

resume();

pause();

isTypeSupported(type: string): boolean;

requestData();


addEventListener<K extends keyof MediaRecorderEventMap>(type: K, listener: (this: MediaStream, ev: MediaRecorderEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;

addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;

removeEventListener<K extends keyof MediaRecorderEventMap>(type: K, listener: (this: MediaStream, ev: MediaRecorderEventMap[K]) => any, options?: boolean | EventListenerOptions): void;

removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;

} 

我不知道如何更改 blobToFile() 函数以在转换过程中保留录音质量。如果您能帮助我解决这个问题,我将非常感激。


你设置了适当的位/采样频率吗? - JSmith
1
不确定质量如何,但您这里可能没有WAV文件。我所知道的MediaRecorder的任何实现都不会记录为WAV格式,如果他们这样做了,那么您在此处设置它之前就不会有它,而是在启动录音机之前。因此,您拥有的是opus oga / webm-audio文件。 - Kaiido
我编辑了我的帖子,以展示我在哪里声明了 MediaRecorder。实际上,我得到的文件是 webm 格式的。 - Emanuela Colta
1个回答

8
根据您在评论中提供的链接中的元数据,我了解到您使用了一种编解码器(此处为Opus)来压缩文件。

我的建议有两个:

  • 如果可能,请减少编解码器的压缩比率。
  • 使用未压缩配置(例如PCM)的WAV容器。

根据您在聊天中描述的问题,我认为第二个解决方案更适合您。虽然我自己没有使用mediarecorder,但我找到了这种检查mime类型是否与其兼容的方法。

MediaRecorder.isTypeSupported("audio/wav;codecs=MS_PCM")

如果您正在创建 Blob,我建议您更改 MIME 类型为

new Blob(chunks, { 'type' : 'audio/wav; codecs=MS_PCM' });

或者

new Blob(chunks, { 'type' : 'audio/wav; codecs=0' });

实际上,这里提供的详细分析 https://www.get-metadata.com/result/10525caf-9757-4b4d-910e-abf60b62655b 表明音频每个采样位数为32,在流中每个采样位数为0。我认为问题就出在这里。 - Emanuela Colta
是的,我做了。它们听起来很好。在这里听:https://drive.google.com/file/d/1zMGkgkA5EW7iCYSL7Kv7mePnEpMokJ0N/view?usp=sharing - Emanuela Colta
我没有初始音频文件。我只是录制我的声音。根据录音,我得到一个 blob,然后根据这个 blob 生成音频文件。 - Emanuela Colta
还没有。我正在考虑从MediaRecorder切换到Recorder.js - Emanuela Colta
我现在正在打开它。 - Emanuela Colta
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接