音频持续时间是NaN

时间:2015-08-26 19:31:35

标签: javascript html5-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);
}

3 个答案:

答案 0 :(得分:1)

继上面的评论之后,这是一个有效的演示。我选择将jQuery引用交换为vanilla JS,因为这是我的偏好(我没有花时间熟悉jQuery。也许这些年中的一个:))

您可以轻松地将其重新插入。

您也无法获得源的有效结果,因为<audio>元素的src属性为空,您想要的是{{1}的src属性包含在source元素中的元素。

另一个疏忽是范围。由于<audio>事件是onloadedmetadata元素对象的一部分,因此<audio>关键字引用this元素 <audio>应为this.audio.play()this.play()应替换为this.audiothis应更改为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.durationthis.audio.duration时,NaN才会为真