将blob转换为WAV文件,而不会丢失数据或压缩

时间:2018-08-25 21:22:29

标签: javascript typescript file blob wav

我正在录制语音并将其转换为可下载的WAV文件。我正在使用Angular6和MediaRecorder。首先,我获得blob,然后从blob中获得.wav文件。问题在于,WAV文件(可以播放且听起来不错)在此过程中失去了很多属性,因此不是有效的WAV。它一直是WebM文件。为了进行进一步处理,我需要真正有效和高质量的WAV文件。最后,我得到的文件约为20KB,而不是较大的文件为300KB。

我的代码如下:

*argv[i]

//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); }; 文件中的MediaRecorder设置如下所示:

typings.d.ts

我不知道如何更改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; } 函数以在转换期间保持录制质量。如果您可以帮助我,我将非常感谢。

2 个答案:

答案 0 :(得分:2)

正如我在评论中linked中所看到的文件的元数据中所看到的那样。 您使用压缩文件的编解码器(此处为Opus)。

我看到两种解决方案:

  • 如果可以,请降低编解码器的压缩率。
  • WAV容器用于未压缩的配置(例如PCM)

正如您在聊天中向我描述的问题一样,我认为这更多是第二种解决方案。 我自己没有使用mediarecorder,但是我发现这种方法可以检查mime类型是否适用。

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

然后,我建议您在创建Blob

时更改哑剧类型。
new Blob(chunks, { 'type' : 'audio/wav; codecs=MS_PCM' });

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

答案 1 :(得分:0)

您可以通过创建新的mediaRecorderwav实例的结果转换为Blob。简单但不那么明显,并且仅适用于Chrome(我在v77.0.3865.90上进行了测试)。

即使MediaRecorder.isTypeSupported('audio/wav')在浏览器控制台上返回false,您也可以执行以下操作:

    navigator.mediaDevices.getUserMedia({ audio: true })
      .then(stream => {
          const mediaRecorder = new MediaRecorder(stream);
            this.mediaRecorder.ondataavailable = (e) => {
                const blobDataInWebaFormat = e.data; // .weba = webaudio; subset of webm
                const blobDataInWavFormat: Blob = new Blob([blobDataInWebaFormat], { type : 'audio/wav; codecs=0' });
                const dataUrl = URL.createObjectURL(blobDataInWavFormat);
                console.log(dataUrl); // There you can listen to your recording in a wav format
            });
            };
      });

希望对某人有用,甚至一年后!