admin管理员组文章数量:1406943
I have been trying to create my custom media player using HTML5 and Jquery.
I have followed different approaches and ran into some trouble based on my way of refreshing the page.
First Case
$(document).ready(function(){
duration = Math.ceil($('audio')[0].duration);
$('#duration').html(duration);
});
In this case, the duration returns NaN when I redirect the page to the same URL by pressing the ENTER
key in the address bar. However, it works pletely fine when I refresh using the reload button
or by pressing the F5
button.
Second Case
I read in some answers that loading duration after the loadedmetadata
event might help. So I tried the following:
$(document).ready(function(){
$('audio').on('loadedmetadata', function(){
duration = Math.ceil($('audio')[0].duration);
$('#duration').html(duration);
});
});
Surprisingly, in this case, the inverse of the first case happened. The duration gets displayed pletely fine in the case of a redirect, i.e., pressing ENTER
while in the address bar. However, in the case of refreshing using the F5
button or the reload button
, the duration doesn't get displayed at all, not even NaN which led me to believe that the code doesn't get executed at all.
Further reading suggested this might be a bug within the webkit browsers but I couldn't find anything conclusive or helpful.
What could be the cause behind this peculiar behavior? It'd be great if you could explain it along with the solution to this problem.
Edit: I am mainly looking for an explanation behind this difference in behavior. I would like to understand the mechanism behind rendering a page in the case of redirect and refresh.
I have been trying to create my custom media player using HTML5 and Jquery.
I have followed different approaches and ran into some trouble based on my way of refreshing the page.
First Case
$(document).ready(function(){
duration = Math.ceil($('audio')[0].duration);
$('#duration').html(duration);
});
In this case, the duration returns NaN when I redirect the page to the same URL by pressing the ENTER
key in the address bar. However, it works pletely fine when I refresh using the reload button
or by pressing the F5
button.
Second Case
I read in some answers that loading duration after the loadedmetadata
event might help. So I tried the following:
$(document).ready(function(){
$('audio').on('loadedmetadata', function(){
duration = Math.ceil($('audio')[0].duration);
$('#duration').html(duration);
});
});
Surprisingly, in this case, the inverse of the first case happened. The duration gets displayed pletely fine in the case of a redirect, i.e., pressing ENTER
while in the address bar. However, in the case of refreshing using the F5
button or the reload button
, the duration doesn't get displayed at all, not even NaN which led me to believe that the code doesn't get executed at all.
Further reading suggested this might be a bug within the webkit browsers but I couldn't find anything conclusive or helpful.
What could be the cause behind this peculiar behavior? It'd be great if you could explain it along with the solution to this problem.
Edit: I am mainly looking for an explanation behind this difference in behavior. I would like to understand the mechanism behind rendering a page in the case of redirect and refresh.
Share edited Jun 12, 2015 at 14:05 Akshay Khetrapal asked Jun 11, 2015 at 0:08 Akshay KhetrapalAkshay Khetrapal 2,6765 gold badges25 silver badges39 bronze badges 04 Answers
Reset to default 3It sounds like the problem is that the event handler is set too late, i.e. the audio file has loaded its metadata before the document is even ready.
Try setting the event handler as soon as possible by removing the $(document).ready
call:
$('audio').on('loadedmetadata', function(){
duration = Math.ceil($('audio')[0].duration);
$('#duration').html(duration);
});
Note that this requires that the <script>
tag be after the <audio>
tag in the document.
Alternatively, you can tweak your logic slightly, so that the code that updates the duration always runs (but fails gracefully if it gets a NaN
):
function updateDuration() {
var duration = Math.ceil($('audio')[0].duration);
if (duration)
$('#duration').html(duration);
}
$(document).ready(function(){
$('audio').on('loadedmetadata', updateDuration);
updateDuration();
});
Lovely code examples and stuff from people - but the explanation is actually very simple.
If the file is already in the cache then the loadedmetadata
event will not fire (nor will a number of other events - basically because they've already fired by the time you attach your listeners) and the duration
will be set. If it's not in the cache then the duration
will be NaN
, and the event will fire.
The solution is sort of simple.
function runWhenLoaded() { /* read duration etc, this = audio element */ }
if (!audio.readyState) { // or $audio[0].readyState
audio.addEventListener("loadedmetadata", runWhenLoaded);
// or $audio.on("loadedmetadata", runWhenLoaded);
} else {
runWhenLoaded.call(audio);
// or runWhenLoaded.call($audio[0]);
}
I've included the jQuery alternatives in the code ments.
According to w3 spec this is standard behavior when duration returns NaN.
So I suggest use durationchange
event:
$('audio').on('durationchange', function(){
var duration = $('audio')[0].duration;
if(!isNaN(duration)) {
$('#duration').html(Math.ceil(duration));
}
});
NOTE: This code (and your too) will not work correct in case if you have more than one audio
element on page. Reason is that you listen events from all audio
elements on page and each element will fire own event:
$('audio').on('durationchange', function(){...});
OR
You can try:
<script>
function durationchange() {
var duration = $('audio')[0].duration;
if(!isNaN(duration)) {
$('#duration').html(Math.ceil(duration));
}
}
</script>
<audio ondurationchange="durationchange()">
<source src="test.mp3" type="audio/mpeg">
</audio>
Note that behaviors will differ from one browser to another. On Chrome, you have different type of loading. When resources are not in cache
, it will fetch either the plete file (for js or css for example), either a part of the file (mp3 for example). This partial file contains metadata
that allows browser to determine duration and other data such as the time it'll take to download whole file at this rate, trigerring for example canplay
or canplaythrough
events. If you look at network usage in you dev console, you'll see that the HTTP status code
will be either 200 (succesful load) or 206(partial load - for mp3 for example).
When you hit refresh
, elements are checked to see if they changed. HTTP status will then be 304
, meaning file hasn't been modified. If it hasn't changed and is still in browser cache, then it won't be downloaded. The call to determine if it has or not changed es from the server providing the file.
When ou simply click enter in adress bar, it's automatically taken from cache, not validating online. So it's much faster.
So depending on how you call or refresh your page (either simmple enter, refresh or plete refresh without cache), you'll have big differences on the moment you get the metadata
from your mp3. Between taking the metadata from cache directly vs making a request to a server, the difference can be a few hundreds milliseconds, which is enough to change what data is available at different moment.
That being said, listening to loadedmetada
should give consistent result. This event is triggered when the data with duration information is loaded, so whatever way the page is loaded, it shouldn't matter if that called is properly made. At this point you have to consider maybe some interference from other elements. What you should do is follow your audio through various events to get exactly where its at at different moments. So in you document ready you could add listeners for different event and see where the problem occurs. Like this:
$('audio')[0].addEventListener('loadstart', check_event)
$('audio')[0].addEventListener('loadeddata', check_event)
$('audio')[0].addEventListener('loadedmetadata', check_event)//at this point you should be able to call duration
$('audio')[0].addEventListener('canplay', check_event) //and so on
function check_event(e) {
console.log(e.target, e.type)
}
You'll see that depending on the way you refresh, these events can e at different moments, maybe explaining inconsistencies in your outputs.
本文标签: javascriptAudio duration NaN on certain page request actionStack Overflow
版权声明:本文标题:javascript - Audio duration NaN on certain page request action - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744935887a2633183.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论