mirror of
https://github.com/tsightler/ring-mqtt.git
synced 2025-10-30 03:31:44 +08:00
116 lines
3.7 KiB
JavaScript
116 lines
3.7 KiB
JavaScript
import { Worker } from 'worker_threads'
|
|
import dgram from 'dgram'
|
|
|
|
export class LiveStream {
|
|
constructor(device) {
|
|
this.altVideoData = false
|
|
this.mqttCamera = device
|
|
this.rtpSocket = false
|
|
this.rtcpSocket = false
|
|
this.session = false
|
|
this.status = 'inactive'
|
|
|
|
this.worker = new Worker('./devices/stream/live-worker.js', {
|
|
workerData: {
|
|
doorbotId: this.mqttCamera.device.id,
|
|
deviceName: this.mqttCamera.deviceData.name
|
|
}
|
|
})
|
|
|
|
this.worker.on('message', (message) => {
|
|
if (message.type === 'state') {
|
|
switch (message.data) {
|
|
case 'active':
|
|
this.status = 'active'
|
|
this.session = true
|
|
this.altVideoData = message.altVideoData
|
|
this.bindAltVideoPorts()
|
|
break
|
|
case 'inactive':
|
|
this.clearSession('inactive')
|
|
break
|
|
case 'failed':
|
|
this.clearSession('failed')
|
|
break
|
|
}
|
|
this.mqttCamera.publishStreamState()
|
|
} else {
|
|
switch (message.type) {
|
|
case 'log_info':
|
|
this.mqttCamera.debug(message.data, 'wrtc')
|
|
break
|
|
case 'log_error':
|
|
this.mqttCamera.debug(message.data, 'wrtc-error')
|
|
break
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
clearSession(status) {
|
|
this.altVideoData = false
|
|
this.session = false
|
|
this.status = status
|
|
this.unbindAltVideoPorts()
|
|
}
|
|
|
|
bindAltVideoPorts() {
|
|
if (this.altVideoData) {
|
|
this.rtpSocket = dgram.createSocket('udp4')
|
|
this.rtcpSocket = dgram.createSocket('udp4')
|
|
this.rtpSocket.bind(this.altVideoData.port)
|
|
this.rtcpSocket.bind(this.altVideoData.port + 1)
|
|
}
|
|
}
|
|
|
|
unbindAltVideoPorts() {
|
|
if (this.rtpSocket) {
|
|
this.rtpSocket.close()
|
|
}
|
|
if (this.rtcpSocket) {
|
|
this.rtcpSocket.close()
|
|
}
|
|
this.rtpSocket = false
|
|
this.rtcpSocket = false
|
|
}
|
|
|
|
async start(rtspPublishUrl) {
|
|
this.session = true
|
|
|
|
const streamData = {
|
|
rtspPublishUrl,
|
|
ticket: null
|
|
}
|
|
|
|
try {
|
|
this.mqttCamera.debug('Acquiring a live stream WebRTC signaling session ticket')
|
|
const response = await this.mqttCamera.device.restClient.request({
|
|
method: 'POST',
|
|
url: 'https://app.ring.com/api/v1/clap/ticket/request/signalsocket'
|
|
})
|
|
streamData.ticket = response.ticket
|
|
} catch(error) {
|
|
if (error?.response?.statusCode === 403) {
|
|
this.mqttCamera.debug('Camera returned 403 when starting a live stream. This usually indicates that live streaming is blocked by Modes settings.')
|
|
} else {
|
|
this.mqttCamera.debug(error)
|
|
}
|
|
}
|
|
|
|
if (streamData.ticket) {
|
|
this.mqttCamera.debug('Live stream WebRTC signaling session ticket acquired, starting live stream worker')
|
|
this.worker.postMessage({ command: 'start', streamData })
|
|
} else {
|
|
this.mqttCamera.debug('Live stream failed to initialize WebRTC signaling session')
|
|
this.clearSession('failed')
|
|
this.mqttCamera.publishStreamState()
|
|
}
|
|
}
|
|
|
|
async stop() {
|
|
if (this.session) {
|
|
this.worker.postMessage({ command: 'stop' })
|
|
}
|
|
this.clearSession('inactive')
|
|
}
|
|
} |