Playing multiple fractions of HTML5 videos at a time - javascript

I am trying to write a function that will take an id of a div and play a given video from for example 2/10th of the way through to 3/10th of the way through and return an event so I can do something else.
I am not to clever with events as yet, and the video duration is not working out for me, any help appreciated. I have jQuery installed.
Some improvement since last time...
Updated, just need the listener to work next.
var finished_event = new Event('finished');
$(document).ready(function(){
class Player {
constructor(pos, vid, part, parts){
this.pos = pos;
this.vid = vid;
this.part = part;
this.parts = parts;
}
start(){
var it = this;
var html = '<video class="video-fit" controls>';
html += '<source src="';
html += it.vid;
html += '" type="video/mp4">';
html += '</video>';
$(it.pos).html(html);
var video = $(it.pos + ' video')[0];
video.addEventListener('loadeddata', function(){
var dur = video.duration;
var fra = dur / it.parts;
var beg = it.part * fra;
var end = it.part * (fra + 1);
video.currentTime = beg;
video.play();
video.addEventListener('timeupdate', function() {
if (video.currentTime >= end) {
video.pause();
this.dispatchEvent(finished_event);
}
}, false);
}, false);
return it;
}
}
$('body').click(function(){
let player_1 = new Player('#pos-1', 'videos/576p.mp4', 5, 10);
player_1.start();
let player_2 = new Player('#pos-2', 'videos/576p.mp4', 5, 10);
player_2.start();
let player_3 = new Player('#pos-3', 'videos/576p.mp4', 5, 10);
player_3.start();
let player_4 = new Player('#pos-4', 'videos/576p.mp4', 5, 10);
player_4.start();
//.addEventListener('finished', function(){ console.log('Finished'); }, false)
});
});

