From 79436d86073a7fd697ec57ec2f134c5a0d7b561e Mon Sep 17 00:00:00 2001 From: Yoan Le Clanche Date: Wed, 29 Jan 2025 17:37:03 +0100 Subject: [PATCH] WIP --- teleforma/src/js/video/SyncVideoPlayer.ts | 163 ++++++++++-------- teleforma/src/js/video/VideoComponent.vue | 68 +++++--- teleforma/src/js/video/VideoPlayer.ts | 89 ++++++---- .../templates/teleforma/course_media.html | 24 ++- 4 files changed, 218 insertions(+), 126 deletions(-) diff --git a/teleforma/src/js/video/SyncVideoPlayer.ts b/teleforma/src/js/video/SyncVideoPlayer.ts index ae304a81..cbcea115 100644 --- a/teleforma/src/js/video/SyncVideoPlayer.ts +++ b/teleforma/src/js/video/SyncVideoPlayer.ts @@ -1,6 +1,7 @@ -import {PlayerState} from './constants'; -import {MultiVideoPlayerOptions, VideoPlayerOptions} from './main'; -import {Logger} from "./utils"; +import { fi } from 'date-fns/locale'; +import { PlayerState } from './constants'; +import { MultiVideoPlayerOptions, VideoPlayerOptions } from './main'; +import { Logger } from "./utils"; import VideoPlayer from './VideoPlayer'; const validStates = { @@ -88,62 +89,73 @@ class SyncVideoPlayer { } public async changeState(state: PlayerState, videoPlayer: VideoPlayer) { - // console.log("change global state", state) + console.log("video state = ", videoPlayer.videoState); + + const mainVideoPlayer = this.videoPlayers.find((vp) => vp.main); + if (state === PlayerState.BUFFERING) { - return this.pause() - // console.log("change state to BUFFERING") - // return this.pause(); - // TODO: find out how to handle buffering - // return; + if (mainVideoPlayer && mainVideoPlayer === videoPlayer) { + console.log("💯changeState - BUFFERING - calling pause()"); + console.log("💯mainVideoPlayer.videoState = ", mainVideoPlayer.videoState); + console.log("💯this.state = ", this.state); + return this.pause(); + } + return; } + if (state === PlayerState.PLAYING) { - return this.play(); + console.log("⌛changeState - PLAYING - call : this.play()"); + console.log("⌛this.state = ", this.state); + + if (this.state !== PlayerState.BUFFERING) { + return this.play(); + } + return; } + if (state === PlayerState.PAUSE) { - if (videoPlayer.isEnded()) { - return; - } - return this.pause(); + if (videoPlayer.isEnded()) { + return; + } + console.log("✍️ changeState - PAUSE - call : this.pause()"); + return this.pause(); } - if (state === PlayerState.ENDED) { - // the main video player is the only one that can end if main is set - const mainVideoPlayer = this.videoPlayers.find((vp) => { - return vp.main; - }); - if (mainVideoPlayer && mainVideoPlayer !== videoPlayer) { - return; - } - await this.moveStateTo(PlayerState.ENDED, () => { - if (this.options.loop) { - this.timeTo(0); + if (state === PlayerState.ENDED) { + if (mainVideoPlayer && mainVideoPlayer !== videoPlayer) { + return; } - }); + await this.moveStateTo(PlayerState.ENDED, () => { + if (this.options.loop) { + console.log("changeState - ENDED - call : this.timeTo(0)"); + this.timeTo(0); + } + }); } + if (state === PlayerState.READY) { - // player has finished buffering and ready to start - // check if every player is ready - - const allReady = this.videoPlayers.every(vp => { - return [PlayerState.READY, PlayerState.PLAYING, PlayerState.PAUSE].includes(vp.videoState); - }); - if(allReady){ - console.log("all ready, start playing") - await this.play(); - } + const allReady = this.videoPlayers.every((vp) => + [PlayerState.READY, PlayerState.PLAYING, PlayerState.PAUSE].includes(vp.videoState) + ); + if (allReady) { + console.log("Toutes les vidéos sont prêtes. Lancement de la lecture."); + console.log("changeState - READY - call : athis.play()"); + this.play(); + } } + if (state === PlayerState.UNSTARTED) { - if (this.state === PlayerState.ENDED) { - if (this.options.loop) { - await this.play(); + if (this.state === PlayerState.ENDED && this.options.loop) { + console.log("changeState - UNSTARTED - call : this.play()"); + this.play(); } - } } - } +} + private async moveStateTo(state: PlayerState, success?: (newState: PlayerState, oldState: PlayerState) => void, fail?: (newState: PlayerState, oldState: PlayerState) => void) { - if(state === this.state) return; + if (state === this.state) return; if (isValidState(this.state, state)) { const oldState = this.state; this.state = state; @@ -168,34 +180,30 @@ class SyncVideoPlayer { public onTimeUpdate(videoPlayer: VideoPlayer, time: number) { const diff = Math.abs(this.currentTime - time); if (diff > 0.5) { - this.timeTo(time); + this.timeTo(time); } this.currentTime = time; this.fixVideoStates(); } private fixVideoStates() { - const mainVideoPlayer = this.videoPlayers.find((vp) => { - return vp.main; - }); - + const mainVideoPlayer = this.videoPlayers.find((vp) => vp.main); if (!mainVideoPlayer) return; - this.videoPlayers.forEach(vp => { - if (vp === mainVideoPlayer) return; - if (vp.isEnded()) return; - if(mainVideoPlayer.isPlaying && !vp.isPlaying) { - vp.play().catch(() => { - // noop - }); - } - if(!mainVideoPlayer.isPlaying && vp.isPlaying) { - vp.pause().catch(() => { - // noop - }); + + this.videoPlayers.forEach(async vp => { + if (vp === mainVideoPlayer || vp.isEnded()) return; + + if (mainVideoPlayer.isPlaying && !vp.isPlaying) { + console.log("fixVideoStates - call: vp.play();"); + vp.play(); + } else if (!mainVideoPlayer.isPlaying && vp.isPlaying) { + console.log("fixVideoStates - call: vp.pause();"); + vp.pause(); } }); } + /** * ------------------------------ * Public methods @@ -204,6 +212,7 @@ class SyncVideoPlayer { public addVideoPlayers(videoPlayers: VideoPlayerOptions[] | undefined) { if (!videoPlayers) return; + videoPlayers.forEach(videoPlayer => { this.addVideoPlayer(videoPlayer); }); @@ -216,22 +225,24 @@ class SyncVideoPlayer { } public async play() { - await this.moveStateTo(PlayerState.PLAYING, async () => { - this.timeTo(this.currentTime); - await Promise.all(this.videoPlayers.map(async video => { - if (this.currentTime < video.getPlayLength()) { - await video.play(); - } - })); - }); + await this.moveStateTo(PlayerState.PLAYING, async () => { + this.timeTo(this.currentTime); + await Promise.all( + this.videoPlayers.map(async (video) => { + if (this.currentTime < video.getPlayLength()) { + await video.play(); + } + }) + ); + }); } - public async pause() { - await this.moveStateTo(PlayerState.PAUSE, async () => { - await Promise.all(this.videoPlayers.map(async video => { - await video.pause(); - })); - }); + public pause() { + this.moveStateTo(PlayerState.PAUSE, async () => { + Promise.all(this.videoPlayers.map(async video => { + video.pause(); + })); + }); } public async stop() { @@ -242,10 +253,10 @@ class SyncVideoPlayer { }); } - public timeTo(time: number) { + public async timeTo(time: number) { this.currentTime = time; - this.videoPlayers.forEach(video => { - video.timeTo(time); + this.videoPlayers.forEach(async video => { + await video.timeTo(time); }); } diff --git a/teleforma/src/js/video/VideoComponent.vue b/teleforma/src/js/video/VideoComponent.vue index 2ebfbaa4..314ca56c 100644 --- a/teleforma/src/js/video/VideoComponent.vue +++ b/teleforma/src/js/video/VideoComponent.vue @@ -2,6 +2,7 @@ import { onMounted, nextTick, ref } from "vue" import SyncVideoPlayer from "./SyncVideoPlayer" +import { PlayerState } from './constants'; const multivideos = (window as any).multivideos console.log(multivideos) @@ -12,29 +13,62 @@ const syncVideoPlayer = new SyncVideoPlayer({ videoPlayers: multivideos || [] }) + // build a list of video ids equal to multivideos length const ids = ref(Array.from({ length: multivideos.length }, (_, i) => `video-${i}`)) const debugInfo = ref({}) +var count = 0; + onMounted(() => { - syncVideoPlayer.mount() + syncVideoPlayer.mount(); setInterval(() => { - debugInfo.value = syncVideoPlayer.getDebugInfo() - }, 50) - // const mainVideo = document.getElementById("main-video").querySelector("video") - - // mainVideo.addEventListener("loadeddata", () => { - // //Video should now be loaded but we can add a second check + debugInfo.value = syncVideoPlayer.getDebugInfo(); + }, 50); + + // const videoElement = document.querySelector("#video-0 video"); + // console.log("✅✅✅✅✅ videoElement = ", videoElement) + // videoElement.addEventListener('play', (event) => { + // count = count + 1; + // try{ + // console.log("✅✅✅✅✅ 778999454555555555", count) + // syncVideoPlayer.play(); + // console.log("✅✅✅✅✅ 778999454555555555") + // } + // catch(error){ + // console.log(error) + // } + // }); - // if (mainVideo.readyState >= 1) { - // resizeVideoContainers() + // videoElement.addEventListener('pause', (event) => { + // try{ + // syncVideoPlayer.pause(); + // } + // catch(error){ + // console.log(error) // } - // }) - // // resize videos containers on window resize - // window.addEventListener("resize", resizeVideoContainers) + // }); + + + // const buttonTest = document.querySelector('.vjs-play-control'); + // if (buttonTest) { + // buttonTest.addEventListener('click', (event) => { + // event.preventDefault(); + // event.stopPropagation(); + // if(buttonTest.classList.contains('vjs-paused')) + // { + // console.log("✅✅✅✅✅ Play ✅✅✅✅✅") + // } + // else { + // console.log("✅✅✅✅✅ Pause ✅✅✅✅✅") + // } + // }); + // } + }) + // function resizeVideoContainers() { // /** resize video containers so it fits a 2/3 - 1/3 */ @@ -101,14 +135,8 @@ async function onChange(e: Event) {
-
+
diff --git a/teleforma/src/js/video/VideoPlayer.ts b/teleforma/src/js/video/VideoPlayer.ts index 0119d90c..99e77442 100644 --- a/teleforma/src/js/video/VideoPlayer.ts +++ b/teleforma/src/js/video/VideoPlayer.ts @@ -55,7 +55,7 @@ class VideoPlayer { }, 1); - + // this.videojs.on('volumechange', (e: any) => { // console.log(e) // // find the videos with the sound on @@ -73,13 +73,27 @@ class VideoPlayer { // e.stopPropagation() // }) + this.videojs.on('loadeddata', this.onReady.bind(this)) this.videojs.on('timeupdate', this.onTimeUpdate.bind(this)) this.videojs.on('seeking', this.onSeeking.bind(this)) this.videojs.on('ended', this.onStateChange.bind(this, PlayerState.ENDED)) - - this.videojs.on('pause', this.onStateChange.bind(this, PlayerState.PAUSE)) - this.videojs.on('play', this.onStateChange.bind(this, PlayerState.PLAYING)) + + this.videojs.on('play', () => {7 + console.log("✅✅✅✅✅✅VideoJs = ", this.videojs) + + console.log("✨play - VIDEO PLAYING = ", this.isPlaying) + console.log("✨✨this.player.state = ", this.player.state) + if (!this.isPlaying && this.player.state !== PlayerState.BUFFERING) { + this.onStateChange(PlayerState.PLAYING); + } + }); + + this.videojs.on('pause', () => { + if (this.isPlaying) { + this.onStateChange(PlayerState.PAUSE); + } + }); // this.videojs.on('waiting', () => { // // console.log("WAITING FOR BUFFERING", this.videoState, e) // // if(this.isPlaying) @@ -95,21 +109,23 @@ class VideoPlayer { this.canWait = false setTimeout(() => { this.canWait = true - + }, 1000) }) - - this.videojs.on('waiting', () => { - if(!this.canWait) - return - if(this.videoElement!.readyState === 4) - return - console.log("BUFFERING...", this.videoElement!.readyState) - if (![PlayerState.LOADING, PlayerState.LOADED].includes(this.player.state as PlayerState)) { - this.onStateChange(PlayerState.BUFFERING) - } - }) - + + // this.videojs.on('waiting', () => { + // if (!this.canWait) + // return + // if (this.videoElement!.readyState === 4) + // return + // console.log("BUFFERING...", this.videoElement!.readyState) + // if (![PlayerState.LOADING, PlayerState.LOADED].includes(this.player.state as PlayerState)) { + // console.log("this.player.state = ", this.player.state) + // console.log("waiting - VIDEO PLAYING = ", this.isPlaying) + // // this.onStateChange(PlayerState.BUFFERING) + // } + // }) + // this.videojs.on('progress', (e:any) => { // console.log('progress') // console.log(e) @@ -128,7 +144,7 @@ class VideoPlayer { // this.videoElement.addEventListener('waiting', this.onStateChange.bind(this, PlayerState.BUFFERING), false); } - get videoElement(): HTMLVideoElement | null{ + get videoElement(): HTMLVideoElement | null { return document.querySelector(`#video_player_${this.videoId} video`) as HTMLVideoElement } @@ -237,7 +253,7 @@ class VideoPlayer { public _swap(videoPlayer: VideoPlayer) { if (!this.videoElement || !videoPlayer.videoElement) return; - + const nodeA = this.videoElement.parentElement; const nodeB = videoPlayer.videoElement.parentElement; // console.log(this.videoElement.attr('id')) @@ -278,31 +294,45 @@ class VideoPlayer { public async play() { if (!this.videoElement) return; - if (this.videoState === PlayerState.PLAYING) return; - - - const isPlaying = this.videoElement.currentTime > 0 && !this.videoElement.paused && !this.videoElement.ended && this.videoElement.readyState > this.videoElement.HAVE_CURRENT_DATA; + if (this.videoState === PlayerState.PLAYING || this.videoState === PlayerState.BUFFERING) return; + const isPlaying = this.videoElement.currentTime > 0 && !this.videoElement.paused && !this.videoElement.ended && this.videoElement.readyState > this.videoElement.HAVE_CURRENT_DATA; if (isPlaying) { console.log("already playing") return } + // debugger; // const video = document.getElementById(this.videoElement.id) // await video!.play() console.log("play") - await this.videoElement.play().catch(error => console.log(error)); //.catch(noop); + try{ + await this.videoElement.play(); + } + catch(error){ + console.log(error); + } } - public async pause() { + public pause() { if (!this.videoElement) return; if (this.videoState === PlayerState.PAUSE) return; - await this.videoElement.pause(); + try { + this.videoElement.pause(); + } + catch (error) { + console.log(error) + } } public stop() { if (!this.videoElement) return; - this.videoElement.pause(); - this.timeTo(this.getDuration() - 0.5); + try { + this.videoElement.pause(); + this.timeTo(this.getDuration() - 0.5); + } + catch (error) { + console.log(error) + } } public setControls(controls: boolean) { @@ -325,7 +355,8 @@ class VideoPlayer { if (time >= this.getDuration()) { this.videoElement.currentTime = this.getDuration() - 0.05; Logger.debug('timeTo: time is greater than duration'); - this.pause().then(noop); + console.log("timeTo") + this.pause(); return; } diff --git a/teleforma/templates/teleforma/course_media.html b/teleforma/templates/teleforma/course_media.html index 5e967f1c..ace6899c 100644 --- a/teleforma/templates/teleforma/course_media.html +++ b/teleforma/templates/teleforma/course_media.html @@ -94,7 +94,7 @@ $(document).ready(function(){ -
-- 2.39.5