@survilla/public-video-player
v1.0.1
Published
This is public javascript ESM library to play video (liveview or recordings) of Survilla.
Downloads
4
Maintainers
Readme
Public video player
This is public javascript ESM library to play video (liveview or recordings) of Survilla.
- Typescript is supported
Requirements
- To play video you need to have account in some survilla resseler (eg. Netrex https://www.netrex.cz/ or Camstreamer https://camstreamer.com/)
- create an API token and use it for authorization
- It uses Web codec (https://developer.mozilla.org/en-US/docs/Web/API/WebCodecs_API) and canvas to render the video.
- See minimal browser supported versions (https://caniuse.com/webcodecs).
Installation
There are two ways
Add library through script tag
Copy the file dist/survilla-player.js to your server and add to you html. Than you can use it as:
<script src="./survilla-player.js" type="module"></script>
<script type="module">
import { Liveview } from './survilla-player.js';
const liveview = new Liveview({
...
});
</script>Note: dont forget to add type="module" because the library is built as ES module.
Install via npm
Use some nodejs package manager npm or yarn
yarn add @survilla/public-video-playerDocumentation
Note: If you have multiple players on the page its recomended to use Looper
Liveview
- Liveview player
- Its automatically restarted on error
- Can be stopped and resumed
- If local connection fails it automatically switches to remote
- Dont forget to call destroy() method to stop all timmers
- Video is started by default
- Audio is turned off by default (browser cant play audio without user action)
constructor
{
canvas: HTMLCanvasElement;
connect: {
containerId: number;
apiToken: string;
dns?: string;
streamProfileId?: number | null;
isLocal?: boolean;
};
clbs?: {
onConnected?: () => void;
onError?: (e: unknown) => void;
onConnectionFailed?: () => void;
onSmartBufferLoad?: () => void;
};
looper?: Looper;
}methods
you can controll it via livePlayback
const liveview = new Liveview({ ... });
liveview.livePlayback.start(); // starts the liveview
liveview.livePlayback.stop(); // stops the liveview
liveview.livePlayback.setMute(true); // controll audio
liveview.livePlayback.setPaintMode('cover') // change paint mode: 'cover' | 'contain' | 'fill'
liveview.livePlayback.state; // you can read the player state: 'IDLE' | 'LOADING' | 'CONNECTING' | 'CONNECTED' | 'PAUSE' | 'RESTARTING' | 'DESTROYED'
liveview.destroy(); // stops liveview and destroy itNote: dont forget to call destroy() method to stop all timmers
example
LiveStream
- Liveview player
- its low layer player - no restarting, stoping, etc.
- constructor params are same as in Liveview
constructor
{
canvas: HTMLCanvasElement;
connect: {
containerId: number;
apiToken: string;
dns?: string;
streamProfileId?: number | null;
isLocal?: boolean;
};
clbs?: {
onConnected?: () => void;
onError?: (e: unknown) => void;
onConnectionFailed?: () => void;
onSmartBufferLoad?: () => void;
};
looper?: Looper;
}methods
there is on livePlayback, but liveCore that is a promise
const liveStream = new LiveStream({ ... });
const core = await liveStream.liveCore;
core.setMute(true); // controll audio
core.setPaintMode('cover') // change paint mode: 'cover' | 'contain' | 'fill'
await liveStream.destroy(); // stops liveStream and destroys itexample
LocalLiveview
- Liveview player that connects to the camera via ip address (port)
- It requires to have on camera EdgeRecording Acap installed
- automatically tries to reconnect if it fails
- Note: every LocalLiveview is opening new connection to the camera, if you open too many streams to one camera (multiple users will open it separetly) => you can overload the camera. If you use LiveStream or Liveview, there is only one connection to the camera and the streams are multiplied on our cloud.
constructor
{
canvas: HTMLCanvasElement;
camera: {
ip: string;
user: string;
pass: string;
rtspParam: string;
reduceLatency?: boolean;
};
clbs?: {
onConnected?: () => void;
onError?: (e: unknown) => void;
onConnectionFailed?: () => void;
onSmartBufferLoad?: () => void;
};
looper?: Looper;
}camera.ipis ip address of the camera (can include port eg.0.0.0.0:5000)camera.user,camera.passare username and password to the cameracamera.rtspParamare parameters of the stream (eg.camera=1&resolution=640x480&fps=30)reduceLatencydecreases latency from 300ms to 150ms
methods
same as in Liveview
example
Recording
- Recording player
- you are passing div as container to the constructor, where canvases will be created
- dont forget about css (see below)
constructor
{
container: HTMLDivElement;
connect: {
containerId: number;
apiToken: string;
dns?: string;
};
clbs?: {
onNoMoreRecording?: () => void;
onTimeChange?: (time: NrTime) => void;
};
range: {
start: NrTime;
end: NrTime;
};
looper?: Looper;
}methods
some of the setting methods are exposed: but there is a lot of more, just investigate methods of RecordingPlayerStore
const recording = new Recording({ ... });
recording.seek(time: NrTime); // seek to time (cant seek outside of defined range passed in constructor)
recording.play()
recording.pause();
recording.getTime(); // retuns current time as NrTime
recording.setMute(value: boolean); // mute and unmute audio
recording.downloadSnapshot(); // download current frame
recording.setPlaybackSpeed(speed: number); // change play speed
// look to recording.store. for more
recording.destroy(); // stops recording and destroys itcss
if you want to have video scaled to container, you have to add these css, where #container is the container you are passing to the Recording constructor
#container canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: contain;
opacity: 1;
transition-property: opacity;
transition-timing-function: linear;
transition-duration: 200ms;
}
#container canvas:not(.active) {
opacity: 0;
}example
NrTime
class used for time
const time = NrTime.fromS(1748604899); // absolute time in s
time.s // get seconds
time.ms // get miliseconds
time.us // get microsecondsLooper
- is moving the video forward
- use this if you have multiple players on the page
constructor
takes number, how often should be triggered in miliseconds
const looper = new Looper(5);
for(let i = 0; i < 4; i++){
new Liveview({ looper, .... });
}Note: Dont forget to destroy it
Examples
Simple liveview
<html>
<head>
<script src="./survilla-player.js" type="module"></script>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="module">
import { Liveview } from './survilla-player.js';
const liveview = new Liveview({
canvas: document.getElementById('canvas'),
connect: {
containerId: 91719,
apiToken: 'token',
},
});
</script>
</body>
</html>
Multiple liveviews
<html>
<head>
<script src="./survilla-player.js" type="module"></script>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
display: flex;
flex-wrap: wrap;
}
canvas {
width: 50%;
height: 50%;
box-sizing: border-box;
}
</style>
</head>
<body>
<canvas id="canvas0"></canvas>
<canvas id="canvas1"></canvas>
<canvas id="canvas2"></canvas>
<canvas id="canvas3"></canvas>
<script type="module">
import { LiveStream, Looper } from './survilla-player.js';
const looper = new Looper();
for (let i = 0; i < 4; i++) {
const canvas = document.getElementById(`canvas${i}`);
const liveStream = new LiveStream({
canvas: canvas,
connect: {
containerId: 91719,
apiToken: 'token',
},
looper,
});
}
</script>
</body>
</html>Recording
<html>
<head>
<script src="./survilla-player.js" type="module"></script>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
display: flex;
flex-wrap: wrap;
}
#container {
width: 100%;
height: 100%;
box-sizing: border-box;
}
#container canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: contain;
opacity: 1;
transition-property: opacity;
transition-timing-function: linear;
transition-duration: 200ms;
}
#container canvas:not(.active) {
opacity: 0;
}
</style>
</head>
<body>
<div id="container"></div>
<script type="module">
import { Recording, NrTime } from './survilla-player.js';
const recording = new Recording({
container: document.getElementById('container'),
connect: {
containerId: 92203,
apiToken: 'token',
},
range: {
start: NrTime.fromS(1748598757),
end: NrTime.fromS(1748599000),
},
});
recording.play();
</script>
</body>
</html>