Overview
Embedding a video from an Nx Witness / Nx Meta 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 of how to pull a video from any Nx Witness / Nx Meta system and embed it in an external website.
Before you Begin
For this example, we will use our the following, fictional, system:
- address: 192.168.178.10:7001
- username: test@networkoptix.com
- password: NxTestUser
- cameraId: a02d3776-a7eb-faea-97d5-6251c1694151 (How to find cameraId in your system: LINK)
JavaScript
var username = 'test@networkoptix.com';
var password = 'NxtestUser';
var cameraId = 'a02d3776-a7eb-faea-97d5-6251c1694151';
var serverAddress = "https://192.168.178.10: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 server-side (backend) to avoid sending password 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 Server:
Visit http://localhost:7001/static/index.html#/developers/api if you have Nx Server installed on your computer, 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://localhost:7001/static/index.html#/developers/api/Calculating%20authentication%20hash
- Using it in URL: http://localhost: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 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 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 on the device with the server application installed: http:/localhost: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 two 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 = 'test@networkoptix.com';\
var password = 'NxTestUser';
var cameraId = 'a02d3776-a7eb-faea-97d5-6251c1694151';
var systemId = '3770508e-569a-423b-a61a-a85abb0ffff2';
var serverCloudAddress = "https://" + systemId + ".relay.vmsproxy.com";
var serverLocalAddress = "https://192.168.178.10: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

Click here to see how the published page looks like

Questions
If you have any questions related to this topic or you want to share your experience with other community members or our team, please visit and engage in our support community or reach out to your local reseller.
Comments
0 comments
Article is closed for comments.