How can I get a video to only loop once - html

How can I get an html5 video to loop only once?
I'm using the html video tag and my video lasts for ten seconds.
I need 20 seconds of video playback.

You could set the autoplay to true and then call play() on the element when it reaches the end. Perhaps not the best approach but I think it should work, this example is using jQuery:
$(document).ready(function() {
// set this variable to the number of times you like to loop the video
var loop = 1;
// this event will be invoked when the media has reached the end
$('#video').on('ended', function() {
// check if we should replay the media
if(loop--) {
// replay the video
this.play();
}
});
});
The markup should be something like this:
<video src="test.ogg" id="video" autoplay></video>

Related

How to detect when HTML5 video is played the first frame?

I ask this because I would like to show a overlay image on exact play time like on 3:00.
Therefore, I binded the "play" event and state setTimeout(...,18000) to show the image.
However, it seems the setTimeout is done too early. The image is shown faster than expected. I can unterstand as the "play" event is fired BEFORE the video is prepared.
So I also tried to bind "loadeddata" and "playing" event. But this time, the image is shown slower than expected.
Also, the image seems to show in "random manner" (not always show on the same time with a few tests, a little bit different).
Is there a event that I can use setTimeout to show image on exact time? Or in simple, how can I show an image on video exact time?
There is another way to do this using currentTime and defining a function for everytime the time for the video changes. Set a div on top of HTML5 video element and modify that element when currentTime is between 3 and 4 seconds.
Sample code would look like this:
HTML:
<div id="wrap_video">
<div id="video_box">
<div id="video_overlays"></div>
<div>
<video id="myVideo" width="320" height="176" controls autoplay>
<source src="https://www.w3schools.com/tags/mov_bbb.mp4" type="video/mp4">
Your browser does not support HTML5 video.
</video>
</div>
</div>
</div>
CSS:
#video_box{
position:relative;
}
#video_overlays {
position:absolute;
width:160px;
min-height:100px;
background:transparent;
z-index:300000;
bottom:50px;
left:10px;
text-align:center;
}
JavaScript:
var vid = document.getElementById("myVideo");
// Assign an ontimeupdate event to the video element, and execute a function if the current playback position has changed
vid.ontimeupdate = function() {myFunction()};
function myFunction() {
//if currentTime is greater than 3 but less than 4, as in second 3+, go into if statement, otherwise go to else statement
if (vid.currentTime > 3 && vid.currentTime < 4) {
document.getElementById("video_overlays").innerHTML = '<p>Image Here</p>';
}
else {
document.getElementById("video_overlays").innerHTML = '';
}
}
You can inside the first if statement pause the video and then show an image and then make the video start again after a certain timeout, if that was your intention but this code is essentially the skeleton to do something like that.
Working sample: http://jsfiddle.net/l33tstealth/wgcbcf1t/10/
The loadeddata event is fired when the frame at the current playback position of the media has finished loading; often the first frame.
First frame is:
const video = document.querySelector('video');
video.addEventListener('loadeddata', (event) => {
console.log('Yay! The readyState just increased to ' +
'HAVE_CURRENT_DATA or greater for the first time.');
});
You can relay on timeUpdate and get the current time in the event:
event?.detail?.target?.currentTime

How can I determine if standard audio player is playing a song

I have the following as part of my html (once for each of several songs):
<audio
name="aMedia"
id="aMedia"
controls
preload="auto">
<source src="audio/mysong.m4a">
</audio>
I wish to determine if the above standard Play button was pressed to play a song. If it was, I need to first stop all other songs that may be playing, e.g.,
function stopAllSongs()
{
var allMedia = document.getElementsByName(theMedia), thisMedia;
for (m=0; m < allMedia.length; m++)
{
thisMedia = allMedia[m];
if (thisMedia.isPlaying())
thisMedia.pause();
}
}
I have seen successful uses of <input ...> to do what I wish; but I would like to avoid that if possible.
Any ideas?
You could use the play event for this, then iterate through all other audio elements and invoke pause on them.
You can use a common handler for all the audio elements, the this object will represent the actual audio element triggering the event (which in turn of course can be used to set a CSS class etc.).
pause() can be called even if the audio is already paused so we don't need to do additional checks for it. We just loop through the array of elements and skip the element that triggered the event.
Example
var audioElements = document.querySelectorAll("audio"), i;
// bind common handler for each audio element in page:
for(i = 0; i < audioElements.length; i++)
audioElements[i].addEventListener("play", playHandler);
// common handler
function playHandler() {
// this = element triggering the event
// pause all but ours (reusing previous audioElements NodeList collection here)
for(var i = 0; i < audioElements.length; i++)
if (this !== audioElements[i]) audioElements[i].pause();
}
<i>Preload time may vary, be patient... (due to links IE will not be able to play these)</i><br>Starting one will stop all others<br>
<audio preload="auto" controls src="https://github.com/epistemex/free-music-for-test-and-demo/blob/master/music/kf_feelme.mp3?raw=true"></audio><br>
<audio preload="auto" controls src="https://github.com/epistemex/free-music-for-test-and-demo/blob/master/music/kf_colibris.mp3?raw=true"></audio><br>
<audio preload="auto" controls src="https://github.com/epistemex/free-music-for-test-and-demo/blob/master/music/kf_limitless.mp3?raw=true"></audio><br>
<audio preload="auto" controls src="https://github.com/epistemex/free-music-for-test-and-demo/blob/master/music/kf_thebattle.mp3?raw=true"></audio>

