Intersection observer for multiple videos on the same page - javascript

I have a portfolio page made in WordPress and on the page I have 5 videos that need to be played when in viewport and stopped when out of viewport.
I have used the following script that works only on the first video on the page.
const video = document.querySelector("video");
let playState = null;
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) {
video.pause();
playState = false;
} else {
video.play();
playState = true;
}
});
}, {});
observer.observe(video);
const onVisibilityChange = () => {
if (document.hidden || !playState) {
video.pause();
} else {
video.play();
}
};
document.addEventListener("visibilitychange", onVisibilityChange);
querySelector("video");
And here is the link to the page:
http://wemedia.co.rs/portfolio-2/
So what I want to achieve is to play and pause every video when in or out of viewport.
Thank you.

You are only selecting one video to use throughout your whole js script.
You need to remember that video represents only a single video and if you want to control multiple, you need to reference them in every function that you call.
I also don't see a purpose in using playState since the way you have it, it is basically an indicator of whether the first video is on screen or not.
const videos = document.querySelectorAll("video"); // Select ALL the Videos
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) {
entry.target.pause(); // Pause the TARGET video
} else {
entry.target.play(); // Play the TARGET video
}
});
}, {});
for (const video of videos) observer.observe(video); // Observe EACH video
const onVisibilityChange = () => {
if (document.hidden) {
for (const video of videos) video.pause(); // Pause EACH video
} else {
for (const video of videos) video.play(); // Play EACH video
}
};
document.addEventListener("visibilitychange", onVisibilityChange);

Related

How to autoplay any iframe video if it is in the viewport

there developers
I'm actually in a bit of a problem I'm trying to make stuff something like if the iframe is in the viewport then video will autoplay
Condition
Iframe is in viewport then video will play
iframe video get paused if it is not in the viewport
iframe video get paused if any modal open
function playvideo(iframe) {
iframe.contentWindow.postMessage(
'{"event":"command","func":"playVideo","args":""}',
'*'
)
}
function pausevideo(iframe) {
iframe.contentWindow.postMessage(
'{"event":"command","func":"pauseVideo","args":""}',
'*'
)
}
let observeroptions = {
root: null,
rootMargin: '0px',
threshold: 1.0
};
let callback = (entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
playvideo(entry.target)
} else {
// pausevideo(entry.target);
observer.unobserve(entry.target)
}
})
}
let observer = new IntersectionObserver(callback, observeroptions);
$(window).scroll(function () {
$('iframe').each(function (e) {
if ($(this).isInViewport()) {
observer.observe($(this)[0])
}
})
})
This is my website link
https://letscodeon.me/research.php?category=videos
Problem
The problem is that video is getting paused when the page reload it is not autoplaying when it is in viewport
If i play one video then autoplay is working
if i'm opening a modal then back video is not getting paused

Javascript Play Video on Mouse Hover (Multiple Videos)

