我正在尝试获取音频的持续时间,但结果为NaN
。以下是我的所作所为,有人可以告诉我这是什么问题吗?
<audio class="my-audio"></audio>
$(document).ready(function(){
addAudioPlayer();
});
//dynamically assign id to an audio player
function addAudioPlayer(){
var index = 0;
//find class"my-audio-player"
$(document).find(".my-audio-player").each(function(){
$(this).attr('id', 'player'+index );
$(this).append("<source src=\""+mediaFiles[index]+"\" type=\"audio/mp3\" >")
new AudioPlayer(mediaFiles[index], index);
index++;
});
}
function AudioPlayer(media, index){
//set objects reference
this.audio = document.getElementById("player"+ index);
this.audio.onloadedmetadata;
this.audio.play();
console.log("audio = " + this.audio);
console.log("audio src = " + this.audio.src);
console.log("audio dur = " + this.audio.duration);
}
答案 0 :(得分:1)
继上面的评论之后,这是一个有效的演示。我选择将jQuery引用交换为vanilla JS,因为这是我的偏好(我没有花时间熟悉jQuery。也许这些年中的一个:))
您可以轻松地将其重新插入。
您也无法获得源的有效结果,因为<audio>
元素的src
属性为空,您想要的是{{1}的src
属性包含在source
元素中的元素。
另一个疏忽是范围。由于<audio>
事件是onloadedmetadata
元素对象的一部分,因此<audio>
关键字引用this
元素
<audio>
应为this.audio.play()
,this.play()
应替换为this.audio
,this
应更改为this.audio.src
(请记住,我们需要src属性(源元素)最后,this.childNodes[0].src
应为this.audio.duration
。
值得指出的是,this.duration
第一行的this
引用了AudioPlayer
函数(对象),因为您没有将新AudioPlayer的结果分配给任何东西,这个line基本上什么都不做,可以稍微修改一下,我刚刚抓住了对AudioPlayer
元素的引用,并从那里设置了它的<audio>
事件处理程序。
唷!头晕了吗? javascript中的范围在某些时候会抓住每个人。许多人仍然没有完全掌握它。 ;)
首先,这是完整的代码:
(编辑#2:更新了代码,以便显示每个播放曲目的进度,每500毫秒更新一次,并以曲目长度的百分比显示 - 应该足以为您提供一个想法,我希望)
onloadmetadata
编辑#1:在页面加载时,控制台输出会立即显示,并且音频文件也会立即播放。我必须使用屏幕录制应用程序来获得甚至是半精确的数字,因为这一切都发生得太快了。
编辑#3:这是控制台输出。 (行号应在右侧)
<!DOCTYPE html>
<html>
<head>
<script>
"use strict";
function allByClass(className,parent){return (parent == undefined ? document : parent).getElementsByClassName(className);}
function forEachNode(nodeList, func){for (var i=0, n=nodeList.length; i<n; i++) func(nodeList[i], i, nodeList); }
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded()
{
addAudioPlayer();
}
var mediaFiles = ['audio/voice_welcomeback.mp3', 'audio/Some Chords.mp3'];
var progressIntervalHandle;
function addAudioPlayer()
{
var index = 0;
var audioPlayers = allByClass('my-audio-player');
forEachNode(audioPlayers, audioPlayerEnumCallback);
progressIntervalHandle = setInterval(updateProgress, 500);
function audioPlayerEnumCallback(elem, index, elemArray)
{
elem.id = 'player'+index;
elem.innerHTML = "<source src='" + mediaFiles[index] + "' type='audio/mp3'>";
new AudioPlayer(mediaFiles[index], index);
index++;
}
}
function AudioPlayer(media, index)
{
document.getElementById("player"+ index).onloadedmetadata = function(evt)
{
this.play();
console.log("audio = " + this);
console.log("audio src = " + this.childNodes[0].src);
console.log("audio dur = " + this.duration);
}
}
function updateProgress()
{
var audioElems = allByClass('my-audio-player');
var outputMsg = '';
forEachNode(audioElems, audioElemEnumProgressCallback);
document.getElementById('progressOutput').innerHTML = outputMsg;
function audioElemEnumProgressCallback(elem, index, elemAray)
{
outputMsg += "Song " + index + ": " + ((100*elem.currentTime) / elem.duration).toFixed(2) + "%" + "<br>";
}
}
</script>
<style>
</style>
</head>
<body>
<audio class="my-audio-player"></audio>
<audio class="my-audio-player"></audio>
Progress:<br>
<div id='progressOutput'></div>
</body>
</html>
答案 1 :(得分:1)
你绝对不需要挖掘你的<audio>
元素的childNodes,它容易出现错误错误(例如,如果你有多个<source>
元素,或者如果您将后备消息设置为<audio>
元素。)
要获取当前播放媒体的地址,您需要检查AudioElement.currentSrc属性。
你的持续时间返回NaN的问题只是你在加载元数据之前尝试获取它,因为你没有为loadedmetadata
事件设置任何内容,即使你做了,{{1} }不再引用好对象了。
this
var mediaFiles = ["http://media.w3.org/2010/07/bunny/04-Death_Becomes_Fur.mp3"];
//dynamically assign id to an audio player
function addAudioPlayer(){
var index = 0;
//find class"my-audio-player"
$(document).find(".my-audio-player").each(function(){
$(this).attr('id', 'player'+index );
$(this).append("<source src=\""+mediaFiles[index]+"\" type=\"audio/mp3\" >")
new AudioPlayer(mediaFiles[index], index);
index++;
});
}
function AudioPlayer(media, index){
//set objects reference
// instead of passing the index, you could simply pass the element as argument
this.audio = document.getElementById("player"+ index);
// you forgot to set onloadedmetadata as a function
this.audio.onloadedmetadata = function(){
// "this" now refers to the audio element
this.play();
snippet.log("audio = " + this);
// to get the audio src, it is always preferred to get its currentSrc (the one of the choosen media resource)
snippet.log("audio src = " + this.currentSrc);
snippet.log("audio dur = " + this.duration);
}
}
addAudioPlayer();
答案 2 :(得分:0)
正如 @PaulRoub 从链接的MDN Arcticle指出:
如果媒体数据可用但长度未知,则此值为NaN。如果媒体是流式传输且没有预定义长度,则值为Inf。
要解决此问题,请检查NaN
的值,并将其替换为用户更需要的内容,例如 unknown 或 unknown duration 。
请参阅下面的快速实施:
console.log("audio dur = "
+ ((this.audio.duration != this.audio.duration) ? "unknown" : this.audio.duration));
这是搜索值NaN
的快捷方式。当且仅当 this.audio.duration != this.audio.duration
为this.audio.duration
时,NaN
才会为真。