Local USB Camera

Hi there! I’m new to this whole home assistant thing, so apologies in advance, but I have tried searching around to see if anyone else is having my problem, and none of the solutions I found have worked.

Basically I just want to display my USB camera on my HA dashboard. The camera is plugged into the Raspberry Pi 4 (8GB) which is running HA. I can’t see any issues with the camera, I’m able to record video from it via ffmpeg when running as the homeassistant user, so that all seems to be fine.

I first started experimenting with the FFMPEG integration, and whacked the following in config.yml:

  - platform: ffmpeg
    name: local_usb_cam
    input: -i /dev/video0
    extra_arguments: -f video4linux2

Then when I restart HA, camera shows up in the media section, and there’s even a little thumbnail which looks right! However, when I try to view it I get this in the terminal:

2024-06-15 15:34:05.190 ERROR (stream_worker) [root] Uncaught thread exception
Traceback (most recent call last):
    output_vstream = container.add_stream(template=input_vstream)
  File "av/container/output.pyx", line 85, in av.container.output.OutputContainer.add_stream
ValueError: 'mp4' format does not support None codec

Okay, seems there’s some issues with codecs. I’ve tried adding -c:v libx264 -preset ultrafast -b:v 600k to extra_arguments and I still get the same error message AND the thumbnail no longer displays. If I add it to the input field I get a new error:

2024-06-15 15:40:52.229 ERROR (stream_worker) [homeassistant.components.stream.stream.camera.local_usb_cam] Error from stream worker: Error opening stream (ERRORTYPE_2, No such file or directory) 600k

After a bit of trial and error, it looks like that error is caused because something tried to open a stream at whatever the last argument in input field is, in this case 600k.

From my research, similar errors come up if the homeassistant user isn’t in the video or audio groups, but that user is definitely in both. They can record video via ffmpeg manually, and the issue persists if I run homeassistant as the regular pi user. Hence I really doubt its an issue of user permissions.

Okay, so a “direct” connection to the camera ain’t working. next i tried using RTSP with MediaMTX to setup a local RTSP server and stream my camera feed to it.

The relevant MediaMTX config line looks a bit like this:

runOnDemand: ffmpeg -loglevel error -f alsa -thread_queue_size 1024 -i default -r 5 -f v4l2 -i /dev/video0 -c:a aac -strict -2 -ac 1 -b:a 64k -ar 8000 -c:v libx264 -vf "fps=5" -preset ultrafast -tune zerolatency -b:v 500k -f rtsp -bufsize 500k rtsp://$RTSP_PORT/$MTX_PATH

I have tested and confirmed that I can indeed connect to it via VLC as an RTSP client, and I can set it up as a Generic Camera in HA, but it is REALLY flakey.

For example, I have tweaked the settings to swap between UDP and TCP to see if that makes a difference. If I choose UDP there is about a 50% chance I cannot save the settings due to some kind of timeout.

IF I can get past that step, then when I try to view the camera in the dashboard there is usually about a minute delay between opening up the stream and the video (and audio) coming through. Occasionally it will stop entirely until I close and re-open the stream.

I’ve also tried using the FFMPEG integration again, using the RTSP source (in TCP transport mode) as input. It’s a very similar story.

So, has anyone been able to get a local USB camera RELIABLY streaming via a dashboard? And if so, how? Any help would be really much appreciated!

I’ve seen some talk of using go2rtc and webrtc. As far as I can tell, it looks like a similarish plan to MediaMTX, so I’m reluctant to go through all the work just to get the same result. Has anyone experimented with both, is there better performance for one compared to the other?

I tried MediaMTX, but the CPU went over the top. I reverted to the MotionEye add-on.

That’s done the business! Motion is running beautifully, taking up a meager 11% of my Pi’s CPU.

It was a HUGE faff to setup though, I’ll post my steps here later, in case anyone else should find themselves in my situation.

thanks dude!