NRCHKB / node-red-contrib-homekit-bridged

Node-RED Contribution - HomeKit Bridged : Node-RED nodes to simulate Apple HomeKit devices.
https://nrchkb.github.io
MIT License
416 stars 52 forks source link

[Help needed]: Camera with non-host network mode in Docker deployment #538

Closed Nurgak closed 8 months ago

Nurgak commented 8 months ago

Your Current NRCHKB Plugin Version

1.5.0

Operating System

Raspberry Pi, Docker

How can we help?

I am attempting to run Node-RED in docker and use this package to deploy HomeKit devices.

So far I've successfully connected a bridge by exposing a (random) port 16000, installing avahi on the host and configuring the bridge appropriately:

Screenshot 2024-01-14 at 15 39 55

The docker-compose file also needs the following volumes shared to the Node-RED instance:

- /var/run/dbus:/var/run/dbus
- /var/run/avahi-daemon/socket:/var/run/avahi-daemon/socket

What I struggle with is getting the camera to work. The camera is recognized and snapshots are sent to Home.app, but the stream is not working. The stream only works when the Node-RED docker image is deployed with network_mode = "host" option in docker-compose.

I tried to understand why the stream was not working. It looks like the stream needs another port, I do not understand where this port definition is coming from. I would gladly open yet another port for this purpose, but it looks quite random from what I've seen from the debug log: the port changes every time I request the stream.

Error messages in the log

nodered  | 2024-01-14T06:55:20.553Z CameraSource Request type: start
nodered  | 2024-01-14T06:55:20.589Z CameraSource Start streaming video from Camera with 1280x720@299kBit
nodered  | 2024-01-14T06:55:20.590Z CameraSource ffmpeg -re -stream_loop -1 -i /data/test.mp4 -map 0:0 -vcodec libx264 -pix_fmt yuv420p -r 10 -f rawvideo -tune zerolatency -vf scale=1280:720 -b:v 299k -bufsize 299k -maxrate 299k -payload_type 99 -ssrc 5265648 -f rtp -srtp_out_suite AES_CM_128_HMAC_SHA1_80 -srtp_out_params dvQKeimErID0Mrbbrn44OxUc0JT0KHA6CIhVsJKu srtp://192.168.3.79:60881?rtcpport=60881&localrtcpport=60881&pkt_size=1316 -loglevel debug
nodered  | 2024-01-14T06:55:20.593Z CameraSource-Error An error occurred while making stream request
nodered  | 2024-01-14T06:55:20.600Z CameraSource-Error Error: spawn ffmpeg ENOENT
nodered  |     at Process.ChildProcess._handle.onexit (node:internal/child_process:285:19)
nodered  |     at onErrorNT (node:internal/child_process:485:16)
nodered  |     at processTicksAndRejections (node:internal/process/task_queues:83:21) {
nodered  |   errno: -2,
nodered  |   code: 'ENOENT',
nodered  |   syscall: 'spawn ffmpeg',
nodered  |   path: 'ffmpeg',
nodered  |   spawnargs: [
nodered  |     '-re',
nodered  |     '-stream_loop',
nodered  |     '-1',
nodered  |     '-i',
nodered  |     '/data/test.mp4',
nodered  |     '-map',
nodered  |     '0:0',
nodered  |     '-vcodec',
nodered  |     'libx264',
nodered  |     '-pix_fmt',
nodered  |     'yuv420p',
nodered  |     '-r',
nodered  |     '10',
nodered  |     '-f',
nodered  |     'rawvideo',
nodered  |     '-tune',
nodered  |     'zerolatency',
nodered  |     '-vf',
nodered  |     'scale=1280:720',
nodered  |     '-b:v',
nodered  |     '299k',
nodered  |     '-bufsize',
nodered  |     '299k',
nodered  |     '-maxrate',
nodered  |     '299k',
nodered  |     '-payload_type',
nodered  |     '99',
nodered  |     '-ssrc',
nodered  |     '5265648',
nodered  |     '-f',
nodered  |     'rtp',
nodered  |     '-srtp_out_suite',
nodered  |     'AES_CM_128_HMAC_SHA1_80',
nodered  |     '-srtp_out_params',
nodered  |     'dvQKeimErID0Mrbbrn44OxUc0JT0KHA6CIhVsJKu',
nodered  |     'srtp://192.168.3.79:60881?rtcpport=60881&localrtcpport=60881&pkt_size=1316',
nodered  |     '-loglevel',
nodered  |     'debug'
nodered  |   ]
nodered  | }
nodered  | 2024-01-14T06:55:20.606Z CameraSource-Error ERROR: FFmpeg exited with code -2

Could somebody help me understand what's preventing the camera stream from being delivered to the Home.app?

Any more details?

No response

Any code or functions to add?

No response

NorthernMan54 commented 8 months ago

Under the covers this uses the same package as homebridge for HomeKit devices, so you need network_mode = host same as homebridge

see https://github.com/homebridge/docker-homebridge

Shaquu commented 8 months ago

I believe responsible code is placed within hap-nodejs.

    this.service.getCharacteristic(Characteristic.SetupEndpoints)!
        .on(CharacteristicEventTypes.GET, callback => {
          callback(null, this.setupEndpointsResponse);
        })
        .on(CharacteristicEventTypes.SET, (value, callback, context, connection) => {
          if (!connection) {
            debug("Set event handler for SetupEndpoints cannot be called from plugin. Connection undefined!");
            callback(HAPStatus.INVALID_VALUE_IN_REQUEST);
            return;
          }
          this.handleSetupEndpoints(value, callback, connection);
        });

My theory: During stream open in Home.app, app SET a SetupEndpoints value (handleSetupEndpoints). Value is tlv and it holds targetVideoPort at address 0x03.

So, since Home.app decides a port, you have to use host mode (??).

Nurgak commented 8 months ago

@NorthernMan54 Thank you for your answer. Your comment led me to search the homebridge repo and I found a similar question that answers my question.

Basically, stream port depends on the application, the port is defined by the stream requester and cannot be defined by the user. Therefore, one necessarily needs host network mode when running in docker to use the camera.

However, if you do not need to use the camera node and you configure Node-RED just right you do not necessarily need host mode.