将blob转换为WAV文件,而不会丢失数据或压缩 [英] Convert blob to WAV file without loosing data or compressing

查看:321
本文介绍了将blob转换为WAV文件,而不会丢失数据或压缩的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am working on recording speeches and converting them to downloadable WAV files. I am using Angular6 and MediaRecorder. Firstly I obtain the blob and from the blob, I get the .wav file. The problem is that the WAV file (which can be played and sounds good) loss much of its properties during the process and is not a valid WAV. It keeps being a WebM file. For further processing, I need really valid and high-quality WAV files. In the end, I get files of ~20KB, instead of bigger files of ~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设置如下所示:

And the MediaRecorder setup in typings.d.ts file looks like this:

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()函数以在转换过程中保持录制质量.如果您可以帮助我,我将非常感谢.

I don't know how can change the blobToFile() function in order to preserve the recording quality during conversion. If you can help me with this, I would appreciate very much.

推荐答案

正如我在文件的元数据中看到的那样,您

As I can see in the metadatas of the file you've linked in the comment. You use a codec (here Opus) that compresses the file.

我看到两种解决方案:

  • 如果可以的话,降低编解码器的压缩率.
  • 使用具有未压缩配置的 WAV 容器(例如PCM)
  • Reduce the compressing ratio of the codec if you can.
  • Use WAV container with an uncompressed configuration (for example PCM)

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

as you described me the problem in the chat I think it's more of the second solution. I don't use mediarecorder myself but I've found this method to check if a mime type works with it.

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

然后,我建议您在创建 Blob

then you I suggest you change the mime type when creating the Blob to

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

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

这篇关于将blob转换为WAV文件,而不会丢失数据或压缩的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