Wow.
I need to learn when to stop.
Granted, there was a rabbit hole of architectural changes to make that ended up taking longer than expected, and I’m always wary of regressions when making foundational changes like that. So, yeah, this release was a lot longer in the making than I ever anticipated. I prefer a 2 - 3 week cadence.
The Cameras screen now lets you organize your cameras into arbitrary sections. You can drag-and-drop between the sections. Within each section, alphabetical order is enforced though. Sorry.
The primary focus of this release is Access Controls. In short, this allows Streamie to be unlocked only by authorized people, MFA style. Eventually, we’ll support authentication via LDAP (Active Directory), Email, SMS and more, but the feature is being driven by a client whose needs are just User/Pass and Email, so that’s where we’re starting.
One other thing worth mentioning is the Web Portal. It saw a lot of improvements in this release. The specific focus was for remote NAS (SMB) connectivity. There are a lot of ways that can break, but it is now very robust in knowing how to connect and correctly handling reconnections. Additionally, remote connections can be slow, so the movie playback process has been improved, which uses a loading screen that shows transfer progress to Streamie, which completes before the browser makes a request for the movie itself. Great changes all around.
The architectural changes I mentioned allowed for some great improvements. In the beta days there was just the one API server and all was bliss. After launch we had multiple API servers but they were all at a single location, so a dual HAProxy setup worked great. Streamie works best if all of the devices on an account are connected to the same API server. HAProxy accomplished that with an account hash HTTP header. Eventually we migrated to Cloudflare’s D1 database which was the final step before we could spread the API servers apart geographically. Already being a fan of Cloudflare’s services it seemed natural to employ their Load Balancer in lieu of HAProxy. Thus began literally months of low priority support emails trying to figure out how to get LB to work with Tunnels. After all of that it turned out that their Hash-based origin server “sticky” feature doesn’t really work. Bringing this back around to the start: the refactoring mentioned earlier enables a deterministic routing to an API server that is now a part of the app launch and connection process. This still relies on CF LB to handle the routing request, but it doesn’t matter which API server handles it.
Finally, let me say how much I appreciate (and benefit from) the many active free (and paid!) users who rely on Streamie features that I don’t frequently use, and discover compatibility issues and the occasional regression and then report those issues. They usually end up with a beta build incorporating a fix within an hour. Don’t keep these things a secret.
- Adds the 'enableAudio' argument to the Control-Stream-Camera/Group Web API. Use this so that audio will automatically be enabled once streaming has begun. [BG]
- Adds support for inviting a member to an account by scanning a QR code. [DW]
- Adds Sections to the Cameras screen. Group your cameras by their location (Indoor, Outdoor) or whatever grouping you want. Cameras are now auto-sorted alphabetically. I'm sorry if you don't like that. It's just the way it has to be.
- Adds a spinner and a modal dialog to the Accounts screen that are visible when switching accounts.
- Adds support to ChinstrapFileServer for updating the download progress view as a file is downloaded. This is evident when downloading a NAS / S3 recording.
- Adds a progress view when downloading a recording to share. It also features a cancel button. That actually cancels.
- Adds to the file server configuration screens a new output type option ("MP4") to go along with the existing SPF and MOV output type options. The MP4 option does not include the audio track.
- Adds two badges to the File Server cell that indicate the number of cameras (bottom-left) and the number of members (bottom-right).
- Adds "Pause" support to Mode schedules. A mode can be paused until the next hour, next day or next week.
- Adds support for remotely locking, unlocking via the Member screen, a Streamie device that is part of an Access Control group.
- Adds the new Access Controls feature which allows you to set up authentication mechanisms to be used to unlock Streamie. For this initial release, the one supported mechanism is MFA via email.
- Adds the new Access Control Password feature, which includes usernames and passwords, each of which can be individually enabled / disabled.
- Adds support for sending Device Offline alerts to the email address in the account Profile, if there is one.
- Adds a spinner when clicking "Apply" to Permissions.
- Adds a spinner to the Save & Close button in the Profile screen.
- Adds Modes-v2.0, which replaces the original Modes feature. The new Modes feature includes scheduling support (like business hours). All of the old modes were migrated over to the new modes. The older API hides the changes from the app, so older app versions shouldn't notice any change.
- Fixes a crash in ONVIF Device Prober where concurrent access to the matches
dictionary happened due to not making use of the matchesQueue
as appropriate.
- Fixes an Event Manager problem where we called .stop() on it when backgrounding the app but we never called .start(), which means that it would never update events.
- Fixes an issue in Source List Screen (the screen in which you can select cameras, modules), which always displays them in the internal order, but since the Cameras screen now uses sections and forced alphabetizing, this internal order was a mess and the screen needed to just alphabetize everything.
- Fixes a remote stream reconnection issue. We previously changed sendRequest() to append request to the whenReady queue when disconnected. If a client did not have auto-restart enabled though, this would prevent a reconnection from ever occurring because it'd wait forever to send the streamStop() request. I've updated ChinstrapStreamieClient to correctly indicate that a connection has failed and to set stopped = true on the router.
- Fixes the log uploading loop so that it will catch the "Log file already exists" error and not treat it as a fatal error, but instead to delete the log file and move on to the next one.
- Fixes the Integrations screen by removing the Noonlight option, which wasn't meant to be available in production and removes the Done section, replacing it with an Options button in the navigation menu.
- Fixes a remote Recording playback issue that prevented scrubbing from working.
- Fixes several issues in Chinstrap File Server Input Stream where the wrong segments were being requested in the read-ahead strategy because we were not correctly synchronizing our use of certain state variables. Also resolved is the issue of trying to read beyond the end of the file.
- Fixes several issues that prevented automatic reconnection from occurring in ChinstrapFileServer.
- Fixes the Help url for the Custom module to point to the correct help article, even if it is blank. One day. Maybe I'll get a contract tech writer?
- Fixes a BaseScreenViewController bug where if the Screen loaded its content before the initial CollectionView load, the BaseScreenViewController might not yet have registered the cell types, leading to a crash. Use didFinalizeLoad
to assume zero sections until loading is completed the first time. The only edge case I see with this is if a reload of similar speediness introduces new cell types.
- Fixes a long-standing API server issue, ultimately a memory leak but it caused other problems, where a client connection could begin, send a login request and then disconnect before the login request was processed. The disconnection was handled before the login request was handled and since the connection was already cleaned up, the login was sort of "orphaned". Later on when we would send notifications to that connection, they'd just queue up and never complete. What a mess.
- Fixes a remote-file-server playback issue. When the KrillPacketReader calls scrub(0) on the ChinstrapFileServerInputStream, it deletes all of its cache and starts the read-ahead process again. Now, we check to make sure the readOffset is not already at the desired scrub offset. This fixes the playback issue.
- Fixes a bug when editing File Servers on tvOS where the Quota values were not editable. [John Cahill]
- Fixes a bug when editing File Servers on tvOS where, when browsing folders, if a folder was empty it was not possible to navigate to the Choose button. I've added a placeholder cell ("This folder is empty.") to quickly resolve this. [John Cahill]
- Fixes the naming of the TOC (table-of-contents) file written out by Camera Recorder, which used the CMCCrypto.Account.accountId value, which is super weird; changed it to the publicKeyId for the active user.
- Fixes a bug related to remote streaming of UniFi cameras. The issue is that I wrote "#if SREAMIE" instead of STREAMIE, so the isReachable() implementation in CMCCameraUniFiSource used by Streamie was the stub that just returns a default value (false) instead of actually checking. [John Cahill]
- Fixes a Krill video timestamp calculation issue.
- Fixes a YouTube live streaming issue when using a Google Nest camera where audio-video sync was never achieved. This was fixed by adding a timing offset of +1 second to the silent audio generator.
- Fixes an issue where the Credentials screen had the name "Modes" on it (copy-pasta).
- Fixes a text wrapping issue in OptionCollectionViewCell and a constraint issue in LabelCollectionViewCell.
- Fixes an integer overflow issue in CMCBufferView that caused a crash because I was doing some silly math, manually, that CMTime actually has functions to perform.
- Fixes a YouTube Live Streaming issue associated with ContentDetails.startWithSlate, which is apparently not always present. [Angus Parker].
- Fixes an issue where motion events would not produce recordings due to a stupid, stupid bug. [DD]
- Improves ChinstrapService so that it keeps track of incoming Streamie connection routers so that they'll show up when viewing a Member's details
- Improves the S3 File Server configuration screen with an option to adjust concurrency and timeouts.
- Improves the SMB File Server configuration screen with an option to adjust the concurrency.
- Improves the Azure Blob File Server configuration screen with options, like S3, including: Request Timeout, Retry Count, Retry Wait and (the new) Concurrency.
- Improves the Camera Recorder's updateSnapshots() function so that it has a Task Scheduler that allows 5 concurrent snapshots and the 15s timer will not start another round of snapshots if the previous round has not yet concluded. This is important for scaling NAS/S3 recording when the user doesn't want to decode the video; just recording it.
- Improves the Web Portal support for file servers. If the "reachable" state of a file server is unknown, we wait for that to be updated before trying the file server.
- Improves the web portal's handling of movie playback. A /begin-download API call is made to get Streamie downloading the file. The /download-progress API is used to show progress to the web browser. Finally, the movie itself is grabbed once transcoding has finished.
- Improves file caching so that every file is put in a per-account directory so that there's no chance of data "leaking" between accounts AND the caches are retained when switching accounts, which was previously a major pain point.
- Improves the user experience when reconnecting to the API server: if the connection has dropped, sendRequest() just tosses requests on the whenReady queue instead of showing the user the "Not connected" error.
- Improves the UniFi Protect integration to better support recent JSON changes.
- Improves the whole account-switching process so that we actually start an entirely new connection to the server and all of the associated app services, and then replacing the singletons in the app with the new stuff after the connection succeeds.
- Improves various input fields in Permissions Groups, Access Groups, Account names and Modes by trimming whitespace from user input.
- Changes the Integrations screen so that integrations are sorted by service and name (instead of just service type).
- Changes the Recording Cameras screen "Choose a camera" text with the name of the file server that's being browsed.
- Changes the Recording Dates screen "Choose a date" text with the name of the camera that's being browsed.
- Changes the upgrade prompt text to mention that home and small business users can request a free upgrade.
- Changes the Events screen so that it now prompts for comfirmation before deleting a whole day's worth of events.
- Changes the Accounts Screen to use better title1, title2 labels and less redundancy.
- Changes the naming of the various Home Objects Screens so that instead of just saying "Add" they'll say "Add Camera" (for instance).
- Changes the Camera Collection View Cell so that it provides a consistently sized Streamie placeholder icon based on whether or not the label is visibile.
- Changes the Access Control screens for Password and Email so that they show a "Loading..." label until the content is fully ready.
- Changes the remote connection process to start with direct-connect and then fail to reverse-connect. I'm pretty sure my current home setup with UDM + Starlink makes Streamie think that we have UPnP support when we (probably) don't. I need to maybe let Penguin validate that UPnP is working for each client.
- Changes the loading screen so that it shows some status details as Streamie starts up.
- Changes the naming of "Add Account" (“Create New Account”) and "Join Account" (“Join Existing Account”) to reduce confusion.
- Changes the file server collection view cell so that it demonstrates with a green background on the label that the current device uses that file server for recording.
- Changes the S3 File Server configuration screen so that all sections are hidden until the details have loaded.
- Changes the Web Portal so that when viewing a list of Cameras recorded to a File Server, if we lack a thumbnail for a camera, we return a black rectangle instead of a broken image link. The same goes for the periodic thumbnails of a recording, but those really should never be missing.
- Changes the Permissions and Permissions Group screen so that all sections are hidden until the content has loaded.
- Changes (reverses) the order for the Profile cell fields so that the label is in the upper location and the value is in the lower location, which is consistent with the rest of the app.
- Changes the Configure S3 FileServer screen and the Azure one so that the associated Integration name is shown in the Path cell.
- Ports the Recording Files view controller to the Screens framework.
- Ports the Weather Module view controller to the Screens framework.
- Ports the Custom Module view controller to the Screens framework.
- Ports the Time Zone chooser to the Screens framework. The UI is still wildly inefficient, but ... it's better. It needs a search bar or something.
- Ports the Module-Configure-Clock view controller to the Screens framework
- Ports the Configure-Clock-Module view controllers over to the Screen framework.
- Removes the ugly, blue "Switch to Remote" connection button, replaced with a menu option both on iOS and tvOS.
- Removes the "Classify" streaming option, which somehow made its way into production. On the backend it used Cloudflare's AI image classifier and put the best guess on the screen, but it never really worked particularly well.
- Removes PenguinService, which is the original http-based mechanism for API communication which was largely replaced by Chinstrap (WebSockets) a while back. The last remaining bits were associated with app startup stuff, account creation and such, which I didn't want to touch because it took ages to get it really solid.
- Removes audio support from Web Portal-based recording playback because it somehow breaks playback for everything but .mov files, but Windows won't play those files. We're now producing .mp4 files with just a video track.
- Removes use of "https://streamie.co/local/webportal" for reading web portal files, and we now use files hosted by the API server. This could go a step further and use Chinstrap, but I'm not sure there's much value in that; just needless overhead and complexity.
- Removes the checkmarks from active Shares because they're already in a section dedicated to being active.
- Replaces the icons used to represent various types of file servers with a more uniform appearance. This is evident both in the app and the Web Portal.
- Replaces the tvOS launch image with a launch screen roughly the same as the iOS launch screen.
- After years of thinking about it, I finally merged the iOS and tvOS app delegate code into a single class, other than a few bits of platform-specific things (like user notifications on iOS).
- Adds the new concept of a "home node" so that each device on your account will (hopefully) connect to the same API server.
- Refactors a bit of YouTubeService's monolithic encodedVideoSinkHandle() function because we've got a recent crash in that function and it's not obvious exactly what caused it, so splitting it up should help narrow the scope of the next instance of the crash.
- Finally, I've added support for Old Version Lockout. Starting with v3.19.0, the app can be disabled once it is too old and then I can more cleanly deprecate and remove API server features. This is accomplished via a TXT DNS record for streamieapp.com.
- Parallelizes some startup API requests.
- Updates third party libraries and stuff.
Streamie provides a best-in-class user experience on your iPhone, iPad, Apple TV and Apple Silicon Mac, with an intuitive user interface that makes it simple to discover, stream, record, monitor and share your HomeKit, Google Nest, Ubiquiti UniFi Protect and ONVIF-compatible IP and RTSP cameras. Streamie keeps you informed with motion event notifications and it works with most cameras using its advanced audio and video codec support. You can watch your cameras from anywhere, record 24/7 to your private NAS, remotely manage multiple locations, device permissions and seamlessly synchronize settings across your devices; configure Hubitat smart home automations, live stream to YouTube and rely on the in-app technical support system when you need help (but you can also reach us by phone). Download Streamie today.