Конвертировать BLOB-файлы в файл WAV без потери данных или сжатия - PullRequest
0 голосов
/ 26 августа 2018

Я работаю над записью речей и преобразованием их в загружаемые файлы WAV.Я использую Angular6 и MediaRecorder.Сначала я получаю BLOB-объект, а из него я получаю WAV-файл.Проблема заключается в том, что файл WAV (который можно воспроизвести и звучит хорошо) в процессе обработки теряет большую часть своих свойств и не является допустимым WAV.Это продолжает быть файлом WebM.Для дальнейшей обработки мне нужны действительно качественные WAV-файлы.В конце я получаю файлы размером ~ 20 КБ, вместо больших файлов размером ~ 300 КБ.

Мой код выглядит следующим образом:

//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;

} 

Я не знаю, как можно изменить функцию blobToFile(), чтобы сохранить качество записи во время преобразования.Если бы вы могли помочь мне с этим, я был бы очень признателен.

1 Ответ

0 голосов
/ 26 августа 2018

Как я вижу в метаданных файла, который вы связали в комментарии.Вы используете кодек (здесь Opus), который сжимает файл.

Я вижу два решения:

  • Уменьшите коэффициент сжатия кодека, если можете.
  • Используйте контейнер WAV с несжатой конфигурацией (например, PCM)

, поскольку вы описали мне проблему в чате, я думаю, что это скорее второе решение.Я сам не использую медиа-рекордер, но я нашел этот метод, чтобы проверить, работает ли с ним тип mime.

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

тогда я предлагаю вам изменить тип mime при создании Blob на

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

или

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