Videos
Devices can add support for streaming video, which can be viewed from the mobile app & dashboards.
Your app's devices can let Homey know that they support a video stream. Once a front-end (e.g. the Homey app for iOS & Android) requests to start watching, your app will receive a request to share the stream's details, such as URL and authentication. The app, nor Homey, does any transcoding, but acts as a broker between the camera and the front-end.
Supported Video Types
Homey supports video streams with WebRTC, RTSP, RTMP, HLS, DASH. Other types may be supported. Because the Homey Mobile App embeds a VLC media player, you can always try to see if your video type works.
Getting Started with Videos
To register a camera stream, your app needs to ask ManagerVideos first to create a video. Then, attach the video to your Device by calling Device.setCameraVideo
. Note that when a device has both an image and video with the same id
then the image will be used as a background image for the video while it is loading.
Example — WebRTC
This example shows a basic WebRTC camera stream.
import Homey from 'homey';
export default class MyWebRTCDevice extends Homey.Device {
/*
* WebRTC works by creating an offer SDP in the frontend, exchanging it for
* an answer SDP through the cameras API, and using that answer SDP in the
* frontend to set up the connection.
*/
async onInit() {
try {
const video = await this.homey.videos.createVideoWebRTC();
/*
* This listener is called when the user opens the camera stream in the
* mobile app. The argument is an SDP offer generated by the mobile appp.
*/
video.registerOfferListener(async (offerSdp) => {
// Normally, you would call an API to exchange an SDP offer for an SDP answer
const result = await this.oAuth2Client.createStream(offerSdp);
return {
answerSdp: result.answerSdp,
};
});
/*
* Attach the camera to the device.
*/
await this.setCameraVideo('main', 'Main Camera', video);
} catch (err) {
this.error('Error creating camera:', err);
}
}
}
Example — WebRTC without Data Channel
This example shows a WebRTC camera without a data channel, and a keepalive listener.
import Homey from 'homey';
export default class MyWebRTCDevice extends Homey.Device {
/*
* Some cameras require a data channel in order to work, while other cameras
* only work when the offer does not contain a data channel. This can be
* customized through the options object in the createCamera method.
*
* There are also cameras that only keep their stream open for a few minutes.
* These can often be extended through an API call. The keep alive listener
* can be used to send such a request.
*/
async onInit() {
try {
const video = await this.homey.videos.createVideoWebRTC({
dataChannel: false, // default: true
});
/*
* The offer listener now also returns a stream ID next to the anwer
* SDP. This stream ID can be used to identify the stream in the
* keep alive listener.
*/
video.registerOfferListener(async (offerSdp) => {
// Normally, you would call an API to exchange an SDP offer for an SDP answer
const result = await this.oAuth2Client.createStream(offerSdp);
return {
answerSdp: result.answerSdp,
streamId: result.streamId,
};
});
/*
* The keep alive callback has a streamId argument that can be used
* to identify the stream. Most APIs require such an identifier in
* the request to extend the stream.
*/
video.registerKeepAliveListener(async (streamId) => {
// Normally, you would call an API to keep the stream alive
await this.oAuth2Client.extendStream(streamId);
});
await this.setCameraVideo('main', 'Main Camera', video);
} catch (err) {
this.error('Error creating camera:', err);
}
}
}
Example — RTSP
This example shows an RTSP camera, which is as simple as providing an URL. In this example, we use HTTP Basic Authentication (username:password@...
) in the URL.
import Homey from 'homey';
export default class MyRTSPDevice extends Homey.Device {
/*
* To play an RTSP stream, you simply need to return the URL to the stream
* from the video url listener. Some streams require authentication in
* different formats. This example uses query parameters for authentication.
*/
async onInit() {
try {
const video = await this.homey.videos.createVideoRTSP({
allowInvalidCertificates: true,
demuxer: 'h265',
});
/*
* The video url listener takes no arguments. It simply builds the
* URL to the RTSP stream using the username and password.
*/
video.registerVideoUrlListener(async () => {
// Get the username and password that were set during pairing
const {
username,
password,
} = this.getSettings();
// Normally, you would get the device's IP from Discovery, or another method
return {
url: `rtsp://${username}:${password}@192.168.1.100:554/stream`
};
});
/*
* Attach the camera to the device.
*/
await this.setCameraVideo('main', 'Main Camera', video);
} catch (err) {
this.error('Error creating camera:', err);
}
}
}
Example — RTMP
This example shows an RTMP camera, which is as simple as providing an URL. It's very similar to RTSP.
import Homey from 'homey';
export default class MyRTMPDevice extends Homey.Device {
async onInit() {
try {
const video = await this.homey.videos.createVideoRTMP();
/*
* The video url listener takes no arguments. It simply builds the
* URL to the RTMP stream.
*/
video.registerVideoUrlListener(async () => {
// Normally, you would get the device's IP from Discovery, or another method
return {
url: `rtmp://@192.168.1.100:1935`
};
});
/*
* Attach the camera to the device.
*/
await this.setCameraVideo('main', 'Main Camera', video);
} catch (err) {
this.error('Error creating camera:', err);
}
}
}
Example — HLS
This example shows an HLS camera, which is as simple as providing an URL. It's very similar to RTSP.
import Homey from 'homey';
export default class MyHLSDevice extends Homey.Device {
async onInit() {
try {
const video = await this.homey.videos.createVideoHLS();
/*
* The video url listener takes no arguments. It simply builds the
* URL to the HLS stream.
*/
video.registerVideoUrlListener(async () => {
// Normally, you would get the device's IP from Discovery, or another method
return {
url: `http://@192.168.1.100/stream.m3u8`
};
});
/*
* Attach the camera to the device.
*/
await this.setCameraVideo('main', 'Main Camera', video);
} catch (err) {
this.error('Error creating camera:', err);
}
}
}
Example — DASH
This example shows an DASH camera, which is as simple as providing an URL. It's very similar to RTSP.
import Homey from 'homey';
export default class MyDASHDevice extends Homey.Device {
async onInit() {
try {
const video = await this.homey.videos.createVideoDASH();
/*
* The video url listener takes no arguments. It simply builds the
* URL to the DASH stream.
*/
video.registerVideoUrlListener(async () => {
// Normally, you would get the device's IP from Discovery, or another method
return {
url: `http://@192.168.1.100/stream.mpd`
};
});
/*
* Attach the camera to the device.
*/
await this.setCameraVideo('main', 'Main Camera', video);
} catch (err) {
this.error('Error creating camera:', err);
}
}
}
Apps SDK Reference
Please refer to ManagerVideos in the Apps SDK Reference to learn more about videos in your app.
Last updated
Was this helpful?