跪拜 Guibai
← Back to the summary

Cap's Tauri-to-Electron Pivot Is a Footnote; Its 46 Rust Crates Are the Real Story

Cover image

On the evening of August 12, Cap's main maintainer, richiemcilroy, submitted a PR with a very short title: Migrate from Tauri to Electron. This project had bet on Tauri from the first line of code written in November 2023, with a Rust backend and a SolidJS frontend, unwavering for three years. Now they decided to swap the entire desktop runtime for Electron, citing the inconsistent versions of built-in browser engines across operating systems that led to a constant stream of bug reports, while Electron ships with a stable, bundled Chromium.

An open-source project with 20,822 stars made a U-turn on its most fundamental architectural decision.

This event alone is worth writing about. But after actually reading its source code, I discovered that the shell swap is only the surface; Cap's real story is hidden in the Rust layer. To record a single screen, they wrote 46 crates (Rust's term for independent code packages), turned the muxer into a separate process, and even wrote a module specifically to repair already-corrupted recording files.

Let's lay out the basics first. Cap is positioned as an open-source Loom: screen recording, local editing, generating shareable links, comments, and transcriptions—a complete asynchronous video collaboration workflow. Loom was acquired by Atlassian in 2023 for approximately $975 million, proving the commercial value of this category but also leaving the concern of data locked in someone else's cloud. Cap aims to capture the teams that care about data sovereignty; they can connect their own S3 buckets, self-host the entire platform using Docker Compose, and even host the sharing page under their own domain.

Screen recording is much deeper than it looks

Think about it: what is the requirement list for screen recording software when you break it down? Capture the screen, capture the camera, capture the microphone—three streams. On macOS, capture goes through ScreenCaptureKit; on Windows, it goes through Windows Graphics Capture plus Direct3D. The camera uses AVFoundation on one side and Media Foundation on the other. After capture comes encoding, and after encoding, the three streams must be muxed into a single video file, followed by the whole business of editing, rendering, and exporting.

The platform differences at every step are a mountain. This is why Cap's crates directory swelled to 46; it's not over-engineering, it's crushed into existence by platform realities. A glance at a few crate names makes it clear: scap-screencapturekit handles macOS capture, scap-direct3d handles Windows capture, camera-avfoundation and camera-mediafoundation manage the camera on each side, enc-avfoundation, enc-ffmpeg, enc-mediafoundation, and enc-gif are four encoding paths, and rendering-skia is responsible for rendering. Capture, encoding, muxing, rendering, exporting—five pipeline stages, each spread out by platform.

Let's look at a detail from the macOS capture implementation. In crates/scap-screencapturekit/src/capture.rs, they use the cidre Rust binding to directly interface with ScreenCaptureKit's Objective-C callbacks, and each callback is internally wrapped in a catch_unwind. Why? Because if a Rust panic crosses the FFI boundary into the Objective-C world, the behavior is undefined—it will just crash. You would never know this kind of code exists without reading the source; the README won't mention a word of it.

The entire recording pipeline, strung together from top to bottom, looks like this diagram: the desktop shell layer only handles the UI and system bridging, the recording orchestration layer schedules the dual-mode pipeline, the platform capture layer splits capture backends by operating system, the encoding and muxing layer does process isolation, and finally the repair, rendering, and export layer along with the sharing platform layer wrap things up.

cap-rust-recording-pipeline-architecture.png

Muxing is another process's job

The part of Cap's architecture I find most worth discussing is the position of the muxer.

Most applications run capture and file writing in the same process—simple and direct. Cap's approach is to split the muxer out separately. crates/cap-muxer is an independent executable; the recording process feeds encoded frames to it via a pipe, and the two sides communicate using a protocol with frame headers defined by the cap-muxer-protocol crate.

What's the point of splitting it out? Look at the exit codes in main.rs and you'll understand. EXIT_PROTOCOL_ERROR is 10, EXIT_FFMPEG_ERROR is 20, EXIT_INIT_ERROR is 30, EXIT_ABORT is 40, EXIT_BAD_STATE is 50, and the most striking one is EXIT_DISK_FULL, which gets its own code 60. A full disk is a classic death scenario for screen recording software. If the muxer process crashes, the recording process is still alive, so at least you can know what happened and how far the recording got. This is trading process boundaries for crash isolation; if the muxer blows up, it doesn't drag the entire recording session into the grave.

Even corrupted recordings must be rescued

If process isolation is a preemptive defense, then crates/recording/src/track_heal.rs is a post-mortem rescue. This file deserves a full explanation.

Its module comment documents a history of production blood and tears. Some video sources spit out frames at rates exceeding their nominal frame rate. Windows WGC capture on high-refresh-rate monitors does this; a 165Hz monitor can deliver frames at more than double the nominal rate, and if timestamps are still stamped at 30fps during muxing, the result is a video playing back 2.24 times slower, with audio and video completely desynchronized. Another pitfall is the AVFoundation camera, nominally 30fps but actually running at 60fps, causing camera.mp4 to be similarly stretched. The recording-side bug was later fixed, but users already had a batch of corrupted recordings sitting on their disks. What to do?

Their answer is this track heal module. When the editor opens a project, it detects the characteristic signatures of these bad tracks and losslessly rewrites the timestamps to rescue the video. It even handles the race condition of the same project being opened concurrently, using an in-process HealInFlightGuard to ensure only one repair runs at a time.

