HTML5 Javascript/jQuery Video MEDIA_ERR_NETWORK on localhost - javascript

I have a web application which is intermittently producing an error when using Chrome 30.0.1599.101 m.
I am using the HTML5 <video /> tag and controlling the src attribute using javascript.
The page which is causing the error sometimes errors on the first video or on the seventh. There is no predictable pattern.
Here is the javascript which handles the src:
var playing = false;
var media = $('#video')[0];
function initModule() {
$.ajax({
url: recap,
type:'HEAD',
error:
function(){
screenNotify('Error!', false, "404: Module video content could not be found." + recap, true);
},
success:
function() {
media.src = recap;
registerListeners(media);
media.load();
}
});
}
function registerListeners(listen) {
listen.addEventListener('ended', hide_recap);
listen.addEventListener('error', mediaError);
}
function mediaError(event) {
screenNotify('Media Error!', false, "Media failed with code: " + event.currentTarget.error.code, true);
}
function play_recap() {
if (!playing) {
playing = true;
media.play();
}
}
function hide_recap() {
if (playing) {
playing = false;
media.pause();
media.currentTime = 0.0;
}
}
Interestingly, there is no error thrown when I call media.load(), instead, you need to look at the network requests to see that the GET has actually produced a result of (failed).
Another thing to note, is this GET status only occurs for videos which reside within this particular folder location: /interactive/vids/recap/. The error does not occur anywhere else within the application.
Finally, the last thing which is strange about this error, is when the application finally attempts to play the video from play_recap(), about 1 second of the video will actually play, followed by an error being thrown on the video element.
The error is MEDIA_ERR_NETWORK however this application is installed locally on a Tomcat server and is running under localhost.
So why is the GET request producing (failed) and the HTML5 <video> element producing a MEDIA_ERR_NETWORK when everything is only ever running on localhost?

I've noticed very similar issue with Chrome 31. I'm getting inconsistently MEDIA_ERR_NETWORK, all other tested browsers work fine.
I haven't found any other solution than just retrying - you could try recreate the video element or just change currentTime - it always helps in my case.

Related

Feature detect if user gesture is needed

is there a way to detect if calling play() on a video element is allowed without a user gesture?
On Android Chrome this warning is given:
Failed to execute 'play' on 'HTMLMediaElement': API can only be initiated by a user gesture.
So on Chrome Android a user gesture is required to start the playback of a video, while it isn't on desktop Chrome.
Is there a way to detect which behavior I will get?
I want to have slightly different behavior in my app depending on if calling play programatically is allowed or not.
I have tried to use Modernizr.videoautoplay, but that checks if the autoplay property on the element, which is not the same thing. This gives false negatives for IE11 and Edge.
Edit: added an example. The video will start playing automatically in Chrome desktop and IE11 or Edge (with 3s delay) on windows 8 or 10. For Chrome#Android a user interaction is needed (clicking the button) and the error message can be seen in the console.
The play method returns a promise which can be used to catch the error.
Not all browsers follow the specification so you will have to check if what is returned is a promise first.
var autoPlayAllowed = true;
var promise = document.createElement("video").play();
if(promise instanceof Promise) {
promise.catch(function(error) {
// Check if it is the right error
if(error.name == "NotAllowedError") {
autoPlayAllowed = false;
} else {
throw error;
}
}).then(function() {
if(autoPlayAllowed) {
// Allowed
} else {
// Not allowed
}
});
} else {
// Unknown if allowed
}

YouTube embed API issue on IOS and Android

