HTML5 video onended event firing once - html

I am really stumped on this one.
I am trying to use the html5 video player and javascript in safari. I want to
1 play a greeting video
2 play a default looping video while the user makes a selection
3 play user selection
4 return to the default looping video.
1, 2, 3 work but 4 does not.
I call the greeting video from the body
<video id="videok" width=400 height=400 autoplay="autoplay" src="sacagreeting.mov" >
video not supported
</video>
I set my event listener up in the body
body onload="myAddListener()"
function myAddListener(){
var myVideo = document.getElementsByTagName('video')[0];
myVideo.addEventListener('ended',myNewSrc,false);
}
my function to play the looping default video is
function myNewSrc() {
myVideo = document.getElementsByTagName('video')[0];
myVideo.src="sacarest.mov";
myVideo.loop="loop";
myVideo.load();
myVideo.play();
}
I use an select element for the user to pick a video and the onchange event to call my video function
function myNewSrcii() {
myVideo = document.getElementById('videok');
myVideo.loop=""
myquest = document.getElementById('vidquest').value;
switch(myquest)
{
case "a":
myVideo.src="sacaa.mov";
break;
case "b":
myVideo.src="sacab.mov";
break;
case "c":
myVideo.src="sacac.mov";
break;
case "d":
myVideo.src="sacad.mov";
break;
case "e":
myVideo.src="sacae.mov";
break;
case "f":
myVideo.src="sacaf.mov";
}
myVideo.load();
myVideo.play();
}
I have tried dropping the looping attribute, setting the event listener again in the myNewSrcii function, using an onended event in the video tag and no luck. When I check the video event ended is true, the listener however never calls my default video function. Any help would be greatly apprectiated.
thanks

This is due to a strange bug in Safari's HTML5 video tag implementation. It can be reproduced on Safari for Windows as well. I've just found one workaround for this problem - just bind to loadedmetadata event and set the currentTime to some non-zero value. Here is an example:
<!doctype html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.0.min.js"></script>
</head>
<body>
<video id="video" width="500" height="400" controls autoplay></video>
<script>
var src = [
"http://content.adfox.ru/131007/adfox/205544/865991_11.mp4",
"http://all.rutube.ru/130627/gpmdigital/217059/805529_11.mp4"
];
var curSrc = 0;
$(function() {
$('#video').attr("src", src[curSrc % src.length]);
curSrc++;
var video = $('#video').get(0);
$('#video')
.on('loadedmetadata', function() {
video.currentTime=0.01;
video.play();
})
.on('ended', function() {
console.log('ended');
video.src = src[curSrc % src.length];
video.load();
curSrc++;
});
});
</script>
</body>
</html>
You can try this demo in this jsfiddle: http://jsfiddle.net/j2knz6sv/

Related

Angular 8 - Is there a way to bind to a video element to determine when it is loaded/starts playing?

Given:
<video poster="assets/videos/poster.png"
#videoPlayer
onloadedmetadata="this.muted = true">
<source src="assets/videos/video.mp4" type="video/mp4">
</video>
And in Angular:
...
public videoLoaded: boolean = false;
...
How can I bind videoLoaded to update once the video starts playing? (or is loaded) I've looked online and saw some older jquery implementations that seem to not be working in newer versions of chrome and want to know the latest way on how to accomplish this
Thanks
What you could do is make a reference to the video player itself with Angular's ViewChild and check if it's clicked.
#ViewChild('videoPlayer') videoPlayer: ElementRef;
videoClicked = false;
startVideo(): void {
this.videoClicked = true;
this.videoPlayer.nativeElement.play();
}
The startVideo() method will be used inside the HTML to trigger the change. The additional paragraph is used to see the change.
<video (click)="startVideo()" width="400"
#videoPlayer>
<source src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" type="video/mp4">
</video>
<p>Video clicked: {{videoClicked}}</p>
See this StackBlitz as an example of above behaviour.
Edit
A better way to do this is to use HTMLMediaElement's onplaying and loadeddata event. See MDN for documentation on onplaying and documentation on onplaying. In normal JavaScript it would look like this:
const video = document.querySelector('video');
video.onplaying = (event) => {
console.log('Video is no longer paused.');
};
In Angular, there are some small changes required. The HTML can stay pretty clean.
<video controls width="400"
#videoPlayer>
<source src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" type="video/mp4">
</video>
<p>Video loaded: {{dataLoaded}}</p>
<p>Video started: {{videoStarted}}</p>
The biggest changes are in the component, ngAfterViewInit checks if the element is there after view has been initialised. The loadeddata event is fired when the frame at the current playback position of the media has finished loading (so ready to play). Next to that, you can access the element's onplaying event to check if the video is not paused.
#ViewChild('videoPlayer') videoPlayer: ElementRef;
dataLoaded = false;
videoStarted = false;
ngAfterViewInit() {
this.videoPlayer.nativeElement.onloadeddata = (event) => {
console.log('Video data is loaded.');
this.dataLoaded = true;
};
this.videoPlayer.nativeElement.onplaying = (event) => {
console.log('Video is no longer paused.');
this.videoStarted = true;
};
}
Here's a StackBlitz example to show this example.
you can use HTML Audio/Video Events provided by html 5 video attribute.
loadeddata -> Fires when the browser has loaded the current frame of the audio/video
loadedmetadata -> Fires when the browser has loaded meta data for the audio/video
loadstart -> Fires when the browser starts looking for the audio/video

