@survilla/public-video-player
v1.0.1
Published
This is public javascript ESM library to play video (liveview or recordings) of Survilla.
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>