I have the following JavaScript code that work great when I hover over a video. I like how the start and stop is broken into functions and it allows me to customize the hover play exactly how I want. However, this code only works on the first video on the page and I have several videos that are loaded on the page dynamically.
I would like to modify this code so that it will work on all videos on the page. I'm thinking that maybe the functions need to be called inside a loop? I'm not sure as I do not know JavaScript well, so any help on how to modify this code would would be much appreciated!
const video = document.querySelector("video");
function startPreview() {
video.muted = true;
video.currentTime = 5;
video.playbackRate = 2.5;
video.play();
}
function stopPreview() {
video.currentTime = 5;
video.playbackRate = 1;
video.pause();
}
let previewTimeout = null;
video.addEventListener("mouseenter", () => {
startPreview();
previewTimeout = setTimeout(stopPreview, 3000);
});
video.addEventListener("mouseleave", () => {
clearTimeout(previewTimeout);
previewTimeout = null;
stopPreview();
});
You can do event delegation to handle all videos. So:
document.body.addEventListener('mouseenter', (event) => {
if (event.target.matches('video') {
// start playing
}
});
More on the matches() method on MDN.
You would also modify the start and stop methods to take the video element as a parameter:
function startPreview(video) {
video.muted = true;
video.currentTime = 5;
video.playbackRate = 2.5;
video.play();
}
And pass them the event.target.

how to open html 5 video fullscreen if it was fullscreen before

I'm watching a series of videos on a website organised in a playlist. Each video is about 2 minutes long.
The website uses HTML 5 video player and it supports auto-play. That is each time a video ends, the next video is loaded and automatically played, which is great.
However, with Fullscreen, even if I fullscreened a video previously, when the next video loads in the playlist, the screen goes back to normal, and I have to click the fullscreen button again....
I've tried writing a simple javascript extension with Tampermonkey to load the video fullscreen automatically.
$(document).ready(function() {
function makefull() {
var vid = $('video')[0]
if (vid.requestFullscreen) {
vid.requestFullscreen();
} else if (vid.mozRequestFullScreen) {
vid.mozRequestFullScreen();
} else if (vid.webkitRequestFullscreen) {
vid.webkitRequestFullscreen();
}
//var vid = $('button.vjs-fullscreen-control').click();
}
makefull()
But I'm getting this error:
Failed to execute 'requestFullscreen' on 'Element': API can only be initiated by a user gesture.
It's extremely annoying to have to manually click fullscreen after each 2 min video. Is there a way I can achieve this in my own browser? I'm using Chrome.
If you can get the list of URL's then you can create your own playlist. The code cannot be accurately tested within a cross-origin <iframe>, for example at plnkr.co. The code can be tested at console at this very document. To test the code, you can use the variable urls at MediaFragmentRecorder and substitute "pause" event for "ended" event at .addEventListener().
If you have no control over the HTML or JavaScript used at the site not sure how to provide any code that will be able to solve the inquiry.
const video = document.createElement("video");
video.controls = true;
video.autoplay = true;
const urls = [
{
src: "/path/to/video/"
}, {
src: "/path/to/video/"
}
];
(async() => {
try {
video.requestFullscreen = video.requestFullscreen
|| video.mozRequestFullscreen
|| video.webkitRequestFullscreen;
let fullScreen = await video.requestFullscreen().catch(e => {throw e});
console.log(fullScreen);
} catch (e) {
console.error(e.message)
}
for (const {src} of urls) {
await new Promise(resolve => {
video.addEventListener("canplay", e => {
video.load();
video.play();
}, {
once: true
});
video.addEventListener("ended", resolve, {
once: true
});
video.src = src;
});
}
})();

Release webcam and microphone from getUserMedia after countdown [duplicate]

I opened a webcam by using the following JavaScript code:
const stream = await navigator.mediaDevices.getUserMedia({ /* ... */ });
Is there any JavaScript code to stop or close the webcam?
Since this answer has been originally posted the browser API has changed.
.stop() is no longer available on the stream that gets passed to the callback.
The developer will have to access the tracks that make up the stream (audio or video) and stop each of them individually.
More info here: https://developers.google.com/web/updates/2015/07/mediastream-deprecations?hl=en#stop-ended-and-active
Example (from the link above):
stream.getTracks().forEach(function(track) {
track.stop();
});
Browser support may differ.
Previously, navigator.getUserMedia provided you with a stream in the success callback, you could call .stop() on that stream to stop the recording (at least in Chrome, seems FF doesn't like it)
Use any of these functions:
// stop both mic and camera
function stopBothVideoAndAudio(stream) {
stream.getTracks().forEach(function(track) {
if (track.readyState == 'live') {
track.stop();
}
});
}
// stop only camera
function stopVideoOnly(stream) {
stream.getTracks().forEach(function(track) {
if (track.readyState == 'live' && track.kind === 'video') {
track.stop();
}
});
}
// stop only mic
function stopAudioOnly(stream) {
stream.getTracks().forEach(function(track) {
if (track.readyState == 'live' && track.kind === 'audio') {
track.stop();
}
});
}
Don't use stream.stop(), it's deprecated
MediaStream Deprecations
Use stream.getTracks().forEach(track => track.stop())
FF, Chrome and Opera has started exposing getUserMedia via navigator.mediaDevices as standard now (Might change :)
online demo
navigator.mediaDevices.getUserMedia({audio:true,video:true})
.then(stream => {
window.localStream = stream;
})
.catch( (err) =>{
console.log(err);
});
// later you can do below
// stop both video and audio
localStream.getTracks().forEach( (track) => {
track.stop();
});
// stop only audio
localStream.getAudioTracks()[0].stop();
// stop only video
localStream.getVideoTracks()[0].stop();
Suppose we have streaming in video tag and id is video - <video id="video"></video> then we should have following code -
var videoEl = document.getElementById('video');
// now get the steam
stream = videoEl.srcObject;
// now get all tracks
tracks = stream.getTracks();
// now close each track by having forEach loop
tracks.forEach(function(track) {
// stopping every track
track.stop();
});
// assign null to srcObject of video
videoEl.srcObject = null;
Starting Webcam Video with different browsers
For Opera 12
window.navigator.getUserMedia(param, function(stream) {
video.src =window.URL.createObjectURL(stream);
}, videoError );
For Firefox Nightly 18.0
window.navigator.mozGetUserMedia(param, function(stream) {
video.mozSrcObject = stream;
}, videoError );
For Chrome 22
window.navigator.webkitGetUserMedia(param, function(stream) {
video.src =window.webkitURL.createObjectURL(stream);
}, videoError );
Stopping Webcam Video with different browsers
For Opera 12
video.pause();
video.src=null;
For Firefox Nightly 18.0
video.pause();
video.mozSrcObject=null;
For Chrome 22
video.pause();
video.src="";
With this the Webcam light go down everytime...
Try method below:
var mediaStream = null;
navigator.getUserMedia(
{
audio: true,
video: true
},
function (stream) {
mediaStream = stream;
mediaStream.stop = function () {
this.getAudioTracks().forEach(function (track) {
track.stop();
});
this.getVideoTracks().forEach(function (track) { //in case... :)
track.stop();
});
};
/*
* Rest of your code.....
* */
});
/*
* somewhere insdie your code you call
* */
mediaStream.stop();
You can end the stream directly using the stream object returned in the success handler to getUserMedia. e.g.
localMediaStream.stop()
video.src="" or null would just remove the source from video tag. It wont release the hardware.
Since you need the tracks to close the streaming, and you need the stream boject to get to the tracks, the code I have used with the help of the Muaz Khan's answer above is as follows:
if (navigator.getUserMedia) {
navigator.getUserMedia(constraints, function (stream) {
videoEl.src = stream;
videoEl.play();
document.getElementById('close').addEventListener('click', function () {
stopStream(stream);
});
}, errBack);
function stopStream(stream) {
console.log('stop called');
stream.getVideoTracks().forEach(function (track) {
track.stop();
});
Of course this will close all the active video tracks. If you have multiple, you should select accordingly.
If the .stop() is deprecated then I don't think we should re-add it like #MuazKhan dose. It's a reason as to why things get deprecated and should not be used anymore. Just create a helper function instead... Here is a more es6 version
function stopStream (stream) {
for (let track of stream.getTracks()) {
track.stop()
}
}
You need to stop all tracks (from webcam, microphone):
localStream.getTracks().forEach(track => track.stop());
Start and Stop Web Camera,(Update 2020 React es6 )
Start Web Camera
stopWebCamera =()=>
//Start Web Came
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
//use WebCam
navigator.mediaDevices.getUserMedia({ video: true }).then(stream => {
this.localStream = stream;
this.video.srcObject = stream;
this.video.play();
});
}
}
Stop Web Camera or Video playback in general
stopVideo =()=>
{
this.video.pause();
this.video.src = "";
this.video.srcObject = null;
// As per new API stop all streams
if (this.localStream)
this.localStream.getTracks().forEach(track => track.stop());
}
Stop Web Camera function works even with video streams:
this.video.src = this.state.videoToTest;
this.video.play();
Using .stop() on the stream works on chrome when connected via http. It does not work when using ssl (https).
Please check this: https://jsfiddle.net/wazb1jks/3/
navigator.getUserMedia(mediaConstraints, function(stream) {
window.streamReference = stream;
}, onMediaError);
Stop Recording
function stopStream() {
if (!window.streamReference) return;
window.streamReference.getAudioTracks().forEach(function(track) {
track.stop();
});
window.streamReference.getVideoTracks().forEach(function(track) {
track.stop();
});
window.streamReference = null;
}
The following code worked for me:
public vidOff() {
let stream = this.video.nativeElement.srcObject;
let tracks = stream.getTracks();
tracks.forEach(function (track) {
track.stop();
});
this.video.nativeElement.srcObject = null;
this.video.nativeElement.stop();
}
Have a reference of stream form successHandle
var streamRef;
var handleVideo = function (stream) {
streamRef = stream;
}
//this will stop video and audio both track
streamRef.getTracks().map(function (val) {
val.stop();
});

Javascript : Autoplay audio onended function not working

I'm trying to build a web app that fetches a sound of a bird from an API, plays it and gets a new bird once the old one has stopped playing. As of now it works in Safari & Firefox, but the script stops in Chrome.
function init() {
console.log('init');
var container = document.getElementById("container");
container.innerHTML = ("Machines & Birds");
fetchBirdAPI();
}
function fetchBirdAPI() {
fetch(url)
.then(function(response) {
return response.json();
}).then(function(response) {
console.log(response)
getAudio(response);
});
}
function getAudio(response) {
if (response.numRecordings !== 0) {
var birdSrc = (response.recordings[0].file);
var audio = document.createElement('AUDIO');
audio.src = birdSrc;
audio.addEventListener('loadedmetadata', function() {
console.log(audio.duration);
});
audio.play();
audio.onended = function() {
console.log('Audio Ended');
init();
}
}
else {
init();
}
}
So basically the audio.onended doesn't work. Also tried to initiate the audio with audio = new Audio() without any luck.
Really flabbergasted here, so any input would be appreciated.

Categories

Resources