The timeupdate event fires a lot, so it could fire multiple times within the this.currentTime >= end check.
Not changing your code too much, you would want to set a playing state/var and on canplay event change timestamp and then play, this would, in turn, trigger a seeked event which then you can set the video as playing, then on timeupdate, check your timing plus is the video playing.. and for the last video you would need to check ended event as it won't enter into your check this.currentTime >= end as end is +1 second.
Then to separate the event functions from the Player class, id would use an array and watch it for changes, then by pushing a function to the array/stack you can then do a check within the function each time its invoked if the stack matches the video length, suppose you could do it other ways.
(function () {
let video =
'https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/twitter_cat.mp4';
let videos = [
{ id: '#pos-1', video, part: 1, parts: 10 },
{ id: '#pos-2', video, part: 2, parts: 10 },
{ id: '#pos-3', video, part: 3, parts: 10 },
{ id: '#pos-4', video, part: 4, parts: 10 },
];
const playqueue = [];
Object.defineProperty(playqueue, 'push', {
value: function (...args) {
var arr = Array.prototype.push.apply(this, args)
if (typeof args[0] === 'function') args[0]();
return arr;
}
});
function finished_event() {
if (playqueue.length === videos.length) {
console.log('Do something, all videos have stopped playing');
}
}
function video_finished_event(player) {
console.log(
'Do something, ' + JSON.stringify(player) + ' has stopped playing'
);
playqueue.push(finished_event);
}
class Player {
constructor(pos, vid, part, parts) {
this.pos = pos;
this.vid = vid;
this.part = part;
this.parts = parts;
}
start() {
var it = this;
var html = '<video class="video-fit" data-vid="' + it.pos + '" controls>';
html += '<source src="';
html += it.vid;
html += '" type="video/mp4">';
html += '</video>';
$(it.pos).html(html);
var video = $('[data-vid="' + it.pos + '"]')[0];
video.addEventListener(
'loadeddata',
function () {
var fra = video.duration / it.parts;
var beg = it.part * fra;
var end = it.part * (fra + 1);
video.addEventListener('canplay', function () {
if (!this.playing) {
this.currentTime = beg;
this.play();
}
});
video.addEventListener('seeked', function () {
this.playing = true;
});
video.addEventListener('timeupdate', function () {
if (this.playing && this.currentTime >= end) {
this.pause();
this.playing = false;
video_finished_event(it);
}
});
video.addEventListener('ended', function () {
if (this.playing) {
this.pause();
this.playing = false;
video_finished_event(it);
}
})
},
false
);
return it;
}
}
videos.forEach(video => {
video.player = new Player(video.id, video.video, video.part, video.parts);
video.player.start();
});
})();
.videos div {
display: inline-block;
width: calc(25vw - 15px);
height: 100%;
}
.videos div video {
width: 100%;
height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="videos">
<div id="pos-1"></div>
<div id="pos-2"></div>
<div id="pos-3"></div>
<div id="pos-4"></div>
</div>

I suggest you to put an unique id on video, here i choose vpos-1/2/3/4/...
and i display video from beg to end:
var html = '<video ' + 'id="v' + it.pos + '" class="video-fit">';
html += '<source src="';
html += it.vid;
html += '" type="video/mp4">';
html += '</video>';
$(it.pos).html(html);
var video = document.getElementById('v' + it.pos);
$(video).bind('timeupdate', function() {
if(video.currentTime > end){
video.pause();
}
});
$(video).on('play', function() {
video.playbackRate = 1.0;
//calcul the value of beg
video.currentTime = beg;
video.play();//suppress if you have autoplay
});
$(video).bind('ended', function() {
// nothing yet
});
if you want to autoplay and/or display controls i suggest you to add
controls="controls" autoplay
to tag video
if you want to remove video: just do src=''
It stops the video and it saves the memory

Related

how to make a video preview with canvas?

this is my first question here!
im trying to make a website that show videos that i make and i want my viewers can see a preview of video when they hover mouse on the a element or element .
i just do it but i have some problems and questions. lemme show you code example first and then i ask my questions.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="thumbs" style="width:216px;height:468px;border: 5px solid blue;background-color:red;"><canvas onmouseover="getid1(this);" onmouseout="getid2(this);" id="canvas1"></canvas></div>
<script>
var thumbsList = [];
var delay = 100;
var i = 0;
var video = document.createElement("video");
var a = 0;
var m = document.getElementById("canvas1");
var mtx = m.getContext("2d");
var generate = true;
var animstop = false;
var vidFrames = 64;
m.width = 216;
m.height = 468;
video.preload = "auto";
video.src = "aaaa.mp4";
function stranim(bb){
if(generate){
animstop = false;
video.currentTime = i;
generateVid();
generate = false;
}else{
animstop = false;
startAnim();
}
}
function stpanim(bb) {
clearTimeout();
animstop = true;
mtx.drawImage(thumbsList[0], 0, 0);
}
// if i replace this section with generateVid() the code is working
/*video.addEventListener('seeked', function() {
var d = (video.duration / vidFrames) * 2;
generateThumbnail();
i += video.duration / vidFrames;
if (i <= video.duration) {
video.currentTime = i;
generateVid()
if(d == i){
startAnim();
}
}
});*/
function generateVid() {
var d = (video.duration / vidFrames) * 2;
generateThumbnail();
i += video.duration / vidFrames;
if (i <= video.duration) {
video.currentTime = i;
generateVid();
if(d == i){
startAnim();
}
}
}
function generateFirstThumbnail() {
var c = document.createElement("canvas");
var ctx = c.getContext("2d");
c.width = 216;
c.height = 468;
ctx.drawImage(video, 0, 0, 216, 468);
thumbsList.push(c);
thumbs.appendChild(m);
mtx.drawImage(thumbsList[0], 0, 0);
i += video.duration / vidFrames;
}
function generateThumbnail() {
var c = document.createElement("canvas");
var ctx = c.getContext("2d");
c.width = 216;
c.height = 468;
ctx.drawImage(video, 0, 0, 216, 468);
thumbsList.push(c);
}
function startAnim() {
var currentFrame = 0;
function anim() {
if(currentFrame != (vidFrames - 1) && animstop == false){
currentFrame = (currentFrame + 1) % thumbsList.length;
mtx.drawImage(thumbsList[currentFrame], 0, 0);
setTimeout(anim, delay);
}
}
anim();
}
function getid1(obj) {
stranim(obj.id)
}
function getid2(obj) {
stpanim(obj.id)
}
window.onload = function(){
generateFirstThumbnail();
};
</script>
</body>
</html>
the questions are :
1- why my generatevid() function is not working? this function is just like that eventlistener.
2- i want to add this code on a class to use it on multiple videos but idk how and i think this cant be done with js classes.( i search so many sites for it)
3-i can use 2d arrays for saving my video previews but is it dont make my site lower on load speed or it dont fill the ram of user?
4-there is any way that i make this code better and easyer?(i dont want to use jquery for no reason).
For a pure js approach you can check this not mine btw: https://codepen.io/tepexic/pen/BazYgJe
html:
<input type="file" accept="video/*" id="input-tag"/>
<hr>
<video controls id="video-tag">
<source id="video-source" src="splashVideo">
Your browser does not support the video tag.
</video>
JS
const videoSrc = document.querySelector("#video-source");
const videoTag = document.querySelector("#video-tag");
const inputTag = document.querySelector("#input-tag");
inputTag.addEventListener('change', readVideo)
function readVideo(event) {
console.log(event.target.files)
if (event.target.files && event.target.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
console.log('loaded')
videoSrc.src = e.target.result
videoTag.load()
}.bind(this)
reader.readAsDataURL(event.target.files[0]);
}
}
But for other approach i would probably use http://ffmpeg.org/ library to generate a preview video (e.g 10 seconds video) and https://videojs.com library for video player so you have a control when user hover the player.
I just did some test on your code, your video is getting seeked only once. No event is raised after that, which means your thumbnail will remain same.
Here is how I was able to fix it
function generateVid() {
var d = (video.duration / vidFrames) * 2;
generateThumbnail();
i += video.duration / vidFrames;
if (i <= video.duration) {
video.currentTime = i;
console.log("starting seeking");
if(d == i){
startAnim();
}
}
}
video.onseeked = (event) => {
if (animstop == false)
{
setTimeout(generateVid, delay);
}
console.log("seeked");
};