An issues popped up in the last few days with the YouTube embed API. The issue is that when you embed a video with the official API, it simply doesn't allow you to access to the API. When you try to access to the API, you got error message on the log (IOS) and if you try to play the video through the API the video blacks out. If you load it via the API, but you do not use the API, the user is able to play the video with tap.
The issue persist on the following browsers:
IOS 7 Safari on iPad and iPhone
IOS 7 Chrome on iPad and iPhone
Android 4 Chrome
(My play button uses the API to play the video and that produce the error)
JSfiddle: http://jsfiddle.net/frdd8nvr/6/
Error message:
Unable to post message to https://www.youtube.com. Recipient has origin http://fiddle.jshell.net.
postMessage[native code]:0
Jwww-widgetapi.js:26:357
Nwww-widgetapi.js:25
(anonymous function)[native code]:0
html5player.js:1201:97
Blocked a frame with origin "https://www.youtube.com" from accessing a frame with origin "http://jsfiddle.net". The frame requesting access has a protocol of "https", the frame being accessed has a protocol of "http". Protocols must match.
Some debug info:
As I see the API create the iframe on the site. The src is sometime http and sometime https.
http://www.youtube.com/embed/ZPy9VCovVME?enablejsapi=1&origin=http%3A%2F%2Ffiddle.jshell.net&autoplay=0&modestbranding=1&wmode=opaque&forceSSL=false
My test showed that most of the times YouTube servers simply LOCATION: https://... the request to the https url, but around 10% they served the http request with proper content.
I think somehow the issue related with the forced https, but I was not able to figure out the solution.
Have you experienced the same? Do you have some kind of solution for this problem? Is it a YouTube bug?
My test code:
<div id="myvideo"></div>
<button id="play-button">Play</button>
JS:
var tag = document.createElement("script");
tag.src = "//www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
onYouTubeIframeAPIReady = function () {
var vars = {
enablejsapi: 1,
origin: window.location.protocol + "//" + window.location.host,
autoplay: 0,
modestbranding: 1,
wmode: "opaque",
forceSSL: false
};
if (+(navigator.platform.toUpperCase().indexOf('MAC') >= 0 && navigator.userAgent.search("Firefox") > -1)){
vars.html5 = 1;
}
var playerobj = new YT.Player('myvideo', {
videoId: 'ZPy9VCovVME',
wmode: 'opaque',
playerVars: vars,
events: {
onReady: function(){
$('#play-button').on('click', function(){
playerobj.playVideo();
});
//playerobj.playVideo();
},
onStateChange: function(state){
switch(state.data){
case YT.PlayerState.PLAYING:
break;
//case YT.PlayerState.PAUSED:
case YT.PlayerState.ENDED:
break;
}
}
}
});
}
First, I think this is a duplicate of the following question: YouTube IFrame API play method doesn't work before touch on some Android tablets
I could reproduce the same problem on the YouTube Player Demo page.
The error
Unable to post message to https://www.youtube.com. Recipient has origin http://fiddle.jshell.net.
is only occuring on your jsfiddle. On the demo page this error is not occuring, therefore your observed bug seems not to be related to the error logged in the console. I checked this with chrome on Android 4.4.4.
Workaround
I have a dirty workaround which works on chrome on Android 4.4.4 (Nexus5) and 4.1.2 (S2). I have no iOS Device to test this. The workaround works on my phones, because the video always starts the second time I click the play-button.
http://jsfiddle.net/kjwpwpx8/6/
I can always start the video on click-Events after the playVideo function was called once before. In my workaround I put two iframes on the page. One is hidden while the other one is visible. If the page is viewed by a mobile browser I call the playVideo function of the second video after the OnReady-Event. The video won't play as the browser blocks this.
Now when our play-button is pressed the first video becomes hidden and stopped and the second video becomes visible and the playVideo function is called again.
Here is the important code:
var playerOptions = {
videoId: 'ZPy9VCovVME',
wmode: 'opaque',
playerVars: vars,
events: {}
};
var playerobj1 = new YT.Player('myvideo1', playerOptions);
var playerobj2 = null;
playerOptions.events.onReady = function(){
$('#play-button').on('click', function(){
$("#videowrapper .video1wrapper").hide();
playerobj1.stopVideo();
$("#videowrapper .video2wrapper").show();
playerobj2.playVideo();
});
if(isMobileBrowser)
playerobj2.playVideo();
};
playerobj2 = new YT.Player('myvideo2', playerOptions);

Restart download using `nsIWebBrowserPersist saveURI` or something else in a Firefox extension?

Mozzila has sample code for using nsIWebBrowserPersist saveURI to download files from a Firefox extension.
However, it doesn't say how to monitor if the download stops and needs to be restarted again.
Is there some way to check if the download stops and restart the download again? If I can't do it with nsIWebBrowserPersist, can I use something else?
You need to implement and nsIWebProgressListener and .progressListener.
Your listener must implement all nsIWebProgressListener methods, but you can just stub out most of them. The important one (for this question) is onStateChange, where you can check for an error result which will indicate network errors, and, as the documentation states, also check for the server returning http error:
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
var mylistener = {
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIWebProgressListener]),
...
onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
if (!(aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP)) {
// not yet done.
}
aWebProgress.progressListener = null; // reset to avoid circular references -> leaks
if (!Components.isSuccessCode(aStatus)) {
// Some network or file related error happened.
}
if (aRequest instanceof Components.interfaces.nsIHttpChannel && aRequest.responseStatus >= 400) {
// Some http related error happened.
}
}
};
Downloads.jsm supports resuming downloads. Set tryToKeepPartialData on your Downloads object.

Stop/Close webcam using getUserMedia and RTCPeerConnection Chrome 25

