Plays multiple media(videos or whiteboards) at the same time with synchronized progress and speed. Stops when the longest media ended.
AtomPlayer
: Abstract class for anything that is playable.NativeVideoPlayer
: For native<video>
element.VideoPlayer
: Forvideojs
supported media.WhiteboardPlayer
: For Netless Whiteboard replay room.OffsetPlayer
: Add blank offset before anAtomPlayer
.SelectionPlayer
: Cherry-pick segments of anAtomPlayer
.SyncPlayer
: Play groups ofAtomPlayer
s at the same time with synchronized progress and speed.
npm add @netless/sync-player
You may clone this repo and run the dev example.
import {
NativeVideoPlayer,
SyncPlayer,
OffsetPlayer,
} from "@netless/sync-player";
const player1 = new NativeVideoPlayer({
video: document.querySelector("#video1"),
name: "video1",
});
const player2 = new NativeVideoPlayer({
video: document.querySelector("#video2"),
name: "video2",
});
const syncPlayer = new SyncPlayer({ players: [player1, player2] });
syncPlayer.play();
You may add a time offset before any AtomPlayer
:
const video = videojs("#video1");
const videoPlayer = new VideoPlayer({ video, name: "video1" });
// wait 3s before actually playing
const offsetPlayer = new OffsetPlayer({ offset: 3000, player: videoPlayer });
// add css to hide the video element
video.toggleClass("hidden", !player.visible);
offsetPlayer.on("visibilitychange", () => {
video.toggleClass("hidden", !player.visible);
});
You may trim any AtomPlayer
to selected parts by providing a selection list.
const video = document.querySelector("#video1");
const videoPlayer = new NativeVideoPlayer({ video, name: "video1" });
console.log(videoPlayer.duration); // let's say it's 15000
const selectionPlayer = new SelectionPlayer({
player: videoPlayer,
selectionList: [
{ start: 0, duration: 1000 },
{ start: 3000, duration: 9000 },
],
});
console.log(selectionPlayer.duration); // 7000
Sync videos with Netless Whiteboard Replay.
import videojs from "video.js";
import { VideoPlayer, WhiteboardPlayer, SyncPlayer, OffsetPlayer } from "@netless/sync-player";
const videoPlayer1 = new VideoPlayer({ video: videojs("#video1"), name: "video1" });
const videoPlayer2 = new VideoPlayer({ video: videojs("#video2"), name: "video2" });
const sdk = new WhiteWebSdk({ ... });
const room = await sdk.replayRoom({ ... });
room.bindHtmlElement(el);
const whiteboardPlayer = new WhiteboardPlayer({ player: room });
const syncPlayer = new SyncPlayer({ players: [videoPlayer1, videoPlayer2, whiteboardPlayer] });
syncPlayer.play();
import { AtomPlayer, SyncPlayer } from "@netless/sync-player";
const syncPlayer: AtomPlayer = new SyncPlayer({ ... });
syncPlayer.play();
syncPlayer.pause();
syncPlayer.stop();
syncPlayer.seek(200);
Duration(in millisecond) of the longest media.
console.log(syncPlayer.duration);
syncPlayer.on("durationchange", () => {
console.log(syncPlayer.duration);
});
Player progress time(in millisecond).
console.log(syncPlayer.currentTime);
syncPlayer.seek(1000);
syncPlayer.on("timeupdate", () => {
console.log(syncPlayer.currentTime);
});
Player status.
Pause
Player paused by user invokingplayer.pause()
.Ready
Player paused by controller.Buffering
Player is buffering.Playing
Player is playing.Ended
Player ends.
// Ready | Pause | Buffering | Playing | Ended
console.log(syncPlayer.status);
syncPlayer.on("status", () => {
console.log(syncPlayer.status);
});
0~1
. Playback speed, or rate, of a player.
console.log(syncPlayer.playbackRate);
syncPlayer.setPlaybackRate(0.5);
syncPlayer.on("ratechange", () => {
console.log(syncPlayer.playbackRate);
});
A hint for visibility changes for OffsetPlayer
. player.visible
is false
when currentTime
is within the offset.
console.log(syncPlayer.visible);
syncPlayer.on("visibilitychange", () => {
console.log(syncPlayer.visible);
});