npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@survilla/public-video-player

v1.0.1

Published

This is public javascript ESM library to play video (liveview or recordings) of Survilla.

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

Documentation

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 it

Note: dont forget to call destroy() method to stop all timmers

example

Liveview 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 it

example

LiveStream example

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.ip is ip address of the camera (can include port eg. 0.0.0.0:5000)
  • camera.user, camera.pass are username and password to the camera
  • camera.rtspParam are parameters of the stream (eg. camera=1&resolution=640x480&fps=30)
  • reduceLatency decreases latency from 300ms to 150ms

methods

same as in Liveview

example

LocalLiveview example in grid

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 it

css

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

Recording 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 microseconds

Looper

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