play video in loop using setTimeout

I want to play videos in a loop. For some reason I don't want change video src on ended event.
So I created video elements for each video in a loop. Also I have video src and durations in array.
here is my idea:
Only current playing video tag can be visible. Others will be hided.
Instead of using ended event, I want to use setTimeout function. Video's duration will be delay parameter.
But they all play together. I couldn't make them play in order.
Here is what I done so far:
videoArray = [
{"video":video1.mp4, "duration": 5},
{"video":video2.mp4, "duration": 7},
{"video":video3.mp4, "duration": 9},
{"video":video4.mp4, "duration": 10},
]
for (var j = 0; j < videoArray.length; j++){
var video = document.createElement("video");
video.src=videoArray[j];
video.id="video-"+j;
video.preload = "metadata";
video.type="video/mp4";
video.autoplay = true;
video.style.display="none";
document.body.appendChild(video);
}
for (var count = 0; count < videoArray.length; count++) {
(function(num){
setTimeout(function() {
videoArray[num].video.style.display="block";
videoArray[num].video.play();
}, 1000 * videoArray[num].duration);
videoArray[num].video.style.display="none";
})(count);
}
Disclaimer
I know that the question was asked without the ended event, but I do not think that set time out is the way to go.
Think of the scenario where you have video buffering, or slowing down for any reason, your setTimeout will be out of sync.
At the bottom I've added another solution that answers the requirement of not using the ended event, but again, I do not recommend using it.
Solution
The idea is to have an event listener to the end of the video, in that case, even if you run the video on a different speed you are still going to run the next video regardless of the duration.
Another benefit is that you do not need to know the duration of the videos in the first place.
PS.
the event listener that you need to listen to is video.addEventListener("ended", callback);
You are more than welcome to run the code or to have a look at a working example I've created for you
Working Example
const videoUrls = [
'https://videos-play-loop.netlify.com/video1.mp4',
'https://videos-play-loop.netlify.com//video2.mp4',
'https://videos-play-loop.netlify.com//video3.mp4',
];
const createVideo = ({id, src, width, cls = 'video', display = 'block', playbackRate = 1, muted = true, type = 'video/mp4', autoplay = false, controls = true}) => {
const videoElement = document.createElement("video");
videoElement.id = id;
videoElement.src = src;
videoElement.classList.add(src);
videoElement.type = type;
videoElement.autoplay = autoplay;
videoElement.controls = controls;
videoElement.style.display = display;
videoElement.muted = muted;
videoElement.playbackRate = playbackRate;
return videoElement;
};
const addVideos = (container, videoUrls) => {
const videos = videoUrls.map((url, index) => {
const first = index === 0;
const display = first ? 'block' : 'none';
return createVideo({id: `video-${index}`, src: url,display, width: 640, autoplay: first, playbackRate: 3});
});
videos.forEach((video, index) => {
const last = index === videos.length - 1;
const playNext = (element) => {
element.target.style.display = "none";
const nextElementIndex = last ? 0 : index + 1;
const nextElement = videos[nextElementIndex];
nextElement.autoplay = true;
nextElement.style.display="block";
nextElement.load();
};
video.addEventListener("ended", playNext);
container.appendChild(video)
});
};
const videoWrapper = document.getElementById('video-wrapper');
addVideos(videoWrapper, videoUrls);
#video-wrapper video {
max-width: 600px;
}
<div id="video-wrapper"></div>
Working solution with setTimeout (please use the solution above)
const videoUrls = [{
url: `https://videos-play-loop.netlify.com/video3.mp4`,
duration: 3,
},
{
url: `https://videos-play-loop.netlify.com/video2.mp4`,
duration: 4
},
{
url: `https://videos-play-loop.netlify.com/video1.mp4`,
duration: 5
}
];
const createVideo = ({
id,
src,
width,
cls = 'video',
display = 'block',
duration,
playbackRate = 1,
muted = true,
type = 'video/mp4',
autoplay = false,
controls = true
}) => {
const videoElement = document.createElement("video");
videoElement.id = id;
videoElement.src = src;
videoElement.classList.add(src);
videoElement.type = type;
videoElement.autoplay = autoplay;
videoElement.controls = controls;
videoElement.style.display = display;
videoElement.muted = muted;
videoElement.playbackRate = playbackRate;
videoElement.setAttribute('data-duration', duration);
return videoElement;
};
const playNext = (videos, index) => {
const current = videos[index];
const activeVideoDuration = parseInt(current.dataset.duration) * 1000;
setTimeout(() => {
const last = index === videos.length - 1;
current.style.display = "none";
current.pause();
const activeVideoIndex = last ? 0 : index + 1;
const next = videos[activeVideoIndex];
next.autoplay = true;
next.style.display = "block";
next.load();
next.play();
playNext(videos, activeVideoIndex);
}, activeVideoDuration);
};
const addVideos = (container, videoUrls) => {
const videos = videoUrls.map((video, index) => {
const {
url,
duration
} = video;
const first = index === 0;
const display = first ? 'block' : 'none';
return createVideo({
id: `video-${index}`,
src: url,
duration,
display,
width: 640,
autoplay: first,
});
});
videos.forEach(video => container.appendChild(video));
playNext(videos, 0);
};
const videoWrapper = document.getElementById('video-wrapper');
addVideos(videoWrapper, videoUrls);
#video-wrapper video {
max-width: 600px;
}
<div id="video-wrapper"></div>
You could hold the duration of the videos in a variable and the accumulate this variable with the previous video duration and set this a the setTimeOut duration.
Note that the time of the videos is in seconds. And for the first video to play user has to interact otherwise the video will not play.
Working Example:
function startVideos(event) {
event.target.style.display= "none";
(function() {
videoArray = [
{
video:
"http://techslides.com/demos/sample-videos/small.mp4",
duration: 5
},
{
video:
"http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4",
duration: 60
},
{
video:
"https://mobamotion.mobatek.net/samples/sample-mp4-video.mp4",
duration: 120
},
{
video:
"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
duration: 600
}
];
let videArrayElem = [];
for (var j = 0; j < videoArray.length; j++) {
var video = document.createElement("video");
video.src = videoArray[j].video;
video.id = "video-" + j;
video.preload = "metadata";
video.type = "video/mp4";
video.autoplay = false;
video.controls= true;
video.style.display = "none";
videArrayElem.push(video);
document.body.appendChild(video);
}
let prviousVideoDuration = 0;
for (var count = 0; count < videoArray.length; count++) {
(function(num) {
setTimeout(function() {
videArrayElem[num].style.display = "block";
videArrayElem[num].play();
}, prviousVideoDuration);
prviousVideoDuration += 1000 * videoArray[num].duration;
videArrayElem[num].style.display = "none";
})(count);
}
})();
}
video {
height: 100px;
width: 100px;
display: inline-block;
margin: 4px;
float: left;
}
<button type="button" onclick="startVideos(event)">Start Video Demo</button>
Aside from the facts that you are trying to achieve something strange, and that your code example will not compile. As I see it, you've got it.
The only missing thing is pause() and display = "none". With minimum edits you have what you need.
const videoArray = [
{"video":"video1.mp4", "duration": 5}, // of cause you need ""
{"video":"video2.mp4", "duration": 7},
{"video":"video3.mp4", "duration": 9},
{"video":"video4.mp4", "duration": 10},
]
for (let j = 0; j < videoArray.length; j++){
const video = document.createElement("video");
// you need to save DOM nodes somewhere to use them in the second loop
videoArray[j].video_el = video
video.src=videoArray[j].video; // `.video` is added
video.id="video-"+j;
video.preload = "metadata";
video.type="video/mp4";
video.autoplay = true;
video.style.display="none";
document.body.appendChild(video);
}
for (var count = 0; count < videoArray.length; count++) {
(function(num){
setTimeout(function() {
// add this to hide previous video node and stop video from playing
if( num ) {
videoArray[num-1].video_el.style.display="none";
videoArray[num-1].video_el.pause()
}
// videoArray[num].video - is a string, not a DOM node
// so, you need to change this:
// videoArray[num].video.style.display="block";
// for this:
videoArray[num].video_el.style.display="block";
// no need. `autoplay` is set to `true` in the first loop
// videoArray[num].video_el.play();
}, 1000 * videoArray[num].duration);
// no need. already done in the first loop
// videoArray[num].video_el.style.display="none";
})(count);
}
But there is a lot of flaws:
setTimeout does not care about network delays and other time related issues, so most probably your video sequence will not play seamlessly.
Because of the first flow and because I doubt that duration values are exact you should use pause().
As #IslamElshobokshy noted in comments to your question using play/pause is not so simple.
If user opens the page and does nothing more, you'll get:
Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first.
in Chrome. And
Autoplay is only allowed when approved by the user, the site is activated by the user, or media is muted.
NotAllowedError: The play method is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.
in Firefox.
So you'd probably be better off with the ended event after all, and with muted attribute (to mitigate the last issue):
for (let j = 0; j < videoArray.length; j++){
const video = document.createElement("video")
videoArray[j].video_el = video
video.src = videoArray[j].video
video.id = "video-"+j
video.preload = "metadata"
video.type = "video/mp4"
video.autoplay = true
// show the first video right away
if( j !== 0 ) video.style.display = "none"
// set muted attribute
video.muted = "muted"
// play next video after the previous had ended
video.addEventListener('ended', (num => function() {
this.style.display = "none";
if( num !== videoArray.length-1 ) {
videoArray[num+1].video_el.style.display="block";
// only needed if `muted` is not set
videoArray[num+1].video_el.play();
}
})(j), false);
document.body.appendChild(video);
}
If muted attribute is not the option, you can add some event listeners on the body to call play() on the first video as soon as the user starts interaction with the page. And maybe you would like to read more about autoplay here: https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide

JavaScript while loop through a video while automatically playing and pausing

How can I efficiently write a JavaScript while loop code to automatically play a one hour video while playing for three seconds and pausing for six seconds to allow me time to transcribe? This is what I have tried but I have not succeeded.
<!DOCTYPE html>
<html>
<head>
<title> Video transcription</title>
</head>
<body>
</body>
<video id = 'myVideo' >
<source src = 'testVideo.mp4'>
</video>
<script>
var pauseTime = 6000 // six seconds
var initialTime = 0
var timeUpdate = 3
var timeIncrement = initialTime + timeUpdate
var wasPausedBefore1 = 0;
var wasPausedBefore2 = 0;
var wasPausedBefore3 = 0;
while (video.duration > 0) {
var video = document.getElementById('myVideo');
video.play();
video.ontimeupdate = function() {
let currentTime =video.currentTime;
if (currentTime > initialTime && currentTime < timeIncrement && wasPausedBefore1 == 0) {
video.pause();
wasPausedBefore1 = 1;
setTimeout(function() {
video.play();
}, pauseTime);
} else if(currentTime > initialTime && currentTime < timeIncrement && wasPausedBefore2 == 0){
video.pause();
wasPausedBefore2 = 1;
setTimeout(function() {
video.play();
}, pauseTime);
}
initialTime += timeUpdate
timeIncrement += timeUpdate
}
}
</script>
</body>
</html>
I did the following to create a control logic of your application:
Created a Petri Net diagram of the control logic. I used Notepad to create the diagram as PDF form XObject.
Created an interactive prototype of the control logic as a PDF form application.
Created the control logic of the application based on the prototype. I used the setTimeout API instead of a loop structure.
For me this is an effective way to create the control logic of many applications because creating the interactive prototype based on a Petri Net diagram is a systematic activity.
The interactive prototype plus details on its construction and additional sample source codes are available in a dynamic and interactive PDF at https://www.academia.edu/43005182/How_to_Automatically_Play-and-Pause_a_Video_A_Reply_to_a_Request_at_Stack_Overflow.
The following HTML code is an example of how to use the control logic.
<!DOCTYPE html>
<head>
<title>Play-and-Pause Example</title>
</head>
<body>
<video id = 'video0'>
<source src = '1956Pepto_512kb.mp4'>
</video>
<script>
/* Copyright 2020 John Frederick Chionglo */
var tObject;
var vTime = 64000;
var vID = document.getElementById('video0');
function PlayAndPause(parms) {
this.videoID = parms.videoID;
this.videoTime = parms.videoTime;
this.tObject = undefined;
}
PlayAndPause.objs = [];
PlayAndPause.play = function(id) {
PlayAndPause.objs[id].playSegment(id);
};
PlayAndPause.pause = function(id) {
PlayAndPause.objs[id].pauseSegment(id);
};
with (PlayAndPause) {
prototype.window = this;
prototype.playTime = 3000;
prototype.pauseTime = 6000;
prototype.playSegment = function(id) {
this.videoID.play();
this.videoTime -= this.playTime;
this.tObject = setTimeout("PlayAndPause.pause("+ id + ")", this.playTime);
};
prototype.pauseSegment = function(id) {
if (this.videoTime<0) {}
else {
this.videoID.pause();
this.tObject = setTimeout("PlayAndPause.play(" + id + ")", this.pauseTime);
}
};
}
var ppobj = new PlayAndPause({videoID: vID, videoTime: vTime});
PlayAndPause.objs[0] = ppobj;
ppobj.playSegment(0);
</script>
</body>
</html>

