Inspiration
We live on a street where kids play in the front yards and cars come through way faster than they should. Everyone on the block agrees on that and is pretty worried, especially since we had one unfortunate incident already occur. I wanted to see if we could do anything to improve the safety of our road, and our Ring Camera seemed like a perfect option. First, I wanted to see, can we actually validate this is happening, how fast are people driving, when are they driving fastest, if we implement any safety measures, are they effective? I didn't see anything in the Ring app store yet to tackle this problem, so it seemed like the perfect candidate. Using Ring camera recordings, we can calculate how fast cars are driving, build dashboards on when they are driving most often and how fast, and alert if someone flies by way too fast above a specified limit. This just seemed so useful, and maybe if we had enough data we'd even be able to get the town to install a slow sign on our street, so kids and pets can be outside with a little bit less worry all around.
What it does
Speed Alert connects to the Ring cameras pointed at the street, and calculates their speed. For each car you get an estimated speed with an honest range ("41 mph, likely 34–47"). When one crosses the line you set, for example, over 40mph in this 20mph zone, you can get a marked up clip, and an alert email. The dashboard shows cars by hour, speed by hour, and the safest, busiest and fastest hours of the day, so you know when it might be safest to be outside.
It can also build for you what I think is my favorite feature, a printable street report card. In the case you want to go to, for example a town hall meeting asking for a "Slow" sign or a speed bump to improve safety, you now can at least come with some evidence. It includes charts and is written with numbers used commonly by traffic engineers, such at the 85th percentile speed and the share of traffic over the posted limit, followed by the distribution, the worst hours, and, if you choose, a few frames of the fastest cars so nobody can say the readings are made up. You can adjust the dates, and report on certain time periods and more.
What it deliberately doesn't do: read license plates, recognize faces, match cars to each other, or share anything between households. It describes the situation on the road, not the drivers. The report says so on the page, because a document you hand to a council should make the case for a speed bump, not against a neighbor. This isn't software designed to target individuals, its more so to understand and measure aggregate trends on your street, and see how often dangerous driving is occurring on your street.
How we built it
Building this was a fun and challenging project that incorporated lots of different moving parts. On the Camera side, the Ring Partner API provided what is needed to account link get motion webhooks, and download video clips from the cameras.
As motion events come in a Next.js app on Vercel receives the webhooks and queues each vehicle event in Postgres. A Python worker than can be deployed to anywhere (currently a server in the cloud) claims events from that queue, downloads the clip, runs an object detection algorithm (such as YOLO11) to detect and follow each vehicle frame by frame and return bounding boxes and confidence, and turns pixel motion into speed. Clips are deleted within a minute of being measured, we keep one thumbnail per car and a short marked-up clip only for cars over the alert line.
Storage and auth are handled by Supabase. I'm using Postgres with row-level security so every account only ever sees its own street, magic-link sign-in, a private bucket with signed URLs. Alerting runs as pg_cron rules inside Postgres, because the database is the one component that's still up when the worker or the web app isn't. Emails go through Resend. The worker runs on a Hetzner box in Docker and on a spare local computer I have that can also process video events. Any number of workers can pull from the queue to process video events.
The most interesting challenge however was how to improve and align the accuracy of the speed estimation as strong as possible. Obviously there can be many different camera placements, cars, vehicles, and times of day, and all of that can make it difficult to get accurate readings at all times. More on that below.
Challenges we ran into
The two most challenging things here were how to have the best possible accuracy for speed estimation from the camera footage, handling all possible edge cases, and how to keep costs down to a reasonable amount (processing video can be expensive).
Big Challenge #1: Accuracy/Processing The worker fetches the clip and uses ffprobe/ffmpeg to decode the frames and understand rate (the video headers turn out not to be fully accurate). Once the camera has learned where the road is, only that strip of the frame goes to the detector, YOLO11 small, on every frame. Detections go into ByteTrack, which stitches them into tracks, one per vehicle. The detector's confidence cutoff is deliberately low, 0.1: the tracker needs to see the 15%-sure detections to hold a car through a bad frame, and at 0.3 real cars broke into three short tracks with gaps between them.
Per track I throw away the first and last 10% of boxes (the ends of a track wobble), ignore any box touching the frame edge, and verify the class against the box's shape (object detection produces a 'class' like car, truck, bus for each bounding box, and they aren't always accurate). Then a 0.3-second window slides along the track and each one gives a pixels-per-second. The whole crux of the problem is turning those pixels into distance, because a pixel is a different number of meters at every point of a wide-angle frame, and different again in the near and the far lane.
One thing we can do is use the bounding box, and say okay an average car is X feet long, and this car's box was Y pixels, so we can assume the pixels in the road are Z amount of real world distance, but a more accurate approach we used is to normalize this based on all the cars coming in on the road. Since a road has a bunch of cars, we can easily figure out there is a pretty standard average size of car, and that can be used much more accurately than a single cars length to produce a pixels per meter value.
At different parts of the road on the screen, cars may be a different size, so we calculate that metric based on specific areas of the screen that we can reuse if nothing else changes. Every track takes the median across its windows and carries a range, ±10% on the ruler and ±15% on the fallback, and alerts compare the low end of the range against your line, so an alert is a car that was over it even if we're wrong by the whole margin. Every car the detector calls a car goes back into the ruler, so the camera keeps getting better at its own street.
Of course, this is the real world so I ran into a number of challenges and edge cases with this system. First off, getting an accurate clock time. Ring's timestamps come off a 90 kHz streaming clock that gets corrected in discrete steps. Every keyframe is stamped about 30 ms early. Every so often two consecutive frames, one normal frame of motion apart, are 200 ms apart on the clock; over two days on one camera I counted 369 of those steps landing inside 24% of tracks. A window straddling one reads 40% slow. Another clip had three frames spread over 2.9 s and then sixteen crammed into 170 ms; dividing a normal displacement by seven milliseconds gave 931 px/s and a 69 mph reading on a car that was barely moving. I pulled the raw streams apart with ffprobe to be sure none of this was our decoder; it isn't. So now: no window shorter than 80 ms or longer than a second, no track longer than 30 s, and any window whose elapsed time disagrees with the track's own frame cadence by more than a third has a clock step in it and is thrown out. This prevents any video that we detected to be slightly corrupted or skipping to affect our speed calculations.
Confidence intervals were another issue, sometimes we would detect things that are not cars with low confidence but sometimes low confidence objects were cars and we wanted to include that in the tracking without ever saying something is a fast moving car that isn't. This required some tweaking and additional code to determine whether or not the object in question was actually behaving as a car possibly would/could.
Next was how time of day and glare affected tracking. I noticed the YOLO11 nano model was missing some readings during sunset because of strong glare, but other open source models such as RF-DETR were still able to detect cars through worse lighting. This is something I'm continuing to work on and evaluate. I discovered tweaking contrast before running the models can help significantly, also scaling up to strong models provides slightly more accuracy in diminished lighting conditions, however the cost to run goes way up.
Continuously evaluating the accuracy, driving various cars at exact speeds past the camera to test it, and moving the camera around to different types of locations and view has helped enormously in identifying edge cases and improving accuracy. It's at a really good spot now, but obviously more will arise and this will be a focus in the future to continue to iterate on.
Big Challenge #2: Cost
The second challenge was how to make this run in a way that it can actually scale to many users in a cost effective way. The app doesn't need to make an insane amount of money, but it at least needs to cover its costs in a way that would be reasonable for customers. I decided $2.99 would be a reasonable customer cost to spend on this (per camera cost as per how Ring works). Not enough to break the bank, but worthwhile for people to get this valuable data.
Unfortunately, compute is expensive. We need to run calculations on almost every frame of every motion event, which on a busy road, is many hours of video. A busy street sends 500 to 650 clips a day and the detector runs on every frame of every one. When I first costed the code as it stood, a cloud CPU came out at $25 to 50 per camera per month, a per-clip serverless function at about $60, a GPU box at $4 to 13. None of that works at $2.99.
One of the wins came from doing less per clip without actually measuring less. The ruler already knows where the road is, so the detector now sees only that band of the frame: roughly half the cost, and nothing a car could be in gets skipped. We don't actually have to analyze frames that aren't the road. This helps drop costs by around 50%, but is still pretty expensive to run.
Everything else was made deliberately small. The clip is deleted within a minute of being measured; what's kept is one 53 kB thumbnail per car and a short marked-up clip only for cars over your alert line, about 33 MB a day for a busy camera, a gigabyte a month, which works out to roughly a quarter per month for each year of history. Per-frame box data is shed after 30 days.
Emails cost money, so for a customer that has many many alerts, I added a daily digest, over 5 alerts per day, and they start getting grouped into a daily digest for the rest of the day, this prevents a storm of thousands of emails, which wouldn't be useful to anyone, and also provides an upper bound on cost per customer.
There are a number of open source Object Detection models, some run better on CPU, some run better on GPU. Right now at a low scale, I'm able to run some local workers on my PC, and well as a small CPU bound cloud box that can process a decent amount of customer camera footage.
With all of that in, a busy street costs about $2.80 a month all-in, and a quiet one maybe around $1.50, against a $2.99 subscription. This is feasible to work out but without a ton of wiggle room. At a higher level of scale however, it will be possible to launch on higher performance GPU boxes, which can according to my testing, reach closer to the $1.80 level or lower for a busy street. If we can find ways to continue to process video even more accurately with potentially less frames this can go down even more. This is much better than the original unoptimized estimations of closer to $20-30 dollars a street, and close enough to actually begin running a viable business model. There can always be more done, but I am very happy with the progress I've made so far on cost optimization and processing efficiency.
Accomplishments that we're proud of
It's live. It passed Ring's certification review. It has measured thousands of cars on my streets, and I can tell you the 85th percentile at 7pm to a tenth of a mile an hour. I'm super proud to have been able to build something that can measure safety, and give the ability and tools for people to actually measurably improve safety on their streets. Speed kills, and be aware and alert of it is something that can actually save lives so I'm really excited to be a part of that. Getting this out to customers, and providing something valuable to the community is really important to me, and I'm well on my way to do that.
What we learned
Computer vision is hard, there is alot to learn. There are endless detection models, algorithms, and ways to approach problems. Also compute is expensive, navigating the trade-offs between these things are fun and challenging. Also privacy is super important to make so I made sure to significantly limit what data could be stored, focus hard on security, and make sure this won't be used in a nefarious manner. Obviously, that can limit some potential features and functionality, but in the long run, it's the right decision, and it's most important to focus on the actual features that matter most and make them work perfectly.
What's next for Speed Alert
Potentially an app, with push notifications could be useful for power users. Improved search and tracking. Better accuracy tools, such marking up videos with known speeds to be able to calibrate your individual camera perfectly. Getting to scale so we can use larger and faster and more accurate detection models cost effectively. But in general, marketing this and getting it out to customers, learning what they need and want, will be my main priority. I want to understand from people what they need most, and how this can best improve safety in our streets. Maybe there is a potential to sell or partner with someone who sells 'Slow' signs, or even partner with cities who may have their own cameras to help provide them data they can use to keep their citizens safer.
Built With
- amazon-web-services
- docker
- next
- ring-api
- supabase
- vercel
Log in or sign up for Devpost to join the conversation.