I try to record audio and get the duration of the audio from blub using loadedmetadata event in Promise. It works well in Firefox. But Chrome returns duration as Infinity. iPhone cannot even load audio metadata from blob. What is the problem. If I try to get audio duration for file selected from local device instead of the blob file from media recorder, these codes work in Chrome and iPhone Safari. What is the problem? How to get audio duration from blob file?
Here is the code in jsfiddle :
https://jsfiddle.net/c7a8bqvp/3/
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.js"></script>
<button id="startAudioRecord" onClick="startAudioRecording()">Start Audio recording </button>
<button id="endAudioRecorder" onClick="endAudioRecording()">End Recording</button>
<div id="audioRec_div"><br>Here is the audio:<br><audio id="audioRec" ></audio></div>
<script>
var sc_audioStream , sc_audioRec ;
var url ;
// var url = "https://www.w3schools.com/tags/horse.mp3";
async function getAudioUrlDuration(src) {
var audio = new Audio();
audio.src = src;
return new Promise((resolve) => {
$(audio).on("loadedmetadata", function(){
duration = audio.duration;
resolve(audio.duration);
});
$(audio).on("error", function(e) {
alert("Failed to load audio metadata="+JSON.stringify(e));
});
});
}
function getUserMedia_audio(){
navigator.mediaDevices.getUserMedia({
audio: true
})
.then(stream => {
sc_audioStream = stream ;
sc_audioRec = new MediaRecorder(stream);
sc_audioRec.ondataavailable = e => {
var audioRec_arr = [] ;
audioRec_arr.push(e.data);
if( sc_audioRec.state == "inactive") {
alert(666);
let blob = new Blob(audioRec_arr, {
type: 'audio/mp3'
});
processBlob(blob) ;
}
}
})
.catch((e) => {
console_log(e);
});
}
function startAudioRecording() {
sc_audioStream = null ; sc_audioRec = null ;
getUserMedia_audio() ;
setTimeout(function(){
sc_audioRec.start();
alert('speak now to record, click end button to stop recording');
},1500); // use at least 1500
}
function endAudioRecording() {
if( sc_audioStream != null ){
//sc_audioRecord.stop(); This works for audio too
sc_audioStream.getAudioTracks().forEach(function(track) {
// alert('track.readyState='+track.readyState);
if (track.readyState == 'live') {
track.stop();
}
});
}
}
async function processBlob(blob){
// load audio to hmtl
var audio_recorded = $('#audioRec') ;
alert(888); alert(URL.createObjectURL(blob));
audio_recorded.attr("src", URL.createObjectURL(blob));
audio_recorded.prop("controls", true);
//
var audioDuration = await getAudioUrlDuration( URL.createObjectURL(blob) ) ;
alert('audioDuration='+audioDuration) ;
}
</script>