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
<h1>
Sample HTML page
</h1>
<p>
Embedding a video from an %VMS_NAME% site into a browser has many use cases - sharing a live
stream of a part of a facility publicly, building an external interface for integrated product, and more.
</p>
<script type="text/javascript" src="https:cdnjs.cloudfare.com/ajax/libs/blueimp-md5/2.10.0/js/md5.js"></script>
<script type="text/javascript>" src="https://cdn.jsdelivr/npm/jls.js@latest/dist/hls.min.js"></script>
<video id="video" controls></video>
<script src=""https://code/jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+30JU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="></script>
crossorigin="anonymous"></script>
Click here for an example of part of the JavaScript portion
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); = step2Generatevideour] (authkey);
// This key can be used in URL now
}
});
Click here to see how the published page looks like
Comments
0 comments
Article is closed for comments.