2016-07-18 105 views
12

Sono in procinto di sostituire RecordRTC con il MediaRecorder integrato per registrare l'audio in Chrome. L'audio registrato viene quindi riprodotto nel programma con audio api. Sto avendo problemi a far funzionare la proprietà audio.duration. DiceCome posso aggiungere una lunghezza predefinita all'audio registrato da MediaRecorder in Chrome?

Se il video (audio) è in streaming e non ha una lunghezza predefinita, viene restituito "Inf" (Infinito).

Con RecordRTC, ho dovuto utilizzare ffmpeg_asm.js per convertire l'audio da wav a ogg. La mia ipotesi è da qualche parte nel processo RecordRTC imposta la lunghezza audio predefinita. C'è un modo per impostare la lunghezza predefinita usando MediaRecorder?

+1

Sto avendo lo stesso identico problema. Hai trovato una soluzione? –

+0

Cosa intendi per lunghezza predefinita? Puoi semplicemente avere un timer che viene avviato all'avvio della registrazione e interromperlo al momento opportuno? –

+0

@Tom Chen quando controllo i miei file audio registrati dopo una registrazione (usando la riga di comando '$ ffmpeg -i test.webm' Vedo che la definizione è impostata su N/A. Hai trovato un modo per impostare la lunghezza? –

risposta

17

Questo è un chrome bug.

FF fa esporre la durata dei supporti registrati, e se imposta la currentTime dei supporti registrati a più di sua effettiva duration, allora la proprietà è disponibile in cromo ...

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>

quindi il consiglio qui sarebbe di star del bug report in modo che la squadra di cromo richiede un po 'di tempo per risolvere il problema, anche se questa soluzione può fare il trucco ...

+0

Là è un bug: https://crbug.com/642012. Suggerisco di "definirlo" in modo che gli sviluppatori possano stabilire le priorità di conseguenza. – miguelao

+0

@miguelao, sì ho archiviato [questo] (https://bugs.chromium.org/ p/cromo/issues/detail? id = 656426) che è stato unito a quello che hai citato – Kaiido

+0

Wow, questo ha funzionato. –

0

Grazie a @Kaiido per identificare bug e offrire la soluzione di lavoro.

Ho preparato un pacchetto npm chiamato get-blob-duration che è possibile installare per ottenere una bella funzione Promise-wrapped per eseguire il lavoro sporco.

uso è il seguente:

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

o ECMAScript 6:

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