]> git.parisson.com Git - teleforma.git/commitdiff
WIP
authorYoan Le Clanche <yoanl@pilotsystems.net>
Wed, 29 Jan 2025 16:37:03 +0000 (17:37 +0100)
committerYoan Le Clanche <yoanl@pilotsystems.net>
Wed, 29 Jan 2025 16:37:03 +0000 (17:37 +0100)
teleforma/src/js/video/SyncVideoPlayer.ts
teleforma/src/js/video/VideoComponent.vue
teleforma/src/js/video/VideoPlayer.ts
teleforma/templates/teleforma/course_media.html

index ae304a8136f1ceb41f7620c30593beaec7362f19..cbcea115d6587d3834d32022ef0dd74383b4115d 100644 (file)
@@ -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);
     });
   }
 
index 2ebfbaa49a4394da286a23903f5bba148eca7674..314ca56cad9e75acee4b13191fd4c7551b7ab749 100644 (file)
@@ -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) {
           <div class="box" id="video-0" :key="0" @click="onClick(0)" @touchend="onClick(0)"></div>
         </div>
         <div id="thumbnails-videos">
-          <div
-            v-for="(id, i) in ids.slice(1)"
-            class="box"
-            :id="id"
-            :key="i + 1"
-            @click.prevent="onClick(i + 1)"
-            @touchend.prevent="onClick(i + 1)"
-          ></div>
+          <div v-for="(id, i) in ids.slice(1)" class="box" :id="id" :key="i + 1" @click.prevent="onClick(i + 1)"
+            @touchend.prevent="onClick(i + 1)"></div>
         </div>
       </div>
     </div>
index 0119d90cb58a886f0791bb276ba377bb7547bb2b..99e77442ea88165cd325a4c2d47c0cae49d1a78e 100644 (file)
@@ -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;
     }
 
index 5e967f1cedfe114fe34af704be431545c75c896a..ace6899c0c5091864b47da87476754dda2b4f722 100644 (file)
@@ -94,7 +94,7 @@ $(document).ready(function(){
 
 
 
-<script>
+<!-- <script>
 window.multivideos = [
     {
       id: "#video-0",
@@ -115,6 +115,28 @@ window.multivideos = [
       initialSrc: "https://e-learning.crfpa.pre-barreau.com/media/TEST/2024/1/monitor_4.webm-02_26_24-16:34:19-377319.mp4"
     },
 ]
+</script> -->
+<script>
+window.multivideos = [
+    {
+      id: "#video-0",
+      controls: true,
+      main: true,
+      sound: true,
+      initialSrc:
+        "https://trackers.pilotsystems.net/prebarreau/0867/thread004/_files/0d/0da2b732-dd51-11ef-b984-9201d6d72dfc/video-01.mp4"
+    },
+    {
+      id: "#video-1",
+      // startSeconds: 0,
+      initialSrc:
+        "https://trackers.pilotsystems.net/prebarreau/0867/thread004/_files/09/09c2e218-dd51-11ef-8a35-9201d6d72dfc/video-02.mp4"
+    },
+    {
+      id: "#video-2",
+      initialSrc: "https://trackers.pilotsystems.net/prebarreau/0867/thread004/_files/0b/0b3cb3da-dd51-11ef-bc6e-9201d6d72dfc/video-03.mp4"
+    },
+]
 </script>
 <div id="multivideo"></div>
 <div class="video">