音频持续时间为 NaN
audio duration is NaN
我正在尝试获取音频的持续时间,但结果是 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);
}
正如 @PaulRoub 从链接中指出的 MDN Arcticle:
If the media data is available but the length is unknown, this value is NaN. If the media is streamed and has no predefined length, the value is Inf.
要解决此问题,请检查 NaN
的值并将其替换为用户更想要的内容,例如 unknown 或 未知持续时间.
请参阅下面的快速实施:
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
.
除了我上面的评论,这里还有一个工作演示。我选择将 jQuery 引用换成 vanilla JS,因为那是我的偏好(而且我没有花时间熟悉 jQuery。也许这些年中的某一年 :) )
你可以很容易地把它放回去。
您也不会获得源的有效结果,因为 <audio>
元素的 src
属性为空,您需要的是 src
属性 source
元素包含在 <audio>
元素中。
另一个疏忽是范围。由于 onloadedmetadata
事件是 <audio>
元素对象的一部分,因此 this
关键字引用 <audio>
元素
this.audio.play()
应该是this.play()
,this.audio
应该换成this
,this.audio.src
应该改成this.childNodes[0].src
(记住,我们要的是src属性源元素的)最后,this.audio.duration
应该是 this.duration
。
还值得指出的是,AudioPlayer
第一行的 this
指的是 AudioPlayer
函数(对象),因为您没有将 new AudioPlayer 的结果分配给任何东西,这line 基本上什么都不做,可以稍微改变,我刚刚获取了对 <audio>
元素的引用,并从那里设置了它的 onloadmetadata
事件处理程序。
呸!头疼了吗? javascript 中的范围界定在某些时候会抓住所有人。许多人仍然无法完全掌握它。 ;)
首先,这是完整的代码:
(编辑 #2: 更新代码以便显示每个播放曲目的进度,每 500 毫秒更新一次并显示为曲目长度的百分比 - 它应该足以给你一个想法,我希望)
<!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: 控制台输出几乎在页面加载时立即出现,音频文件(两者)也立即播放。我不得不使用屏幕录制应用程序来获得半准确的数字,因为这一切发生得太快了。
编辑 #3: 这是控制台输出。 (行号应该在右边)
audioDemo.html:42 audio = [object HTMLAudioElement]
audioDemo.html:43 audio src = file:///C:/xampp/htdocs/enhzflep/audio/voice_welcomeback.mp3
audioDemo.html:44 audio dur = 1.68
audioDemo.html:42 audio = [object HTMLAudioElement]
audioDemo.html:43 audio src = file:///C:/xampp/htdocs/enhzflep/audio/Some%20Chords.mp3
audioDemo.html:44 audio dur = 444.186122
你绝对不需要挖掘你的 <audio>
元素的子节点,这很容易出错(例如,如果你有多个 <source>
元素,或者如果您在 <audio>
元素中设置回退消息。)
为了获取当前播放媒体的地址,您需要检查 AudioElement.currentSrc 属性。
你的持续时间返回 NaN 的问题只是你试图在加载元数据之前获取它,因为你没有为 loadedmetadata
事件设置任何东西,即使你这样做了,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();
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<audio class="my-audio-player" controls></audio>
我正在尝试获取音频的持续时间,但结果是 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);
}
正如 @PaulRoub 从链接中指出的 MDN Arcticle:
If the media data is available but the length is unknown, this value is NaN. If the media is streamed and has no predefined length, the value is Inf.
要解决此问题,请检查 NaN
的值并将其替换为用户更想要的内容,例如 unknown 或 未知持续时间.
请参阅下面的快速实施:
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
.
除了我上面的评论,这里还有一个工作演示。我选择将 jQuery 引用换成 vanilla JS,因为那是我的偏好(而且我没有花时间熟悉 jQuery。也许这些年中的某一年 :) )
你可以很容易地把它放回去。
您也不会获得源的有效结果,因为 <audio>
元素的 src
属性为空,您需要的是 src
属性 source
元素包含在 <audio>
元素中。
另一个疏忽是范围。由于 onloadedmetadata
事件是 <audio>
元素对象的一部分,因此 this
关键字引用 <audio>
元素
this.audio.play()
应该是this.play()
,this.audio
应该换成this
,this.audio.src
应该改成this.childNodes[0].src
(记住,我们要的是src属性源元素的)最后,this.audio.duration
应该是 this.duration
。
还值得指出的是,AudioPlayer
第一行的 this
指的是 AudioPlayer
函数(对象),因为您没有将 new AudioPlayer 的结果分配给任何东西,这line 基本上什么都不做,可以稍微改变,我刚刚获取了对 <audio>
元素的引用,并从那里设置了它的 onloadmetadata
事件处理程序。
呸!头疼了吗? javascript 中的范围界定在某些时候会抓住所有人。许多人仍然无法完全掌握它。 ;)
首先,这是完整的代码:
(编辑 #2: 更新代码以便显示每个播放曲目的进度,每 500 毫秒更新一次并显示为曲目长度的百分比 - 它应该足以给你一个想法,我希望)
<!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: 控制台输出几乎在页面加载时立即出现,音频文件(两者)也立即播放。我不得不使用屏幕录制应用程序来获得半准确的数字,因为这一切发生得太快了。
编辑 #3: 这是控制台输出。 (行号应该在右边)
audioDemo.html:42 audio = [object HTMLAudioElement]
audioDemo.html:43 audio src = file:///C:/xampp/htdocs/enhzflep/audio/voice_welcomeback.mp3
audioDemo.html:44 audio dur = 1.68
audioDemo.html:42 audio = [object HTMLAudioElement]
audioDemo.html:43 audio src = file:///C:/xampp/htdocs/enhzflep/audio/Some%20Chords.mp3
audioDemo.html:44 audio dur = 444.186122
你绝对不需要挖掘你的 <audio>
元素的子节点,这很容易出错(例如,如果你有多个 <source>
元素,或者如果您在 <audio>
元素中设置回退消息。)
为了获取当前播放媒体的地址,您需要检查 AudioElement.currentSrc 属性。
你的持续时间返回 NaN 的问题只是你试图在加载元数据之前获取它,因为你没有为 loadedmetadata
事件设置任何东西,即使你这样做了,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();
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<audio class="my-audio-player" controls></audio>