我尝试使用Promise中的loadedmetadata事件来录制音频并从blub获取音频的持续时间。它在 Firefox 中运行良好。但 Chrome 返回的持续时间为 Infinity。 iPhone 甚至无法从 blob 加载音频元数据。问题是什么。如果我尝试获取从本地设备选择的文件的音频持续时间,而不是从媒体记录器中获取 blob 文件,这些代码可以在 Chrome 和 iPhone Safari 中使用。问题是什么?如何从 blob 文件获取音频持续时间?
这是jsfiddle中的代码:
https://jsfiddle.net/c7a8bqvp/4/
<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(){
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>
使用事件监听器尝试一次