Html video should stop at first frame

I have a .mp4 video in my html page. I applied autoplay to that video, it stops at ending frame. My concern here is this video should come back at first frame once the video playing done. Can anybody please suggest what should i do to do this. Thanks
If you just want the video to loop and start again you can use the 'loop' attribute:
<video controls loop>
<source src="yourVideo.mp4" type="video/mp4">
...
</video>
If you want to detect the end of the video and do something else, like restart the video you can use the end of video event in JavaScript:
$("#yourVideo").on("ended", function() {
//Add whatever you want to do when the video ends here
video.pause();
video.currentTime = 0;
video.play(); //You may not need this - experiment on different browsers
video.pause();
});
Must include js file I am using CDN
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type='text/javascript'>
$(document).ready(function () {
document.getElementById('Sample').addEventListener('ended',myHandler,false);
function myHandler(e) {
var video =document.getElementById('Sample');
video.currentTime = 0;
video.pause();
}
});
</script>
HTML
<video src="video.mp4" id="Sample" autoplay>
video not supported
</video>
By javascript and assuming that you know the framerate of your video:
function goFirstFrame () {
var video = document.getElementById('videoId');
var frameTime = 1/25; // If your video is 25fps
video.currentTime = 0 + frameTime;
video.pause();
}

Hide Video Controls Until User Hover Over Video

