Circumstances finally permitted me to actually focus on v3.9.0. This release contains the fourth iteration of remote streaming which keeps with the penguin-themed naming scheme: Chinstrap. The history of remote streaming is:
- #1 was a simple TCP socket mechanism that redirected the ONVIF and RTSP sockets to a local listener that made a secure connection to a remote Streamie instance, that directed those sockets to the target camera. The security implications of this always scared me a bit and it relied on UPnP, which some ISPs blocked. It was fairly light-weight and easy to shoehorn into Streamie with minimal fuss.
- #2 used ENet, a UDP library, and it relied on the remote Streamie instance to do all of the camera communication and to then relay a media stream in Streamie’s internal format. Besides some fickleness the only real downside was that I needed UPnP, which I learned when setting things up for a neighbor, is blocked by some ISPs (like AT&T).
- #3 used WebRTC. I was not familiar with WebRTC until I bought a new Nest camera which I discovered no longer supported RTSP. I realized the potential of WebRTC data channels combined with its TURN/STUN features which would allow Streamie to ditch UPnP. The main downside to WebRTC is that it is an enormous pain to build. I can’t keep it up-to-date because figuring out the new build failures every time is a full time job. WebRTC mostly worked, but when it failed, there was little hope of debugging the connectivity problem.
And that brings us to #4, which in some ways is three steps back to #1. Instead of a plain TCP socket, we're using WebSockets. Under ideal circumstances, either the remote streaming client or server is on a network with UPnP support and a direct (or reverse) connection is possible. If neither the client network nor the server network can use UPnP, we fall back to relaying. Much like with WebRTC, the client and server both connect to the same relay node and it allows the two Streamie instances to "talk" to each other, ultimately negotiating a video stream.
But why WebSockets instead of just a plain TCP socket?
First, by using using a tunneling service, we are able to really focus on locking down our infrastructure specifically by not needing open ports on the firewall.
Second, while we only have a single physical location at the moment, having connections proxied will make expanding to multiple locations a little less painful one day.
Finally, and possibly most importantly, I'd really like to have Streamie-in-a-browser support one day. This support might start out as just being able to share a camera URL to someone who doesn't have the app installed, but might eventually include advanced features as well. By having communication based on WebSockets, this'll be a touch easier to accomplish.
Looking to the future with this new WebSocket-based foundation in place, Streamie will soon support local network event notifications (that don't rely on internet access and the latency that adds) and the existing HTTP-based API calls will gradually be migrated over to the WebSocket-based API.
- Overhauled networking code. The most immediate impact is that the mechanism for remote streaming has been replaced (again), and will continue to be improved. The new networking code will form the basis for improved Streamie-to-Streamie communication for sharing cameras, sending alerts, configuring devices, etc; ultimately this will also improve Streamie's offline performance as well.
- Possible fix for speech synthesis only working for a little while and then just going silent for no obvious reason.
- Serializes the process of loading stream previews when editing an ONVIF camera because if you're accessing an NVR, there could be many dozens, and starting all of those video streams concurrently tends to have an undesirable affect on the NVR.