In the same directory, there's also sync_calibration.rs, following the same line of thinking. Audio-video sync doesn't rely on hard alignment during recording; instead, analysis is done after recording. SyncAnalyzer works with calculate_frame_motion_score to calculate inter-frame motion scores to calibrate offsets, and the calibration results for each device are stored in CalibrationStore. The next time the same camera is used with the same microphone, the offset is looked up directly from the table. This is treating media engineering as a measurement problem.

Frankly, my perception of this project changed significantly after reading this. A screen recording tool willing to write dedicated repair code for "damage that has already occurred and is irreversible" shows that the team has truly been educated by real user losses.

Two modes, two trade-offs

On the product side, Cap offers two recording modes: Instant and Studio. Instant mode uploads while recording; the crates/recording/src/fragmentation/ directory contains a fragmentation and manifest mechanism. The recording is split into segments that are pushed to an upload queue, and the link is ready to use the moment recording stops. Studio mode keeps everything local; inside the recording crate, instant_recording.rs and studio_recording.rs are two independent pipelines. The latter connects to the full editor—backgrounds, zoom, cropping, subtitles—and exports on demand.

One prioritizes speed, the other quality, with no compromised hybrid state in between. This product judgment is, in my opinion, much stronger than many "smart mode" compromises.

Three years of Tauri, then Electron overnight

Back to that opening PR.

richiemcilroy's stated reason for the migration didn't beat around the bush: the fragmentation of built-in WebView versions across operating systems caused the same code to behave inconsistently on different OS releases, and they were overwhelmed by this type of bug report. Electron, despite its reputation for high memory usage, bundles a fixed version of Chromium, buying cross-version consistency outright. The migration plan retains the Rust backend and existing UI, only replacing the runtime and bridging layer. The newly added apps/desktop/electron/backend.cjs is responsible for launching the Rust backend and communicating via a framed localhost transport, while the Rust side corresponds to crates/desktop-runtime/src/transport.rs. The PR's verification checklist includes Rust checks, clippy, and 141 tests.

This isn't good news for the Tauri ecosystem, but it's a reminder for those in the middle of technology selection: the "lightness" of WebView is traded for consistency. When a desktop media application demands extremely high determinism in rendering behavior, this trade-off needs to be recalculated.

Incidentally, the comment section of this PR is quite characteristic of the times. richiemcilroy sent 17 re-review requests to the AI code review bot greptile, spanning from the early hours of August 13 to noon on August 14. Looking at the contributor list, first place is richiemcilroy himself with 6,078 contributions, second is Brendonovich with 1,018, and fifth is an account named cursoragent with 93. An AI programming agent has ranked among the core contributors. This project is probably one of the highest-concentration "AI collaborative development" star projects right now.

Places where skepticism is warranted

After all that praise, it's time to pour some cold water.

First, look at the pricing page. The free tier is quite feature-rich, including local recording, the full editor, and 4K 60fps export, but shared links are limited to 5 minutes each. The promotional AI titles, summaries, clickable chapters, and transcriptions are all locked behind the Pro plan at $12 per person per month. Moreover, these AI capabilities depend on the cloud; self-hosted users who want to use them must configure their own AI provider. The so-called open source opens the client and platform framework; the cloud value-added part is closed source. This is standard commercial open source playbook—nothing shameful, but it needs to be seen clearly.

There's also nuance in the licensing. The LICENSE is AGPLv3, but the cap-camera and scap series of crates are separately released under MIT. This split is very deliberate: foundational components like capture and muxing, which downstream might reuse, are released to build an ecosystem, while the core business logic stays behind AGPL to block commercial freeloading. If you want to embed Cap's code into your own closed-source product, there's basically no compliance path; you can only go through the API or self-hosting.

The most precarious aspect is actually the people. A contribution distribution of 6,078 to 1,018 means the bus factor is visibly 1. The good news is the project is active enough; version 0.5.9 was just released on August 11, with two releases in July, maintaining a steady rhythm of one release every two to four weeks. Public bounties are posted on Algora to attract external contributions. The bad news is that for an open-source company that hasn't yet validated profitability, its lifeline is tied to a single person.

Additionally, the README casually mentions that the analytics feature depends on Tinybird. To fully replicate viewer analytics in a self-hosted setup, you need to integrate yet another third-party service—a hidden cost not detailed in the documentation.

An unreplayable event stream

After dissecting Cap, I kept thinking about its biggest inspiration for me, and it comes down to these four words: unreplayable event stream.

The fundamental difference between screen recording and ordinary applications is that every second of recording a user presses is a one-time event stream. If it crashes, you can't re-record; if sync is wrong, you can't redo it; if the disk is full, you can't undo it. That's why you see Cap's engineering focus almost entirely bet on "what to do after something goes wrong": splitting the muxer into a separate process for isolation, dividing exit codes into six levels so the parent process can make judgments, repairing existing bad data on load, and storing per-device calibration for incremental correction.

This line of thinking is portable. Any system that processes "one-shot, unrepeatable" data—live streaming, interview recording, dashcams, transaction logs—is worth shifting its defensive fortifications one notch from "avoiding errors" toward "how much can be preserved after an error." With 46 crates, Cap proves one thing: the moat of screen recording software isn't in buttons and filters; it's in those layers of fallback that you always hope you'll never need, but that save the day when things go wrong.

As for the Tauri to Electron pivot, I don't find it regrettable at all. Technology choices should follow real bug reports, not community hype. Choosing Tauri three years ago was right; switching to Electron today is also right. Being able to openly admit a framework's limitations and act on it is far more respectable than stubbornly defending a position.