12

Я занимаюсь заменой RecordRTC встроенным MediaRecorder для записи аудио в Chrome. Затем записанный звук воспроизводится в программе со звуком api. У меня возникла проблема с работой свойства audio.duration. В нем говорится:Как добавить предопределенную длину в аудиозапись, записанную в MediaRecorder в Chrome?

Если видео (аудио) передано и не имеет предопределенной длины, возвращается «Inf» (Infinity).

С RecordRTC мне пришлось использовать ffmpeg_asm.js для преобразования звука из wav в ogg. Моя догадка где-то в процессе RecordRTC устанавливает предопределенную длину аудио. Есть ли способ установить предопределенную длину с помощью MediaRecorder?

+1

У меня точно такая же проблема. Вы нашли решение? –

+0

Что значит предопределенная длина? У вас может быть только таймер, который запускается, когда начинается запись, а затем останавливается в соответствующее время? –

+0

@Tom Chen, когда я проверяю записанные аудиофайлы после записи (используя командную строку '$ ffmpeg -i test.webm', я вижу, что определение задано как N/A. Вы нашли способ установить длину? –

ответ

17

Это chrome bug.

FF делает разоблачить продолжительность записанных носителей информации, и если вы установите currentTime из записанных носителей информации более, чем его фактическая duration, то свойство доступно в хроме ...

var recorder, 
 
    chunks = [], 
 
    ctx = new AudioContext(), 
 
    aud = document.getElementById('aud'); 
 

 
function exportAudio() { 
 
    var blob = new Blob(chunks, { 
 
    type: 'audio/ogg' 
 
    }); 
 
    aud.src = URL.createObjectURL(new Blob(chunks)); 
 

 
    aud.onloadedmetadata = function() { 
 
    // it should already be available here 
 
    log.textContent = ' duration: ' + aud.duration; 
 
    // handle chrome's bug 
 
    if(aud.duration === Infinity){ 
 
     // set it to bigger than the actual duration 
 
     aud.currentTime = 1e101; 
 
     aud.ontimeupdate = function(){ 
 
     \t this.ontimeupdate =()=>{return;} 
 
\t  log.textContent += ' after workaround: ' + aud.duration; 
 
    \t aud.currentTime = 0; 
 
    \t } 
 
     } 
 
    } 
 
} 
 

 
function getData() { 
 
    var request = new XMLHttpRequest(); 
 
    request.open('GET', 'https://upload.wikimedia.org/wikipedia/commons/4/4b/011229beowulf_grendel.ogg', true); 
 
    request.responseType = 'arraybuffer'; 
 
    request.onload = decodeAudio; 
 
    request.send(); 
 
} 
 

 

 
function decodeAudio(evt) { 
 
    var audioData = this.response; 
 
    ctx.decodeAudioData(audioData, startRecording); 
 
} 
 

 
function startRecording(buffer) { 
 

 
    var source = ctx.createBufferSource(); 
 
    source.buffer = buffer; 
 
    var dest = ctx.createMediaStreamDestination(); 
 
    source.connect(dest); 
 

 
    recorder = new MediaRecorder(dest.stream); 
 
    recorder.ondataavailable = saveChunks; 
 
    recorder.onstop = exportAudio; 
 
    source.start(0); 
 
    recorder.start(); 
 
    log.innerHTML = 'recording...' 
 
    // record only 5 seconds 
 
    setTimeout(function() { 
 
    recorder.stop(); 
 
    }, 5000); 
 
} 
 

 
function saveChunks(evt) { 
 
    if (evt.data.size > 0) { 
 
    chunks.push(evt.data); 
 
    } 
 

 
} 
 

 

 

 
getData();
<audio id="aud" controls></audio><span id="log"></span>

так что совет здесь должен был бы звездой bug report так команда, что хром занимает некоторое время, чтобы исправить это, даже если этот способ может сделать трюк ...

+0

это ошибка: https://crbug.com/642012. Я предлагаю, чтобы мы «запустили» ее, чтобы разработчики могли расставить приоритеты соответственно. – miguelao

+0

@miguelao, yep Я зарегистрировал [этот] (https://bugs.chromium.org/) p/chromium/issues/detail? id = 656426), который был объединен с тем, что вы упомянули. – Kaiido

+0

Вау, это действительно сработало. –

0

Благодаря @Kaiido для определения ошибки и предложения рабочего исправления.

Я подготовил пакет npm под названием get-blob-duration, который вы можете установить, чтобы получить прекрасную функцию, предназначенную для выполнения грязной работы.

Использование выглядит следующим образом:

// Returns Promise<Number> 
getBlobDuration(blob).then(function(duration) { 
    console.log(duration + ' seconds'); 
}); 

Или ECMAScript 6:

// yada yada async 
const duration = await getBlobDuration(blob) 
console.log(duration + ' seconds')