A security camera NVR. (Help wanted! I'm developing it here: https://github.com/scottlamb/moonfire-nvr I'm proud of the design but it's still far from a polished system that does everything a reasonable person would expect. Lots of opportunities to extend it if you're looking for a fun Rust + Javascript project.) A Raspberry Pi 2 will run a working setup; the new Raspberry Pi 4 should be a lot more pleasant in terms of being able to recompile it in a reasonable time, transfer video segments quickly, etc. I think the biggest missing piece is a real-time clock. Faster flash, builtin SATA, and a builtin NPU would also be great of course but not realistic for $35.
A home theater control system. The Pi uses HDMI-CEC, my Samsung TV's EXLINK (their protocol over RS-232), Roku's HTTP interface, etc. and an Android app is the frontend. I wanted to make this into a nice polished thing other people could use but have given up on the idea for now. The thing is that media components are super finicky, many things need special support written just for them, and you really have to extensively tweak them to see how they function as a whole. (eg does your TV turn off your stereo receiver when it turns off itself. The answer varies based on the model and settings of both components.) HDMI-CEC doesn't live up to its potential in this regard.
Moonfire NVR looks like an amazing project that I can learn a lot from for an entirely different project with streams and stuff that I’m interested in and have zero experience with!
Also great that it’s written in rust
Is there any way to test it without rpi/camera?
If I understand the readme correctly, you store frames individually (as jpegs?) on disk and construct flexible mp4 streams on the fly. Naturally I would have assumed that this would be inefficient so I’m wondering if I got this right, not very familiar with stream/video/codec tech
Without a Raspberry Pi, yes. It should run on any Unix-like OS. I've tested Linux/arm32, Linux/x86-64, and macOS/x86-64. (For the last, install ffmpeg via homebrew first.)
Without an IP camera...hmm, there are probably some public RTSP live streams somewhere. Not sure offhand.
> If I understand the readme correctly, you store frames individually (as jpegs?) on disk and construct flexible mp4 streams on the fly. Naturally I would have assumed that this would be inefficient so I’m wondering if I got this right, not very familiar with stream/video/codec tech
No, I store the video stream in the compressed form the camera gave it to me. Currently that's H.264; it wouldn't be hard to add H.265 support as well. I break it apart into roughly one-minute segments at convenient locations. The schema design doc talks about that here: https://github.com/scottlamb/moonfire-nvr/blob/master/design...
.mp4 serving will aggregate those together (maybe clipping the start and end segment) to give you a .mp4 segment for any time range of interest. It comes up with a mp4::File struct which knows what video segments to serve and maps byte locations to parts of the .mp4 container format. I don't have a good doc about how this works other than the source code right now. https://github.com/scottlamb/moonfire-nvr/blob/master/src/mp... [edit: and you probably won't be successful in understanding it without having a pdf of the ISO/IEC 14496-12 specification open next to it.] Here's some debug output for generating a five-minute video segment: https://pastebin.com/Wzfz7BF7
Storing individual frames as jpegs would be inefficient I agree in all sorts of ways: recording CPU (you have to decode the H.264 and re-encode it as JPEGs), disk space, disk seeks, playback bandwidth, browser CPU, etc. My understanding is this is how Zoneminder currently works. I imagine it worked better with the cameras Zoneminder was originally designed for: low-resolution, low-qps webcams that didn't do their own H.264 encoding.
I've wanted some security cam software to run on a Pi for ages because the stuff shipped on my IP cameras is awful. Do you have any plans to offer a callback system, e.g. so when some customisable event happens (change detection, perhaps between certain hours of the day/night) it could then callback to a custom script for further processing?
My plan is to extend the HTTP API [1] with an event stream [2] that can be accessed via https-with-a-session-cookie or http-over-Unix-domain-socket. It could be used by browser-based Javascript, mobile clients, and automated event subscribers. One could write a subscriber that launches a subprocess or runs scripts in-process. I think there are a few advantages over doing this directly from the main process:
* it keeps the main process logic minimal. This API is needed anyway to make a good web interface.
* it's the easiest way to have nothing else run as the same Unix user as the main process. My design is similar to a DBMS in that that you should only ever be accessing Moonfire NVR's data through its interfaces (except for development or emergency maintenance purposes). Having a dedicated user helps enforce that.
* your script can run on a separate machine if desired
Also a couple disadvantages:
* two services to set up (main process + subscriber) instead of one.
* there's the possibility that an event happens while the main process is running but your subscriber is disconnected, so the event gets committed to the database but you never see it. The easiest thing to do is to accept skipping these (as would happen anyway if the main process is down). Or the main process could buffer events for a while. Or the watcher could have logic to "catch up" (which unfortunately means not only more complex logic but also keeping state somehow).
If you'd prefer another approach or want it sooner than I'm likely to implement it, please contribute! I have my priorities & design ideas, but if you chip in, you get a say in both. And I go pretty slowly on my own anyway, so if you're able, it's worth chipping in even if you agree with me about everything.
I've been looking for something like Moonfire! Do you have any recommendations for an outdoor camera, I was looking at Lorex but don't have much experience? Thanks!
I have a Dahua IPC-HDW5231R-Z that's worked quite well for me. But I haven't tried a lot of cameras, and your needs and budget may vary, so look at the ipcamtalk cliff notes: https://ipcamtalk.com/wiki/ip-cam-talk-cliff-notes/
It doesn't do enough work today to require that, given that it's meant for home use and doesn't decode/re-encode the video. One Raspberry Pi 4 with a couple 6 TB drives in an external USB3 SATA enclosure should be sufficient for 16+ cameras in terms of CPU, USB3 bandwidth, Ethernet bandwidth, spindle time, storage capacity, etc. If for some reason you need more security cameras than that in your home, you can probably afford a single machine beefy enough to handle it.
The only thing I anticipate being a significant performance challenge is on-NVR motion detection. Most likely that will end up being separate processes that download the video and annotate it via the HTTP API. Those workers could then run on separate machines if needed. The primary machine would have sufficient bandwidth to support this.
A home theater control system. The Pi uses HDMI-CEC, my Samsung TV's EXLINK (their protocol over RS-232), Roku's HTTP interface, etc. and an Android app is the frontend. I wanted to make this into a nice polished thing other people could use but have given up on the idea for now. The thing is that media components are super finicky, many things need special support written just for them, and you really have to extensively tweak them to see how they function as a whole. (eg does your TV turn off your stereo receiver when it turns off itself. The answer varies based on the model and settings of both components.) HDMI-CEC doesn't live up to its potential in this regard.
[edit: fixed hyperlink]