Firefox doesn't recognize if video src gets interrupted - javascript

i'm currently playing around with video.js to make video watching a bit more reliable. The current case if: while watching a video, the connection gets interrupted (loss of internet connectivity).
With chrome it was no big deal: I created a function, attached the function to the error event and voila, if an error occurred, my function was able to recover (in this case its just trying to reload the video and seek to the last known position).
On firefox nothing happened at all. The error is never raised.
I tried to work around this a bit and noticed that firefox seems to think the file is fully loaded in case of a network interruption. So the bufferedPercent jumps to 1 and the loadedalldata event is also triggered. For me this seems to be just broken, but i'm unable to nail it down to a firefox or a video.js problem.
Anyone else having such problems or knows a better way to handle such problems?
Background info: to test the case, i run a HAProxy infront of two webservers running nginx who deliver the video files. To trigger my problem, i just kill the nginx which is currently delivering the stream. So a reconnect should work fine (as long as the other one is still working of course ;)
Thanks and regards,
Darkman

Could it be that you are binding the error on the video tag and not the source tag?
As stated here:
Instead of the error event being dispatched to the media element itself, it now gets delivered to the child elements corresponding to the sources resulting in the error.
<video controls id="videoTag" width="640" height="360" preload="auto">
<source src="pathto.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' id="mp4Source">
<source src="pathto.webm" type='video/webm; codecs="vp8.0, vorbis"' id="webmSource">
</video>
<script type="text/javascript">
document.getElementById('mp4Source').addEventListener('error', function(ev) {
alert('mp4Source error');
}, false);
document.getElementById('webmSource').addEventListener('error', function(ev) {
alert('webmSource error');
}, false);
document.getElementById('videoTag').addEventListener('error', function(ev) {
alert('videoTag error');
}, false);
document.getElementById('videoTag').addEventListener('stalled', function(ev) {
alert('videoTag stalled');
}, false);
</script>
EDIT: also check for the stalled event as it triggers when one disconnects the network while the media resource is downloading. Source.
When detecting playback/network errors on HTML5 video I normally use something that follows the code at end of this section.
Thanks

Related

Safari does not stop downloading media after removing src and calling load()

After an HTML media element is paused, the browser keeps downloading the media.
MDN describes how the download can be stopped by removing the media element's src attribute and calling HTMLMediaElement.load(): MDN - Stopping the download of media.
In Safari, this is not sufficient to stop the media continuing to download. In the Web Inspector Network tab, the transfer can be seen to continue. This is despite the load() method being supported and the appropriate events being sent when it is called. (See MDN.)
Using the following example and monitoring the network, you should be able to see the behaviour in Safari differ compared to Chrome, for example.
<audio
controls preload="none" type="audio/mpeg"
src="http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio1_mf_p"
/>
<script>
const mediaEl = document.querySelector('audio');
mediaEl.addEventListener('abort', (e) => {
console.log('abort', e.target);
});
mediaEl.addEventListener('emptied', (e) => {
console.log('emptied', e.target);
});
mediaEl.addEventListener('pause', (e) => {
e.target.removeAttribute('src');
e.target.load();
});
</script>
Removing the media element from the DOM is not sufficient to stop the download either.
mediaEl.addEventListener('pause', (e) => {
e.target.parentNode.removeChild(e.target);
});
Is there a way to work around this issue in Safari and stop the download initiated by the media element?
My use case involves an audio stream. I do not want the browser to continue buffering after the user has stopped playback.
I had the same issue.
The only good workaround I've found is putting the audio tag in separate html and loading that into an iframe - then adding an event listener that reloads the audio tag's page when the stream is paused.

(Video-JS) Error from one video prevents all other videos from playing

I'm implementing Video-JS in to a client's website. The player works perfectly if the source of the video is found (of course). However, when the source of the video is not found, the plugin throws a JS error in the console:
VIDEOJS: ERROR: (CODE:4 MEDIA_ERR_SRC_NOT_SUPPORTED) FLASH: srcnotfound.
Such behavior is expected in this circumstance. However, that single error prevents all other Video-JS dependent videos from being playable.
I would prefer that the rest of the videos in the video gallery work correctly in the unlikely event that a video source is not found.
Is it possible to disable or catch the error and handle it in a manner that does not affect the rest of the application?
I figured out that this problem isn't related to the source not being found at all. Each video-js video must have a unique id attribute in the <video> tag in order for the flash videos to work.

Execute javascript when all videos on page have been fully loaded

