HTML5 video - Waiting event not firing - javascript

I'm messing around with HTML5 videos and custom controls and I'm looking to use the waiting event to ideally display a loading image but just writing to the console will do for now.
The waiting event
Playback has stopped because the next frame is not available, but the
user agent expects that frame to become available in due course.
I've set an example up here -> http://jsbin.com/uvipev/2/edit#javascript,html,live
Here's the video code minus the controls:
<video controls preload="meta">
<source src="http://www.tools4movies.com/dvd_catalyst_profile_samples/The%20Amazing%20Spiderman%20tablet.mp4" />
This is video fallback
</video>
And here's my event listener for the waiting event.
var video = document.getElementsByTagName('video')[0];
video.addEventListener('waiting', function() {
console.log('waiting');
}, false);
Can anyone see why this isn't running? The waiting event sounds like what I need.

Are you looking to display a waiting image while the video buffers for the first time? If so, you probably aren't looking for waiting.
Take a look at this demo: http://www.w3.org/2010/05/video/mediaevents.html
If you call play() without any preloading, you should see waiting fire, even on a cached copy. If you call load() before play(), you may never see waiting fire, since the next frame could always be available.
The best process would be to display your image, call load() and then listen wait for either canplay or canplaythrough. At that point, hide your image and kick off play().
Update
Looking at the video in this fiddle: http://jsfiddle.net/bnickel/zE8F3/ Chrome isn't sending the waiting event but is instead sending the stalled event shortly after the video freezes up. You're probably going to need to check how things work on each browser you support. Bear in mind, players like VideoJS are huge (~142KB) because they deal with a lot of browser inconsistencies.

There's a good chart here that attempts to document the behavior of different browsers in a "buffer underrun" scenario, which is what I think you're looking for.
https://web.archive.org/web/20130902074352/http://www.longtailvideo.com/html5/buffering/
Unfortunately, the browsers are wildly inconsistent, so while I do believe the "waiting" event is what you want, Chrome doesn't fire it.
I've been experimenting with "guessing" when the player is buffering based on the elapsed time of the video, checking for play/pause/etc. events so that I know when the time should be increasing.

Related

Audio delay on Safari Desktop

I have a page with several <audio> tags. Whenever I play the audio in Chrome (Desktop, macOS), it starts immediately, while in Safari (13.1, macOS) it waits for some time before starting playing (the weird thing is that it waits longer if they are several audio tags on the page).
I thought that the problem was with the "preload" attribute not set, so I've set it to "auto" according to the docs]1, but it didn't change a thing.
I don't want to use a 3rd party library to keep as as simple as possible.
How can I remove this delay? And why is it longer the more audio tags I have on the page?
I was not able to remove the delay completely, but I made it much better by setting preload to ="metadata". For some reason it makes files load much quicker for playback.
Chrome actually is smart about this. When the preload is set to auto, it caches around 1mb of each audio file upon page load, so it can play it quicker when you press "Play" button.
I also started listening to onwaiting event of the audio element, so I can show the preloader to make experience a little bit better.
Since Safari fires oncanplay and onplaying much sooner when the file is actually ready to play, I don't just hide preloader on this events, but after a 1.5 second timeout to smooth it out.
That's good enough for me, since the lag decreased from 30 seconds (with 10 audio elements on page) to just 1.5 seconds.

Detect if <audio> `pause` event fired by user interaction or buffer underrun?

