JS Camera SDK
The Nabto WebRTC SDK is available for JavaScript on npm.
The package @nabto/webrtc-signaling-device is used when creating a Nabto WebRTC Device or Camera application. This is mostly used for demos since most real IoT Cameras does not run on Javascript, but C++ or another language suitable for embedded devices.
npm install --save @nabto/webrtc-signaling-device
The package @nabto/webrtc-signaling-util provides utilities which can be used in both client and device applications.
npm install --save @nabto/webrtc-signaling-util
Quick Start
This simple quickstart creates a very simple html page which runs some JavaScript which serves the webcam of the machine to remote clients connecting. Use this simple example together with the Nabto WebRTC React Demo.
The source for this very simple example can be found here.
First we create a very simple html component which loads the javascript:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Very Simple Nabto WebRTC JavaScript Device/Camera Example</title>
</head>
<body>
<script type="module" src="/main.js" defer></script>
</body>
</html>
Then we create a very simple JavaScript application which connects to the Nabto WebRTC Signaling Service. When a client connects a new RTCConnectionHandler is created which serves the local webcam to the remote client. This is purposely made really simple, and does not handle releasing of resources or handling of errors.
import { createSignalingDevice } from '@nabto/webrtc-signaling-device'
import { PerfectNegotiation, DeviceTokenGenerator, createDeviceMessageTransport, DeviceMessageTransportSecurityMode, SignalingEventHandler } from '@nabto/webrtc-signaling-util'
const productId = "...";
const deviceId = "...";
const sharedSecret = "...";
const privateKey = `-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----` // a private key in PEM format.
class RTCConnectionHandler {
messageTransport;
constructor(signalingDevice, channel) {
this.messageTransport = createDeviceMessageTransport(signalingDevice, channel, { securityMode: DeviceMessageTransportSecurityMode.SHARED_SECRET, sharedSecretCallback: async (keyId) => { return sharedSecret; } });
this.messageTransport.on("setupdone", async (iceServers) => {
const pc = new RTCPeerConnection({ iceServers: iceServers });
new PerfectNegotiation(pc, this.messageTransport);
new SignalingEventHandler(pc, signalingDevice);
const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: false });
stream.getTracks().forEach((track) => {
pc.addTrack(track);
})
})
}
}
function createDevice() {
const tokenGenerator = new DeviceTokenGenerator(productId, deviceId, privateKey);
const signalingDevice = createSignalingDevice({ productId: productId, deviceId: deviceId, tokenGenerator: () => { return tokenGenerator.generateToken() } });
signalingDevice.onNewSignalingChannel = (channel, authorized) => {
new RTCConnectionHandler(signalingDevice, channel);
}
signalingDevice.start();
}
createDevice();