Remove all other 'vtt cues' from video tag

I have a video tag in which I pass video data i.e src and vtt dynamically, I want to keep vtt for the current video only, and remove all other textTracks.
Right Now on switching the video, all vtt related to previously played videos start playing inside the video tag.
vtt is subtitle
function addVttInvideo(data) {
// http://www.html5rocks.com/en/tutorials/track/basics/
// https://www.iandevlin.com/blog/2015/02/javascript/dynamically-adding-text-tracks-to-html5-video
var video = document.getElementById('videoSrc');
var track = video.addTextTrack('subtitles', 'English', 'en');
track.mode = "showing";
var startTime = parse_timestamp(data.info.start);
var endTime = parse_timestamp(data.info.end);
var cue = new VTTCue(startTime, endTime, data.info.text);
// track.addEventListener("cuechange", function () {
// // get current cue, and remove it if it's number 2
// var currentCue = track.activeCues[0];
// track.removeCue(currentCue)
// },false);
track.addCue(cue);
// console.log('subtitle.innerHTML',subtitle.innerHTML);
// quick_and_dirty_vtt_or_srt_parser(subtitle.innerHTML).map(function(cue) {
// track.addCue(cue);
// });
// track.addCue(quick_and_dirty_vtt_or_srt_parser(2,55,'my profile'));
}
function parse_timestamp(s) {
var match = s.match(/^(?:([0-9]{2,}):)?([0-5][0-9]):([0-5][0-9][.,][0-9]{0,3})/);
if (match == null) {
throw 'Invalid timestamp format: ' + s;
}
var hours = parseInt(match[1] || "0", 10);
var minutes = parseInt(match[2], 10);
var seconds = parseFloat(match[3].replace(',', '.'));
return seconds + 60 * minutes + 60 * 60 * hours;
}
} catch (e) {
console.log('the exception album ' + e);
}
// load video is called when user swipe next and back
function loadVideo(way) {
var videoSrc = $('#videoSrc');
if (way === 'prev') {
videoCounter = videoCounter - 1;
if (videoCounter < 0) videoCounter = VideoData.length - 1;
videoSrc.attr('src', VideoData[videoCounter].vurl);
videoSrc.attr('poster', VideoData[videoCounter].turl)
addVttInvideo(VideoData[videoCounter].vtt)
} else if (way === 'next') {
videoCounter = videoCounter + 1;
if (videoCounter > VideoData.length - 1) videoCounter = 0;
videoSrc.attr('src', VideoData[videoCounter].vurl);
videoSrc.attr('poster', VideoData[videoCounter].turl)
addVttInvideo(VideoData[videoCounter].vtt)
} else {
videoSrc.attr('src', VideoData[0].vurl);
videoSrc.attr('poster', VideoData[0].turl)
addVttInvideo(VideoData[0].vtt)
// document.getElementById('vsrc').onloadeddata = function() {
// debugger
//
// };
}
$("#videoAlbumCaption").text(videoCounter + 1 + " / " + VideoData.length);
}
A bit confusing as your question is for removing vtt cue, but from what you described is removing all other textTracks.
I will explain how to remove all other textTracks.
HTML
<video src="foo.ogv">
<track kind="subtitles" label="English subtitles" src="subtitles_en.vtt" srclang="en" default>
</track>
<track kind="subtitles" label="Deutsche Untertitel" src="subtitles_de.vtt" srclang="de">
</track>
</video>
videoElement.textTracks console output
var videoElement = document.querySelector("video");
console.log(videoElement);
TextTrackList {0: TextTrack, 1: TextTrack, length: 2, onchange: null, onaddtrack: null, onremovetrack: null}
0: TextTrack {kind: "subtitles", label: "English subtitles", language: "en", id: "", mode: "showing", …}
1: TextTrack {kind: "subtitles", label: "Deutsche Untertitel", language: "de", id: "", mode: "disabled", …}
length: 2
Remove Track
var videoElement = document.querySelector("video");
videoElement.removeChild(videoElement.children[0]); //remove English subtitle
// you need iterlate videoElement.textTracks and find index according to language
var i =0;
var targetLanguage = "de";
for (let track of videoElement.textTracks){
if(track.language !== targetLanguage){
videoElement.removeChild(videoElement.children[i]);
}
i++;
}
As #Heretic Monkey commented, please refer to this for TextTrackList Implementation.
Delete a TextTrack from a video

