I have multiple videos and want to get an event from all of them. But I get only the event from one of them (tested in Chrome). Why?
HTML:
<video id="video1" preload="auto" src="video1.ogg"></video>
<video id="video2" preload="auto" src="video2.ogg"></video>
JS:
$('video').on('canplay', function(){
console.log($(this).attr('id'));
});
jsFiddle
EDIT:
Ok.. it is really strange. On the very first load I get sometimes both events. But after that on every reload I get just an event from one of them!? Here a screenshot of my console:
The problem is that the 'canplay' event has already fired by the time you register it. I believe this is because jsFiddle wraps your code inside of $(window).load(.... If you were to move the script into the html, like on this example, it should work.
Most of the time, if you know for sure that your script is going to run synchronously right after the video element is created with a src, you can assume that none of those events have been fired. But, just to be safe, and especially when you don't know how your code will be used, I recommend something like this:
function handleCanplay(video) {
console.log($(video).attr('id'));
};
$('video').each(function () {
//first, check if we missed the 'canplay' event
if (this.readyState >= this.HAVE_FUTURE_DATA) {
//yup, we missed it, so run this immediately.
handleCanplay(this);
} else {
//no, we didn't miss it, so listen for it
$(this).on('canplay', function () {
handleCanplay(this);
});
}
});
Working example here.
Related
I am trying to view a video stream from an IP camera in a web page, when the stream can be played I want it to start automatically. Trying to do that with a timer, try to play and if that fails, try again.
The timer (timeout) doesn't seem to do that, however if I execute the script using a button, it does. What am I missing?
see the code below.
thanks,
Ron
PS: I commented out the setTimeout functions, to make the button work.
<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">
function playVid() {
var videoElem = document.getElementById("IPcamerastream");
var playPromise = videoElem.play();
// In browsers that don’t yet support this functionality playPromise won’t be defined.
if (playPromise !== undefined) {
playPromise.then(function() {
// Automatic playback started!
videoElem.controls = true;
}).catch(function(error) {
// Automatic playback failed.
// setTimeout(playVid, 1000);
});
}
}
//setTimeout(playVid, 1000);
</script>
<button onclick="playVid()" type="button">Play Video</button><BR>
<video id="IPcamerastream" src="http://192.168.2.8:8080" width="960" height="540"></video>
</body>
</html>
Look into the features of the video html5 tag:(https://www.w3schools.com/tags/tag_video.asp)
one of the optional attributes is autoplay (Specifies that the video will start playing as soon as it is ready) so there is no need to set timeout.
<video id="IPcamerastream" src="http://192.168.2.8:8080" width="960" height="540" autoplay></video>
Move your script below the video element, and you should not need the timeout at all, because the element will already be initialized when the script is executed. So document.getElementById should resolve the element right away.
Using timers will introduce race conditions. If anything, you should add a listener to the DOMContentLoaded event.
Welcome Ron,
This is a well formatted question, but target browser info could also assist in helping you resolve your issue. Please consider adding it in future!
As for your problem, you tell us that you wish the video to autoplay, I'm assuming on page load?
I've also removed the duplicate source paste.
In this case, you only call playVid() from within the promise erroring out. The initial call is bound to the button click event.
In short, only clicking the button will initiate the playVid() function.
You need to add an event listener for DOM readiness and call playVid() within that. Otherwise, it's only being called when you click your button!
document.addEventListener('DOMContentLoaded', (event) => {
//the event occurred
playVid();
});
You can also use the autoplay HTML option in the video tag.
lang-html
<video {...} autoplay />
I had an almost similar problem ، when I received the video stream in a webrtc project, the video would not be displayed without clicking a button.
if you want to play automatically received stream video, you should add "muted" in the video tag.
I am trying to end a video when a user clicks a skip button allowing a user to skip the video.
I have been using the following, which is all good, and allows me to trigger an action when the video ends.
HTML
<video autoplay>
<source src="video.mp4" type="video/mp4">
</video>
<button class="skip">Skip video</button>
JS
$('video').on('ended',function(){....
//do stuff here
}
however, I want to do something like the following, but not sure how to implement this.
$('.skip').click(function(){
$('video').end();
});
The end() method in jQuery using to get back to the previous selector.
Description from jQuery docs :
End the most recent filtering operation in the current chain and return the set of matched elements to its previous state.
To stop the video get dom object and then use HTMLMediaElement#pause method. Although finally trigger the ended event programmatically using trigger() method.
$('.skip').click(function(){
$('video').trigger('ended')[0].pause();
});
$('.skip').click(function(){
$('video')[0].load();
$('video')[0].pause();
});
Moving a video to the end of playback is not a straightforward operation as you need to first get the length of the video, then move to that point.
A much simpler alternative is to extract the logic that's invoked under ended and call it when the button is clicked too. Try this:
$('video').on('ended', function() {
videoEnded();
})
$('.skip').click(function() {
$('video')[0].pause();
videoEnded();
});
function videoEnded() {
// do stuff here
}
Working example
I have the following audio tag:
<audio preload>
<source src='/sounds/notify.ogg' type='audio/ogg'>
</audio>
I want to play it through js, so naturally I would expect calling $("audio").play() to do it (it's the only audio tag on the page), but I get an error stating play isn't defined. Upon inspecting it that is the case. The audio element has no play property. Every tutorial or resource I read says this is all you need to do, but... well, I just can't do it. Is my version of FF just broken or am I somehow missing something not stated in these various texts?
play() is a DOM method, not a jQuery method, which means that you'll need to get the actual DOM element before being able to get the play property. To get the actual DOM element, you can use the jQuery get() method:
$('audio').get(/*insert element index*/).play();
or simply use array indices:
$('audio')[/*insert element index*/].play();
And for even more choice, you can do something like this:
$('audio').eq(/*insert element index*/).prop('play')();
You could even do something like this to play each audio element:
$('audio').each(function () { this.play(); });
As Qantas mentioned play is not a jQuery method, but you can easily add it if desired as below:
$.fn.play = function() {
return this.each(function() {
this.play();
});
}
I am having a bit of an issue with checking to see if a video is being loaded in iPad. I need to check and see if loads because I am looping through to load all videos with an increment like video_1.mp4, video_2.mp4, video_3.mp4. However, it seems like it ignores the "readyState" and goes straight to the else statement.
Here is the code:
function loadMedia() {
var media = document.getElementsByTagName("video")[0];
if (media.readyState === 4) {
alert("Video has been loaded!");
} else {
alert("Video hasn't been loaded!");
}
}
Is readyState supported by iPad?
Edit: Added more code.
The loadMedia function is binded to window.onload via an anonymous function.
window.onload = (function () {
loadMedia();
});
Here is the HTML:
<video class="video" controls="controls" poster="images/posters/tb_1.jpg" preload="metadata">
<source src="media/tb_1.mp4" type="video/mp4; codecs='avc1.42E01E, mp4a.40.2'" />
We apologize, but your browser does not support this video. Please consider an upgrade.
</video>
Apple documentation seems to at least suggest that readyState for media elements has been around since iOS 3.0:
http://developer.apple.com/library/safari/#documentation/AudioVideo/Reference/HTMLMediaElementClassReference/HTMLMediaElement/HTMLMediaElement.html
That's sort of indirect documentation, perhaps, but it's something.
Since firing up a JS debugger on devices can be annoying, you might want to change this:
alert("Video hasn't been loaded!")
To this:
alert("Video hasn't been loaded! " + media.readyState);
If you turn on the console in the browser (and, if you like, switch to console.log() rather than alert()), this should tell you if your problem is that readyState is undefined (and therefore likely not supported) or if the problem is that maybe media is undefined (seems unlikely).
Of course, you may have also found a bug. You might want to search Apple's bug tracker, if they allow such things.
I'm currently using Video JS to serve video files, and the video source is changing depending on what item the visitor clicks. When my page loads I run the following code to bind the videoplayer object to a variable.
var videoPlayer = _V_("my_video_1");
This works perfectly in every browser except for IE7 and IE8. I've been debugging my code and it seems like it gets stuck on the ready event, which never fires. Although it does not leave any errors in the console. But any alerts or actions inside the ready function are ignored, and it's really at that point that the source is being modified. This is the code I use to change the source:
videoPlayer.ready(function(){
var myPlayer = this;
myPlayer.src([
{ type: "video/mp4", src: videoFile + ".mp4" },
{ type: "video/ogg", src: videoFile + ".ogv" }
]);
myPlayer.play();
myPlayer.volume(0.2);
$('div#videoViewer').show();
});
I've been using the same code on two other pages, and there have been no issues getting this to work. Now both myself and a colleague have been debugging this for hours but come nowhere closer to a solution.
Does anyone here have any ideas what could be causing the ready event to be ignored?
I've been trying to disable all other scripts in order to find the root of the issue but it has not been working.
I'm very thankful for any answers that could help me fix this.
I had the same problem. In my case, the ready event wouldn't fire in IE8 because I had a wrapper div that was set to display:none. If the wrapper was visible, the ready event would fire as expected. This problem did not occur in IE9.
I had the same problem, my solution was to directly pass the DOM element instead the id to videojs function.
//having this
<video id="VIDEO" ....>
//this fails
videojs('VIDEO').ready(...)
// this works!!
videojs(document.getElementById('VIDEO')).ready(...)
Hope it helps :D