I have modified this script to accept videos instead of images:
http://www.catchmyfame.com/catchmyfame-jquery-plugins/jquery-beforeafter-plugin/
Locally, it works fine, but when I upload to a server, the videos are not synced. The first video starts earlier than the other one. Check it out:
http://amarsyla.com/sandbox/beforeafter/
HTML:
<div id="container">
<div>
<video alt="before" autoplay="true" loop="true" width="600" height="366">
<source src="before.mp4" type="video/mp4;">
</video>
</div>
<div>
<video alt="after" autoplay="true" loop="true" width="600" height="366">
<source src="after.mp4" type="video/mp4;">
</video>
</div>
</div>
I initialize the plugin using this code:
$(window).load(function() {
$('#container').beforeAfter();
});
Obviously, the window.load doesn't do the job. I need a JavaScript event or something similar which will be triggered that both of the videos have been loaded and they can start playing simultaneously with each other. I want the videos to be in perfect sync with each other, so each of them starts at the same time, and I thought this would be possible by initializing the plugin after both videos have been fully loaded. I've tried this:
var vid = document.getElementById("myVideo");
vid.oncanplaythrough = function() {
alert("Can play through video without stopping");
};
That doesn't work as I expected. It doesn't always fire. Any help would be appreciated.
The code in your question is different from the code at the link, so I'll go by the latter since that's the one actually running.
It looks like what's happening is that even once the videos are playing, they're losing synchronization a few seconds later when they have to wait for more data from the network. One might think that "oncanplaythrough" would be enough to assume that the videos are sufficiently buffered to play all the way through without pausing, it's not always the case.
In theory, "canplaythrough" fires when the browser guesses that data is coming in faster than you're playing it, as opposed to "canplay" which fires when there is just enough data to show one or two frames from the current time. But Chrome fires "canplaythrough" immediately after "canplay" so you can't count on it. Even on other better-behaved browsers, it's still possible that the data transfer starts fast and then slows down after the event fires.
So that means that you have to continuously watch for any "waiting" events on either video and pause them both until they catch up again.
Here's an example you can use as a reference to get you started:
http://code.chirls.com/whiteknuckles/
It's very old code and not my best work. I would do it differently if I wrote it today, but it seems to work reasonably well.

when trying to set crossorigin attribute on video tag video playback is damaged

The issue occur on chrome browser desktop.
I'm getting the following error when trying to add track element to the video:
<video ...>
<track..>
</video>
http://jsfiddle.net/itayKinnrot/6Up5t/1/
when i'm adding the crossorigin attribute to the video (as the error suggest) the video playback is damaged (when trying to resume the video after pause - no playback + error from the video element)
http://jsfiddle.net/itayKinnrot/PrCZ5/1/
what am i'm doing wrong here.
I noticed that in your second fiddle, the resource request (of the video) is being 302-redirected.
It seems that Chrome does not properly handle CORS-enabled videos after a redirect (possibly due to a bug in the implementation that handles buffering/caching).
This is how it looks like in the network tab of the developer tools:
After replacing the src attribute of the video tag with the target of the redirection, I can properly seek through the video and pause/resume the playback. The network log shows successful byte range requests. Note that the developer tools did not show chunked responses for the first request, but only one continuous request.
This behavior screams "bug", so opening a new issue at http://crbug.com/new seems to be the best course of action. Try to create a small test case (preferably self-contained) to make it easier to pin-point the bug. Please add a comment with a link to the bug report when you've created the issue.

Javascript onloadedmetadata event not firing on iOS devices

Part of my current project involves loading external videos through HTML5's native video tag and then resizing them with Javascript to be the full height & width of the DOM.
My code seems to work perfectly on desktop browsers, but when I load up my project on my ipad the video doesn't get resized because the onloadedmetadata event never gets fired.
Here is a small code sample which reproduces the problem:
function init() {
var video = document.getElementById('viddy');
video.addEventListener('loadedmetadata', function(e){
var dimensions = [video.videoWidth, video.videoHeight];
alert(dimensions);
});
}
document.addEventListener("DOMContentLoaded", init, false);
<video id="viddy" autoplay>
<source src="http://media.w3.org/2010/05/sintel/trailer.webm" type='video/webm' />
<source src="http://www.w3schools.com/html/movie.mp4" type="video/mp4" />
</video>
http://jsfiddle.net/AUSNu/213/
I've even tried coding up a solution using jQuery, on the off-chance that the event may fire, but it still doesn't.
$('#viddy').on('loadedmetadata', function() {
alert('test');
});
I even went as far as enabling remote debugging through safari on my ipad, but still no output within the console.
Are there any workarounds to this? I couldn't find much info about this on the web / in documentation.
Unfortunately, there isn't really a way around this. Mobile Safari will not download any part of the video file until it gets a user interaction (i.e. some kind of touch event), not even the header, which is required to know the dimensions.
In your specific example, you need to enable controls on the video so the user can start it playing. (Or you can write your own code that starts it, but it has to be triggered by a touch or click event.) Once it starts playing, the loadedmetadata even will fire, and you can do what you want.
I recommend reading this other answer where someone else was trying to do pretty much the same thing. It discusses the problem in more detail along with a working link. Also, it addresses another problem with scaling the video that you will probably run into.
Safari on iPad (iOS6) does not scale HTML5 video to fill 100% of page width

Categories

Resources