Animation Array in JavaScript

I've come up with this little animation that uses images in an array, but it's sloppy. What I'd really like is to modularize it so that I can use multiple instances of the same function to animate different arrays depending on which key is pressed. Also, I'd like to get it so that the animation stops when the key is released, if possible. I realize that calling all of those variables globally is a big no-no, but I have no idea how to make it work otherwise! Last but not least, I'd like to figure out how to get that last bit of inline script over to the external file and have it still work correctly. Any help would be much appreciated! But please note, I'm a novice with JavaScript, so please try to be as specific/detailed as possible so I can learn from your wisdom! Thank you!
I've created a jsfiddle.
HTML:
<div id="wrapper">
<span id="jajo"><img id="my_img" src="jajo.png" /></span>
<script>element = document.getElementById("jajo"); </script>
</div><!--wrapper-->
JavaScript:
var i = 0;
var element;
var waveArray = ["wave0.png","wave1.png","wave2.png","wave3.png","wave4.png","wave5.png"];
var jumpArray = ["jump0.png","jump1.png","jump2.png","jump3.png","jump4.png","jump5.png"];
var foodArray = ["food0.png","food1.png","food2.png","food3.png","food4.png","food5.png"];
document.onkeydown = function(event) {
var keyPress = String.fromCharCode(event.keyCode);
if(keyPress == "W") { // if "w" is pressed, display wave animation
increment ();
document.onkeyup = function(event) { // if "w" is released, display default image
document.getElementById("jajo").innerHTML= "<img alt='Jajo' src='jajo.png'>";
}
} else if(keyPress == "A") { // if "a" is pressed, display jump animation
} else if(keyPress == "S") { // if "s" is pressed, display food animation
}
}
function increment (){
i++;
if(i > (waveArray.length - 1)){
i = 0;
}
setTimeout(animation,1000/30);
}
function animation() {
var img = '<img src="' + waveArray[i] + '" alt="Jajo" />';
element.innerHTML = img;
setTimeout(increment, 2000/30);
}
Demo
http://jsfiddle.net/ghQwF/4/
Module
var animation = (function() {
var delay = 1000 / 30;
var map = {}, active = [], timer;
function animate() {
for(var i=0, l=active.length; i<l; ++i) {
var data = map[active[i]];
++data.index;
data.index %= data.array.length;
data.image.src = data.array[data.index];
}
timer = setTimeout(animate, delay);
}
function begin(e) {
var key = String.fromCharCode(e.keyCode),
data = map[key];
if(!data) return;
if(!active.length) timer = setTimeout(animate, delay);
if(!~active.indexOf(key)) active.push(key);
}
function end(e) {
var key = String.fromCharCode(e.keyCode),
data = map[key];
if(!data) return;
data.image.src = data.default;
var index = active.indexOf(key);
if(!~index) return;
active.splice(index, 1);
if(!active.length) clearTimeout(timer);
}
return {
add: function(data) {
data.index = data.index || 0;
data.image = data.image || data.target.getElementsByTagName('img')[0];
data.default = data.default || data.image.src;
map[data.key] = data;
},
remove: function(key) {
delete map[key];
},
enable: function() {
document.addEventListener('keydown', begin, false);
document.addEventListener('keyup', end, false);
},
disable: function() {
document.removeEventListener('keydown', begin, false);
document.removeEventListener('keyup', end, false);
clearTimeout(timer);
active = [];
}
};
})();
Example
animation.enable();
animation.add({
key: 'W',
target: document.getElementById('jajo'),
array: [
"http://static.spoonful.com/sites/default/files/styles/square_128x128/public/crafts/fingerprint-flowers-spring-craft-photo-420x420-aformaro-01.jpg",
"http://static.spoonful.com/sites/default/files/styles/square_128x128/public/crafts/paper-flowers-spring-craft-photo-420x420-aformaro-11.jpg",
"http://static.spoonful.com/sites/default/files/styles/square_128x128/public/crafts/tissue-paper-flowers-kaboose-craft-photo-350-fs-IMG_8971_rdax_65.jpg"
]
});
animation.add({ /* ... */ });
Methods
add
Adds a new animation, with parameters:
key: key to activate animation
target: wrapper of the image (optional if image is specified)
image: image to animate (optional, defaults to first image in target)
default: default url of the image (optional, defaults to original url)
index: initial position in array (optional, defaults to 0)
array: array of images
remove
Removes the animation related with key specified.
disable
Disables animations (typing keys would have no effect), and stops current ones.
enable
Enable animations (typing keys can start animations).

Categories

Resources