Mission : Create a connection with a list of videos and a canvas make them plays 1 by 1, without stops, no click function, ended AddEventListener

I would like to make a video playlist, (Source video is copied in a canvas to block controls,
options like download video), i made 2 Drag and Drop lists and i would like to connect 1 drag n Drop list to the canvas (that is also the video player box) then play the videos 1 by 1,
witout stops, no click function, function AddEventListener ended in the canvas box.
I worth for 2 videos, here is some parts of the code :
<script type="text/javascript">
// listener function changes src
function myNewSrc() {
var myVideo = document.getElementsByTagName('video')[0];
myVideo.src = "videos/80s_Mix_II-700.mp4";
myVideo.src = "videos/80s_Mix_II-700.webm";
myVideo.load();
myVideo.play();
}
// add a listener function to the ended event
function myAddListener() {
var myVideo = document.getElementsByTagName('video')[0];
myVideo.addEventListener('ended', myNewSrc, false);
}
</script>
<body onload="myAddListener()">
<div id="video_player_box">
<video id="video" autoplay autobuffer width="1" height="1" >
<source src="videos/milenio_6_minimix_700.mp4" type="video/mp4">
<source src="videos/milenio_6_minimix_700.webm" type="video/webm">
<source src="videos/milenio_6_minimix_700.ogg" type="video/ogg">
</video>
<div align="center">
<canvas id="myCanvas" width="1130" height="560">
Your browser does not support the HTML5 canvas tag.</canvas>
</div>
<script>
var v = document.getElementById("video");
var c = document.getElementById("myCanvas");
ctx = c.getContext('2d');
v.addEventListener('play', function() {
var i = window.setInterval(function()
{
ctx.drawImage(v, 5, 5, 1130, 560)
}, 20);
}, false);
v.addEventListener('pause', function() {
window.clearInterval(i);
}, false);
v.addEventListener('ended', function() {
clearInterval(i);
}, false);
</script>
</div>
<div id="cadre2" ondrop="drop(event)" ondragover="allowDrop(event)"> <p> Canal VIP </p>
<ol><li> <video src="videos/milenio_6_minimix_700.mp4" draggable="true"
ondragstart="drag(event)" id="drag1" width="288" height="188" alt="Video 1">
</video></li>
...
The idea is to say get the videos from #cadre2, play them, 1 by 1, in the canvas until the end and loop, make the same path.
I made my list Drag and drop to have the decision to modify online the video playlist, more flexible.
Hope to have some advises!! I'm not pro of Php and dynamic, i've started Javascript but
it takes time to be pro!
If you have some code, it will be really appreciated!! Thanks in advance!!!
In order to make a player that can play videos continously you need to implement some sort of double-buffering at load level (I'll demonstrate later).
But there are some issues in the code as it is -
myVideo.src = "videos/80s_Mix_II-700.mp4";
myVideo.src = "videos/80s_Mix_II-700.webm";
myVideo.load();
This will simply override the source property. And setting the source will automatically start loading the video.
The proper way to check for video support is using the method canPlayType like this:
/// which format can we play?
if (video.canPlayType("video/mp4").length > 0) {
video.src = urlToMP4;
} else if (video.canPlayType("video/webm").length > 0) {
video.src = urlToWEBM;
} else {
video.src = urlToOggOrSomeOtherSupportedFormat;
}
The problem though with canPlayType is that it returns maybe in Chrome and probably in Firefox. It returns an empty string if it cannot play the video type so we check if string contains anything to determine the possibility for this format to play.
You also need to implement an event listener for canplay which tells your app that the video was loaded and buffered successfully and can now be started using play (or starts if autoplay was set to true).
I would recommend a simple procedure like this:
Create an array of objects with the video URLs you want to play for the various formats
When first video is loaded (canplay) start loading the next video in the list when start playing the first
I would also recommend a re-factoring of the code to handle loading and playing.
For example, if we initialize an array to hold our custom video objects:
var list = [];
we can now add URLs like this:
function addVideo(urlMP4, url) {
list.push({
urlMP4: urlMP4,
url: url,
isReady: false
})
}
Then this function will let us add a MP4 and a link for WEBM or OGG:
addVideo('http://video1.mp4', 'http://video1.webm');
addVideo('http://video2.mp4', 'http://video2.webm');
addVideo('http://video3.mp4', 'http://video3.ogg');
...
Then we need to start a "chain-reaction" so to speak by using a double-buffered loading mechanism. The first time we need to trigger it manually:
getVideo(list[0], play);
function getVideo(vid, callback) {
/// which video is playing? (see demo for details)
var video = (isVideo1 === false ? video1 : video2),
me = this;
/// we need to know when video is ready
video.addEventListener('canplay', canPlay, false);;
/// call this when ready
function canPlay(e) {
/// remove event listener (in case setting new src does not trigger)
video.removeEventListener('canplay', canPlay, false);
/// update our object with useful data, for example:
vid.isReady = true;
/// if we provided a callback then call that with custom video object
if (typeof callback === 'function')
callback(vid);
}
/// check video format support (see demo for details)
if (video.canPlayType("video/mp4").length > 0) {
video.src = vid.urlMP4;
} else {
video.src = vid.url;
}
}
Our play function will manage which video is playing and what to play next:
function play(){
/// what video is currently not playing?
var video = (isVideo1 === false ? video1 : video2),
next = current; /// current is index for list, starts at 0
/// switch
isVideo1 = !isVideo1;
/// increment for next video to platy and start over if list ended
next++;
if (next > list.length - 1) next = 0;
/// only attempt next if there are more videos than 1 in list
if (list.length > 0) getVideo(list[next]);
/// start already loaded video (getVideo)
video.play();
isPlaying = true;
/// set current to next in list
current = next;
}
Here is an online demo
I made this demo just to demonstrate the double-buffered loading. Feel free to incorporate in your own project with pause, stop etc.
There is room to move things around in the code I provided here but it's as said just example of the principle. You also need to consider a scenario where next video takes longer to load then what current video playing takes to play (ie. current video ends before next has finished loading). This is not checked in this code.
In order to properly synchronize video frames with canvas you need to use requestAnimationFrame or you will get freezes from time to time.
In the demo the loop runs all the time. You can consider to implement a conditional to stop the loop. I just implemented a conditional for drawing when video list has started playing (rAF does not use much resources in it self and you may get problems synchronizing stop and start when you switch videos so I would personally leave it running as-is for this type of scenarios (continuous video play) and only stop it if there is an error occurring).

HTML5 audio - play sound repeatedly on click, regardless if previous iteration has finished

I'm building a game in which a wav file plays on click - in this case it's a gun sound "bang".
The problem is if I rapid click, it won't play the sound once for each click - it's as if the clicks are ignored while the sound is playing, and once the sound is finished, it starts listening for clicks again. The delay seems to be about one second long, so you figure if someone clicks 4 or 5 times per second, I want 5 bangs, not 1.
Here's my HTML:
<audio id="gun_sound" preload>
<source src="http://www.seancannon.com/_test/audio/gun_bang.wav" />
</audio>
Here's my JS:
$('#' + CANVAS_ID).bind(_click, function() {
document.getElementById('gun_sound').play();
adj_game_data(GAME_DATA_AMMO_ID, -1);
check_ammo();
});
Ideas?
I know it's a very late answer, I just wanted to , but seeking for a solution I found that in my case the best one was to preload the sound and then clone the node each time I want to play it, this allows me to play it even if the previous has not ended:
var sound = new Audio("click.mp3");
sound.preload = 'auto';
sound.load();
function playSound(volume) {
var click=sound.cloneNode();
click.volume=volume;
click.play();
}
Once the gun_bang.wav is preloaded, you can dynamically make new elements with that sound attached to it, play the audio, and then remove them when the audio has finished.
function gun_bang() {
var audio = document.createElement("audio");
audio.src = "http://www.seancannon.com/_test/audio/gun_bang.wav";
audio.addEventListener("ended", function() {
document.removeChild(this);
}, false);
audio.play();
}
$('#' + CANVAS_ID).bind(_click, function() {
gun_bang();
adj_game_data(GAME_DATA_AMMO_ID, -1);
check_ammo();
});
You can wrap the following with your own program-specific click logic, but the following demonstrates 3 gun sounds at the same time. If you want any kind of delay, you can introduce a minor sleep() function (many kludge hacks for this are easily found), or you can use setTimeout() to call subsequent ones.
<audio id="gun_sound" preload="preload">
<source src="http://www.seancannon.com/_test/audio/gun_bang.wav" />
</audio>
<script type="text/javascript">
jQuery(document).ready(function($){
$('#gun_sound').clone()[0].play();
$('#gun_sound').clone()[0].play();
$('#gun_sound').clone()[0].play();
});
</script>

How to do something after video finishes?

I have a 15 second video that's not embedded (it's sourced from an url). How can I get it to play the next frame when then video is finished?
If you are using the FLVPlayback component, you can do it like this:
// for clarification
var video:FLVPlayback = myVideoInstance;
video.source = "http://example.com/myvideo.flv";
video.autoPlay = true;
video.addEventListener(VideoEvent.COMPLETE, function(e:VideoEvent) {
// video has finished
});
See VideoEvent.COMPLETE which is dispatched when a video has finished playing.
video.addEventListener(VideoEvent.COMPLETE, _doNext);
function _doNext(e:VideoEvent):void
{
video.removeEventListener(VideoEvent.COMPLETE, _doNext);
trace("video done, what's next?");
}