I'm on Chrome 25 successfully using getUserMedia and RTCPeerConnection to connect audio from a web page to another party, but I'm unable to get the API to stop the red blinking indication icon in the Chrome tab that media is being used on that page. My question is essentially a duplicate of Stop/Close webcam which is opened by navigator.getUserMedia except that the resolution there isn't working. If I have a page that just uses getUserMedia with no remote media (no peer), then stopping the camera turns off the blinking tab indicator. Adding remote streams seems to be a/the issue. Here's what I've currently got for my "close" code:
if (localStream) {
if (peerConnection && peerConnection.removeStream) {
peerConnection.removeStream(localStream);
}
if (localStream.stop) {
localStream.stop();
}
localStream.onended = null;
localStream = null;
}
if (localElement) {
localElement.onerror = null;
localElement.pause();
localElement.src = undefined;
localElement = null;
}
if (remoteStream) {
if (peerConnection && peerConnection.removeStream) {
peerConnection.removeStream(remoteStream);
}
if(remoteStream.stop) {
remoteStream.stop();
}
remoteStream.onended = null;
remoteStream = null;
}
if (remoteElement) {
remoteElement.onerror = null;
remoteElement.pause();
remoteElement.src = undefined;
remoteElement = null;
}
if (peerConnection) {
peerConnection.close();
peerConnection = null;
}
I've tried with and without the removeStream() call, I've tried with and without the stop() call, I've tried the element.src="" and element.src=null, I'm running out of ideas. Anyone know if this is a bug or user/my error in the use of the API?
EDIT: I set my default device (using Windows) to a camera that has a light when it's in use, and upon stopping, the camera light goes off, so perhaps this is a Chrome bug. I also discovered that if I use chrome://settings/content to change the microphone device to anything other than "Default", Chrome audio fails altogether. And finally, I realized that using element.src=undefined resulted in Chrome attempting to load a resource and throwing a 404 so that's clearly not correct... so back to element.src='' on that.
Ended up being my fault (yes, shocking). Turns out I wasn't saving localStream correctly in the onUserMediaSuccess callback of getUserMedia... once that was set, Chrome is turning off the blinking recording icon. That didn't explain the other anomalies, but it closes the main point of the question.
I just got this working yesterday after trawling through the WebRTC specification. I don't know if this is the "right" way to do it, but I found that renegotiating the PeerConnection with a new offer after removing the stream did the trick.
var pc = peerConnections[socketId];
pc.removeStream(stream);
pc.createOffer( function(session_description) {
pc.setLocalDescription(session_description);
_socket.send(JSON.stringify({
"eventName": "send_offer",
"data":{
"socketId": socketId,
"sdp": session_description
}
}));
},
function(error) {},
defaultConstraints);

Jquery - how to load everything except the images?

I'm currently working on a WordPress addition which loads full post content (normally it shows exceprts) when asked to. I did my code like this:
$(".readMore").click(function() {
var url = $(this).attr("href");
$(this).parent("p").parent("div").children("div.text").slideUp("slow", function () {
$(this).load(url + " .text", function(){
$(this).slideDown("slow");
});
});
$(this).parent("p").fadeOut();
return false; });
And it works. But I don't want images to be loaded. I tried .text:not(img), but it didn't worked. How can I do this?
The trick, of course, is preventing the images from being downloaded unnecessarily by the user's browser; not displaying them is easy.
I only have two browsers were it's easy and convenient to tell what's downloading: Chrome and Firefox+Firebug. In my tests, Martin's solution using *:not(img) results in the images being downloaded (although not displayed) in both Chrome and Firefox+Firebug. (I emphasize "Firefox+Firebug" because Firebug can change the behavior of Firefox on occasion, and so it may well be changing its behavior here, although I don't think it is; more on that below.)
It took some tweaking, but this seems to do the trick (more on testing below):
$.ajax({
url: url,
success: function(data) {
var div = $("<div>").html(data);
if (stripImages) {
// Find the images, remove them, and explicitly
// clear the `src` property from each of them
div.find("img").remove().each(function() {
this.src = "";
});
}
$(targetSelector).append(div.children());
},
error: function(jxhr, status, err) {
display("ajax error, status = " + status + ", err = " + err);
}
});
Live example The "Include big image" checkbox includes a large file from NASA's Astronomy Picture of the Day (APOD).
The key there was setting the src of the img elements to "". On Chrome, just removing the elements was enough to prevent Chrome starting the download of the images, but on Firefox+Firebug it not only started downloading them, but continued even when the download took considerable time. Clearing the src causes Firefox to abort the download (I can see this in the Firebug Net console).
So what about IE? Or Firefox without Firebug? I only did unscientific testing of those, but it's promising: If I run my live example of Martin's solution on either IE or Firefox without Firebug in a VM, I see the VM's network interface working hard, suggesting that it's downloading that big APOD picture. In contrast, if I run my solution above in that same environment (with caches cleared, etc., etc.), I don't see the VM network interface doing that work, suggesting that the download is either not being started or is being aborted early on.
.text *:not(img) will select every descendant from .text that is not an image, so in theory it should work.

Categories

Resources