When playing a live audio stream, like web radio, through <audio> or Audio(), the pause event can fire in (at least) three ways:
user clicks on the pause button (with <audio controls>)
user clicks the browsers global audio controls
iOS: Control Center
Android: browser's notification drawer (at least Chrome, Opera, Firefox)
Desktop: Media Session API controls, but uninitialized, without explicit setActionHandler (might be hidden behind a flag as of now)
a buffer underrun caused by various network conditions
Is it possible to distinguish between 1/2 and 3?
Ideally, there would be an event property like isTrusted, which I am missing
I have tried to guess, looking esp. at readyState and networkState, but both are very inconclusive, especially across browsers (e.g. the interpretation/semantics of HAVE_FUTURE_DATA vs HAVE_ENOUGH_DATA)
I have shied away from making a "decaying state machine", juggling other events. A buffer underrun is often preceded by stalled events, and sometimes followed by ended events. A cross-browser implementation seems crazy complex and the danger of false positives very high.
Am I out of luck until Media Session lands everywhere?
Note: this question looks like a solution, but unfortunately isn't -- browsers handle live streams' "ends" differently and inconsistently.
The waiting event should fit your needs.
You can try this demo while you simulate bad network with the dropdown in Chrome's Network tab (e.g: Slow 3G)
const video = document.getElementById('mwe_player_0');
video.onwaiting = function() { console.log('onwaiting'); };
<video id="mwe_player_0" controls="" preload="none" style="width:800px;height:450px"><source src="https://upload.wikimedia.org/wikipedia/commons/2/22/Volcano_Lava_Sample.webm" type="video/webm; codecs="vp8, vorbis""></video>
Note that this demo works with HTMLAudioElement as well (because it inherits HTMLMediaElement). The video demo is just easier to test.
If you want to start an event when the user pauses the audio then this snippet will do the job. I didn't test it on mobile in the notification drawer but I think it'll work.
const video = document.querySelector('video');
video.addEventListener('pause', (event) => {
console.log('The Boolean paused property is now true. Either the ' +
'pause() method was called or the autoplay attribute was toggled.');
});
resource: audio element events
resource: pause event
I also found a helpful answer to what you are trying to do 2 (at least from what I understand) and why it's a bad technique. Link to question
3 Events: stalled / waiting check the events resource

currentlyLoading-Event for html5 video-Tag

I'm looking for a way to create something like a loading animation on a html5 video similar to the Youtube Video display (reference: https://www.youtube.com/watch?v=5vcCBHVyG50)
I tried it with the canplay-Event but I think I misunderstood the real meaning of this event.
My thought of this event was that enough data has been loaded and buffered so that the video can be played again.
But in my case this event just fires once. At the beginning of the video.
Is there any special Event which will be fired when the video is playable or needs to load more data?
Use fontAwesome framework. It has got your animation.

HTML5 - Check if autoplay is allowed

My website plays background music with autoplay. I made it use my custom controls for play and pause. Now, I'd like to set the initial state according to what is going on. If the music is about to play for real, it should show pause icon, otherwise (e.g. on mobile) play icon.
I would use audio.paused boolean value, but it's always false before the audio is loaded.
I would use audio.autoplay value, but it's always true for me, even on devices that don't support it.
Is there any clean way to know whether the audio will be played? I would like to keep it in sync with autoplay attribute, so if I decided to remove it, the state should always show play icon in the beginning.
Just playing or even buffering songs isn't especially fair, when there is the slightest chance people can be on the site for other reasons, like for example to check for updates, to share the link. people can be on the page with a mobile network, with limited bandwidth and downloads of those sizes shouldn't ever start sneaky behind their back.
edit: a few additional references
Here is an overview over the reasons not to have music on autoplay
And contrary, a website I personally like a lot with a great use of background music on autoplay
But if you are already building your own player and want that to be a feature of the page, setting that player to autoplay would not only devalue your own work, totally break your design. Instead you could just trust that people who want to hear the music will identify your audio player and use it.
To fully implement your custom player GUI you may want to listen for all audio events on the player element and update your view accordingly. The event you are looking for is "canplaythrough" but you probably want to react to at least most of the other events too. Those events are:
playing
waiting
seeking
seeked
ended
loadedmetadata
loadeddata
canplay
canplaythrough
timeupdate
play
pause
ratechange
volumechange
suspend
emptied
stalled
You currently may do something along the lines of
view.showPlayButton();
player.play();
but that breaks as soon as you at some point want to toggle your player in some other way or something else happens, like it gets stalled, so better listen to the event and update your GUI in one place, and control the playback (like start / stop the player) in another.

How to determine when buffering is finished on a HTML5 Audio element

I'm trying to determine when the buffering has finished from a HTML5 audio element, but so far I can't find any loadComplete or similar event. I've tried using the progress event however it doesn't fire when finished downloading - only while downloading and therefore I can't use that to check. I've also tried the standard load event but that seems not to fire at all.
What other events are there that would allow me to check if buffering is finished, or would I have to use a timer to keep checking if a.buffered.end(0) == a.duration?
Thanks,
The Audio Data API provides an event called MozAudioAvailable which does what you need. This is in Firefox 4 only, but other modern browsers may implement it in the future.

Categories