Embedding a video from an Nx Witness system into a browser has many use cases — sharing a live stream of a part of a facility publicly, building an external interface for integrated products, and more. Below is a step-by-step guide outlining a method on how to pull a video from any Nx Witness system and embed it on an external website.
Before you Begin
For this example, we will use a generic system:
- address: 127.0.0.1:7001
- username: user@example.com (be sure to use your cloud account in case of accessing a system via cloud)
- password: password123
- cameraId: a02d3776-a7eb-faea-97d5-6251c1694151 (How to find cameraid in your system)
JavaScript
var username = 'user@example.com';
var password = 'password123';
var cameraId = 'a02d3776-a7eb-faea-97d5-6251c1694151';
var serverAddress = "https://127.0.0.1:7001";
Install the following libraries:
- MD5 generator: https://github.com/blueimp/JavaScript-MD5 (you can use any alternative library)
- HLS player: https://github.com/video-dev/hls.js/
HTML
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-md5/2.10.0/js/md5.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/hls.js@latest/dist/hls.min.js"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
crossorigin="anonymous"></script>
Security
- When you embed the video on a website - always create a dedicated user with limited permissions (ideally - only live viewing for specific public cameras)
- It is better to generate the link on the server-side (backend) to avoid sending passwords with source code to the browser
Step 1: Authentication
To embed a video, you need to use URL-based authentication. It works like this:
- request special session key from the server
- using that key and password generate an authentication key
- use this key in the URL
Find the API documentation when you install Nx Witness Server:
- If you have Nx Witness Server installed on your computer visit http://localhost:7001/static/index.html#/developers/api
- Otherwise, replace the localhost with an IP address if the server is installed in the local network.
You can find detailed documentation here:
- Calculating a hash: http://127.0.0.1:7001/static/index.html#/developers/api/Calculating%20authentication%20hash
- Using it in URL: http://127.0.0.1:7001/static/index.html#/developers/api/URL-based%20authentication
JavaScript
$.ajax({
url: serverAddress +"/api/getNonce",
type: "GET",
success: function (response) {
var realm = response.reply.realm;
var nonce = response.reply.nonce;
var digest = md5(username + ":" + realm + ":" + password);
var partial_ha2 = md5("GET" + ":");
var simplified_ha2 = md5(digest + ":" + nonce + ":" + partial_ha2);
var authKey = btoa(username + ":" + nonce + ":" + simplified_ha2);
callback(authKey); // This key can be used in URL now
}
});
In this example, we use the jQuery library to make the API request and open-source Javascript implementation of MD5.
Important note: The authentication key expires from time to time, so you cannot create a permanent video link. Make sure you generate it every time the page opens.
Step 2: Generate a video link (cloud/local)
The recommended video format for embedding video is HLS. It does not require transcoding on the server-side, but works for h.264 cameras only (most cameras support this codec).
You can find detailed documentation here: http://127.0.0.1:7001/static/index.html#/developers/api/hls/%3CcameraId%3E.m3u
JavaScript
var cameraURL = serverAddress + '/hls/' + cameraId + '.m3u8?lo&auth=' + authKey;
Step 3: Use player
HLS videos can be embedded to any modern browser using hls.js library: https://github.com/video-dev/hls.js/
JavaScript
var video = document.getElementById('video');
if (Hls.isSupported()) {
var hls = new Hls();
hls.loadSource(cameraURL);
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, function() {
video.play();
});
}
Step 4: Understanding the technical limitations & overcoming them using Nx Cloud
It is important to understand a few limitations:
- The video will work only if the browser can reach the system. If you are using your server’s IP address - the video will not be accessible outside of the local network.
- If you embed the video on the secure website (using HTTPS) - requests might not work, because the browser doesn’t trust the server’s self-signed certificate.
- The browser may have a limit of 5-7 connections per domain.
Note: To overcome both limitations you can use Nx Cloud (Routing API calls via Nx Cloud).
HTML
<video id="video" controls></video>
Javascript
var systemId = '3770508e-569a-423b-a61a-a85abb0ffff2';
var serverAddress = "https://" + systemId + ".relay.vmsproxy.com";
Step 5: Putting it all together
In the end, the HTML and JavaScript should look similar to the code below.
HTML
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-md5/2.10.0/js/md5.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/hls.js@latest/dist/hls.min.js"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
crossorigin="anonymous"></script>
<video id="video" controls></video>
Javascript
var username = 'user@example.com';
var password = 'password123';
var cameraId = 'a02d3776-a7eb-faea-97d5-6251c1694151';
var systemId = '3770508e-569a-423b-a61a-a85abb0ffff2';
var serverCloudAddress = "https://" + systemId + ".relay.vmsproxy.com";
var serverLocalAddress = "https://127.0.0.1:7001";
var serverAddress = serverCloudAddress; // serverLocalAddress;
function step1GenerateKey() {
$.ajax({
url: serverAddress + "/api/getNonce",
type: "GET",
success: function(response) {
var realm = response.reply.realm;
var nonce = response.reply.nonce;
var digest = md5(username + ":" + realm + ":" + password);
var partial_ha2 = md5("GET" + ":");
var simplified_ha2 = md5(digest + ":" + nonce + ":" + partial_ha2);
var authKey = btoa(username + ":" + nonce + ":" + simplified_ha2);
step2GenerateVideoUrl(authKey); // This key can be used in URL now
}
});
}
function step2GenerateVideoUrl(authKey) {
var cameraURL = serverAddress + '/hls/' + cameraId + '.m3u8?lo&auth=' + authKey;
console.log(cameraURL); // this URL can be tested with VLC player for verification. VLC should not ask for additional credentials
step3InitPlayer(cameraURL);
}
function step3InitPlayer(cameraURL) {
var video = document.getElementById('video');
if (Hls.isSupported()) {
var hls = new Hls();
hls.loadSource(cameraURL);
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, function() {
video.play();
});
}
}
step1GenerateKey();
Visual Example
Using the format described above, we created a sample HTML of what its implementation could look like.
Note: The video displayed in image 3 is a live stream, although it will have a timestamp that indicates how much time has elapsed in the live stream.
Click here for an example of the HTML portion
Click here for an example of part of the Javascript portion
Comments
0 comments
Article is closed for comments.