2

I am building a multimedia player that needs to control multiple other multimedia players on a page. In order to do that I want to have an area at the bottom of the page which contains a media playback controller (including a seekbar) that will control all other players on the page. For example, when a user hits the play button all the other players on the page starts playing.

I want to use a regular video/audio player, but instead of playing real content all I want is to have the controls, especially a seekbar which advances. The reason for not implementing playback controls on my own is because I want to use the power of video.js plugins (like event markers on the timeline).

I have managed to display a video.js player only with playback controls. In addition I have managed to set the duration. The problem is that the player doesn't play when I hit the play button nor calilng player.play().

This is because the player doesn't have a media source. video.js and the native player won't play without a media source.

Now, is there a way to force a player to play even without a source? Can I make it think it has one?

Thank you,

Matan Givoni
  • 1,080
  • 12
  • 34
  • You could always use javascript to check if your **html5 player** has a source. If it hasn't one, the **html5 player** is _done playing the video_. I can provide an example if needed. – Bird Jul 28 '18 at 13:40
  • You missed all the point, I don't want to have a source, I want a player that can play without a media source. That way I get the functionality of a multimedia player without having to have video or audio content. – Matan Givoni Jul 28 '18 at 13:44
  • When you say "_I want a player that can play without a media source_", what do you want it to play? In my opinion, if you don't have any content, it's fine to assume that that empty **html5 player** is done playing its content. – Bird Jul 28 '18 at 13:49
  • Again, I want to use the playback controls from a multimedia player (seekbar, play button, pause button an so on..) that will control multiple **other** players which are presented on the page. Instead of implementing the functionality myself I want to use the browser's audio/video player. Apparently I can't make a seekbar of player without any content to advance. **This is my question** - Can I somehow make a video/audio player play without any content? – Matan Givoni Jul 28 '18 at 13:56
  • In that case, you can't. The best thing to do in this situation is to feed the **html5 player** with a blank source (black screen) through javascript (if the player has no source). – Bird Jul 28 '18 at 14:05
  • Can you supply me with an example or direction on how to create a blank source? I have tried to create an empty `MediaSource` which is fed from an empty `ArrayBuffer` but with no success. I suspect I need to supply information like mp4/mp3 metadata in the buffer. – Matan Givoni Jul 28 '18 at 14:10

2 Answers2

2

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!!

Matan Givoni
  • 1,080
  • 12
  • 34
  • I've looked everywhere for something like this, but unfortunately I can't get your code to work. How are the play/pause methods triggered? The master controls do nothing for me still. Thanks! – lopsided Dec 14 '21 at 17:49
1

It's the same principle for images. If you don't have an image for some content, you need to have a backup plan : a placeholder image.

You can do the same with videos.

The simplest solution is to have in your project directory :

> placeholders
  |-- fakeVideo_short.mp4
  |-- fakeVideo-long.mp4
  |-- fakeAudio.mp3
  |-- ...

Whenever your upper media controller finds an empty player, you can just feed it a placeholder content.

It's an easy solution that allows you to focus more quickly on wants important : The media controller.

How to detect if a player needs a placeholder?

Well :

  1. Whenever a player finishes/consumes some content, if there is no more content available, you can feed it a placeholder.
  2. At the start of the app, if there are more players than there is content, you can feed a blank content (placeholders) to the empty players.
Bird
  • 572
  • 5
  • 15
  • I can't afford to make a fake video each time. What I am trying to implement is a player which synchronizes multiple multimedia files. For example, to play 4 video files (Assuming all of them were recorded briefly in the same time) you load them to my application, and you will be given a matrix and a main media controller underneath the matrix. All I want is a functional media controller which will be taken from video.js, a one with a seekbar that can advance without a real content from behind the scenes – Matan Givoni Jul 28 '18 at 14:34
  • Oh! No need to have multiple **fakeVideo** files. You just need one video file, let's say 3 seconds of black screen, and you loop it over and over again until some new content is available. I've used **video.js** in the past and I don't think it offers the functionality of controlling multiple videos through a player. You need to build your own media controllers (play, stop, etc). – Bird Jul 28 '18 at 14:51
  • Lets say the first video started at 00:03 and last video ended at 00:09, In that cast I want a blank video that will last 00:12 seconds. How can I load a 3 seconds blank video and make the player play is for 12 seconds? – Matan Givoni Jul 28 '18 at 15:44
  • I think that you should change the title to "How to simulate a continuous flow of video content on the client-side" or ask another question for the **length of the video** part. It seems like you want to generate some video placeholder in between actual live uploaded videos. This process should be done on a server and your app should listen to it. This way, you only need one player. – Bird Jul 28 '18 at 16:14