I have figured out a solution that works.
Again the purpose is having working media controllers from video.js without loading any media content and the most important controller is the seek bar.
I have been playing with video.js and was trying to make the seek bar advance without loading any media content and found out that calling player.currentTime()
does actually updates the curretTime
internal member but doesn't update the UI.
Eventually I found out that in order to make video.js update the UI we need to trigger the timeupdate
event.
So I decided to implement a fake player that has control over all the other players and uses a video.js player as his UI (by showing only the media controls and hiding the video).
The fake player need to use a precise timer as mentioned here.
Conceptual example:
import videojs from 'video.js';
class MainMediaController {
public static readonly INTERVAL = 250;
protected _playerId: string;
protected _duration: number;
protected _mediaController: videojs.Player;
protected _childPlayers: videojs.Player[];
protected _currentTime: number;
private _interval: number;
private _intervalId: number;
constructor(playerId: string, recordingDuration: number, childPlayers: videojs.Player[]) {
this._playerId = playerId; // id of the player at the bottom of the page which will be served as the main timeline
this._duration = recordingDuration;
this._interval = MainMediaController.INTERVAL;
this._childPlayers = childPlayers;
this._currentTime = 0;
}
public async init() {
this._mediaController = videojs(this._playerId);
// await for ready state
await new Promise((resolve, reject) => {
this._mediaController.ready(() => {
resolve();
});
});
// set duration for a correct seek bar (longest.endTime - first.startTime)
this._mediaController.duration(this._duration);
}
public play(){
// update UI every 250ms
this._intervalId = setInterval(this.intervalStep.bind(this), this._interval);
for(let player of this._childPlayers){
player.play();
}
}
private intervalStep(){
this._currentTime += 0.250; // 250ms
this._mediaController.currentTime(this._currentTime);
this._mediaController.trigger("timeupdate"); // trigger() is accessible don't worry
}
public pause(){...}
public stop(){...}
public seek(){...}
}
That solution let me use video.js plugins in my main timeline that has no video in it!!