i'm trying to hide the video controls on my video, until the user hover over the video, then the controls shows up. Any idea or advice? Thanks. And I've got more than one video.
HTML:
<div class="item spoon burger"><video width="300" height="auto" controls><source src="videos/sruthi.mp4" type="video/mp4"></video></div>
We can accomplish this through just a couple lines of jQuery, making use of .hover():
Working Example
$('#myvideo').hover(function toggleControls() {
if (video.hasAttribute("controls")) {
video.removeAttribute("controls")
} else {
video.setAttribute("controls", "controls")
}
})
Edit I mistakenly left the variable video in the code above. I changed it to this so that you won't have to manage variables that grab an ID.
$('#myvideo').hover(function toggleControls() {
if (this.hasAttribute("controls")) {
this.removeAttribute("controls")
} else {
this.setAttribute("controls", "controls")
}
})
HTML
<video width="300" height="auto" id="myvideo">
<source src="#" type="video/mp4" />
</video>
Update:
You mentioned that you have several videos. So you can use this same logic, and just add additional selectors into $( ). Here's an example:
$('#yourID1, #yourID2, #yourID3').hover(function toggleControls() { ...
Doing that will listen or wait until it detects that you're hovering over one of those IDs.
Updated fiddle
One issue with #EnigmaRM's answer is that if jQuery somehow misses a hover event, the controls can be toggled the "wrong" way - that is, they disappear on mouse enter and reappear on mouse leave.
Instead, we can ensure that the controls always appear and disappear correctly with event.type:
$("#myvideo").hover(function(event) {
if(event.type === "mouseenter") {
$(this).attr("controls", "");
} else if(event.type === "mouseleave") {
$(this).removeAttr("controls");
}
});
Untested, but I believe this would work. It uses JavaScript instead of CSS.
<div class="item spoon burger"><video id="videoElement" width="300" height="auto"><source src="videos/sruthi.mp4" type="video/mp4"></video></div>
<script type="text/javascript">
(function(window) {
function setupVideo()
{
var v = document.getElementById('videoElement');
v.addEventListener('mouseover', function() { this.controls = true; }, false);
v.addEventListener('mouseout', function() { this.controls = false; }, false);
}
window.addEventListener('load', setupVideo, false);
})(window);
</script>
<script>
function setupVideos() {
for (const video of document.querySelectorAll('video')) {
video.controls = false
video.addEventListener('mouseover', () => { video.controls = 'controls' })
video.addEventListener('mouseout', () => { video.controls = false })
}
}
window.addEventListener('load', setupVideos, false)
</script>
Using the code below, you don't need a separate javascript section (if that is a concern, which is the case sometimes). Just simply use onmouseover="this.play();this.setAttribute('controls','controls')" and onmouseout="this.load();this.removeAttribute('controls')"
If you don't want it to reset to a poster image, then you can get rid of the this.load.
<div class="img_placeholder">
<video width="350" height="250" loop preload="none" poster="../assets/icon-32.png" onmouseover="this.play();this.setAttribute('controls','controls')" onmouseout="this.load();this.removeAttribute('controls')">
<source src="../assets/bear.mp4" type="video/mp4" />
Your browser does not support the video tag.
</video>
</div>
A previous post explained how to do it this way HTML5 video - show/hide controls programmatically
<video id="myvideo">
<source src="path/to/movie.mp4" />
</video>
<p onclick="toggleControls();">Toggle</p>
<script>
var video = document.getElementById("myvideo");
function toggleControls() {
if (video.hasAttribute("controls")) {
video.removeAttribute("controls")
} else {
video.setAttribute("controls","controls")
}
}
</script>
Check if their solution works for you! Please +1 them if so!

To run a flv file without loop

I am new to run a .flv file. I used a tutorial for this. The link of the tutorialhttp://www.fieg.nl/embed-html5-video-with-flash-fallback#file-index.html
Here the video file is repeating time to time. I think it is in a loop. How can the video file run once when open the window. The code for run the flv file is below.
<script type="text/javascript">
jQuery(document).ready(function() {
var v = document.createElement("video"); // Check if the browser supports the video tag
if ( !v.play ) { // If no, use Flash.
var params = {
allowfullscreen: "false",
allowscriptaccess: "always",
wmode: "transparent"
};
var flashvars = {
src: "demo.flv"
};
swfobject.embedSWF("http://localhost/TantraProjects/Ranjit/html5/demo_flv.SWF", "demo-video-flash", "270", "296", "9.0.0", "http://localhost/TantraProjects/Ranjit/html5/expressInstall.swf", flashvars, params);
}
else {
// fix for firefox not looping
var myVideo = document.getElementById('demo-video');
if ((typeof myVideo.loop == 'boolean')) { // loop supported
myVideo.addEventListener('ended', function () {
this.currentTime = 0;
this.play();
}, false);
}
}
});
</script>
Please help me to know more about it.
Hi i have got the same thing for the video. There is a loop in the video and i dont want to looping the video.My html for the code.
<div id="demo-video-flash"><!-- wrapped in a div for the flash fallback -->
<video id="demo-video" height="155" width="270" autoplay loop>
<source src="http://localhost/TantraProjects/Ranjit/html5/demo.mp4" type="video/mp4" /> <!-- MPEG4 for Safari -->
<source src="http://localhost/TantraProjects/Ranjit/html5/demo.ogv" type="video/ogg" /> <!-- Ogg Theora for Firefox 3.1b2 -->
<!-- this is the image fallback in case flash is not support either -->
<img src="http://localhost/TantraProjects/Ranjit/html5/demoo.png"/>
</video>
</div>
It looks like you are using JW Player, correct? Then you should add repeat: none to the flashvars so it would look something like this.
var flashvars = {
src: "demo.flv",
repeat: "none"
};
More details on the 'flashvars' params over here.

Audio continues after removing <video> element in Chrome

I am having issues with video support in Chrome. My web page must run in Chrome and I am using the following code to check periodically if the web page has to play a video or not... but the problem is that after I remove the element, I still hear the audio and when I recreate the eleemnt, the audio of the new video and the old overlaps.
function showVideo() {
var video = videodata;
var videobox = $('#videobox').first();
var videoplayer = $('#videoplayer').first();
if (video.Enabled) {
if ((videoplayer.length > 0 && videoplayer[0].currentSrc != video.Location) || videoplayer.length == 0) {
videobox.empty();
videobox.append('<video id="videoplayer" preload="auto" src="' + video.Location + '" width="100%" height="100%" autoplay="autoplay" loop="loop" />');
videobox.show();
}
} else {
videobox.hide();
videobox.empty(); // Clear any children.
}
}
How can I solve?
Thank you.
The following was the minimum I had to go to get this to work. I was actually experiencing a stall due to the buffering while spawning ajax requests when the user pressed the back button. Pausing the video in Chrome and the Android browser kept it buffering. The non-async ajax request would get stuck waiting for the buffering to finish, which it never would.
Binding this to the beforepagehide event fixed it.
$("#SOME_JQM_PAGE").live("pagebeforehide", function(event)
{
$("video").each(function ()
{
logger.debug("PAUSE VIDEO");
this.pause();
this.src = "";
});
});
This will clear every video tag on the page.
firsly try to create "video" tag empty in the html and create "source" tag into javascript code
<html>
.
.
<video id="main-video" autoplay=""></video>
.
.
</html>
<script>
$('#main-video').append('<source type="video/mp4" src="URL.mp4">');
</script>
In my case, I had to pause the video first before removing it otherwise the audio is still playing in the background. The reason I used pause is because there is no stop() function on html5 video element.
} else {
videobox.hide();
// you can add something like this
$("#videoplayer").pause();
videobox.empty(); // Clear any children.
}
try (based on SimpleCode's answer):
function showVideo() {
var video = videodata;
var videobox = $('#videobox').first();
var videoplayer = $('#videoplayer').first();
if (video.Enabled) {
if ((videoplayer.length > 0 && videoplayer[0].currentSrc != video.Location) || videoplayer.length == 0) {
videobox.empty();
videobox.append('<video id="videoplayer" preload="auto" src="' + video.Location + '" width="100%" height="100%" loop="loop" />');
videobox.show();
document.getElementById("videoplayer").play();
}
} else {
document.getElementById("videoplayer").pause();
videobox.hide();
videobox.empty(); // Clear any children.
}
}