diff --git a/Cargo.lock b/Cargo.lock
index c395bf6471..9197d09384 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1268,6 +1268,7 @@ dependencies = [
name = "cap-audio"
version = "0.1.0"
dependencies = [
+ "cap-enc-ffmpeg",
"cidre",
"cpal 0.15.3 (git+https://github.com/CapSoftware/cpal?rev=6013cb5f8bd3)",
"ffmpeg-next",
@@ -1560,6 +1561,7 @@ dependencies = [
"thiserror 1.0.69",
"tokio",
"tokio-stream",
+ "tokio-tungstenite",
"tokio-util",
"tracing",
"tracing-appender",
@@ -1584,6 +1586,7 @@ version = "0.1.0"
dependencies = [
"axum",
"cap-audio",
+ "cap-enc-ffmpeg",
"cap-media",
"cap-media-info",
"cap-project",
@@ -1593,6 +1596,7 @@ dependencies = [
"ffmpeg-next",
"flume",
"futures",
+ "image 0.25.8",
"lru",
"ringbuf",
"sentry",
@@ -1635,6 +1639,7 @@ dependencies = [
"tempfile",
"thiserror 1.0.69",
"tracing",
+ "windows 0.60.0",
"workspace-hack",
]
@@ -1926,7 +1931,9 @@ dependencies = [
"bytemuck",
"cap-camera-effects",
"cap-cursor-info",
+ "cap-enc-ffmpeg",
"cap-flags",
+ "cap-media-info",
"cap-project",
"cap-video-decode",
"cidre",
@@ -1950,6 +1957,7 @@ dependencies = [
"serde",
"serde_json",
"specta",
+ "tempfile",
"thiserror 1.0.69",
"tiny-skia",
"tokio",
@@ -2054,10 +2062,14 @@ name = "cap-video-decode"
version = "0.1.0"
dependencies = [
"cap-d3d-adapter",
+ "cap-enc-ffmpeg",
+ "cap-media-info",
"cidre",
"ffmpeg-hw-device",
"ffmpeg-next",
"num_cpus",
+ "serde_json",
+ "sha2",
"tempfile",
"tokio",
"tracing",
diff --git a/apps/desktop-gpui/Cargo.lock b/apps/desktop-gpui/Cargo.lock
index d36888cc56..686399628c 100644
--- a/apps/desktop-gpui/Cargo.lock
+++ b/apps/desktop-gpui/Cargo.lock
@@ -1396,6 +1396,7 @@ dependencies = [
name = "cap-audio"
version = "0.1.0"
dependencies = [
+ "cap-enc-ffmpeg",
"cidre",
"cpal 0.15.3 (git+https://github.com/CapSoftware/cpal?rev=6013cb5f8bd3)",
"ffmpeg-next",
@@ -1538,6 +1539,7 @@ dependencies = [
"anyhow",
"ashpd 0.11.1",
"base64 0.22.1",
+ "cap-audio",
"cap-camera",
"cap-camera-effects",
"cap-cursor-info",
@@ -1619,6 +1621,7 @@ dependencies = [
"ringbuf",
"sentry",
"serde",
+ "serde_json",
"specta",
"tokio",
"tokio-util",
@@ -1654,6 +1657,7 @@ dependencies = [
"sysinfo 0.32.1",
"thiserror 1.0.69",
"tracing",
+ "windows 0.60.0",
"workspace-hack",
]
@@ -1909,6 +1913,7 @@ dependencies = [
"bytemuck",
"cap-camera-effects",
"cap-cursor-info",
+ "cap-enc-ffmpeg",
"cap-flags",
"cap-project",
"cap-video-decode",
@@ -1979,6 +1984,7 @@ name = "cap-video-decode"
version = "0.1.0"
dependencies = [
"cap-d3d-adapter",
+ "cap-enc-ffmpeg",
"cidre",
"ffmpeg-hw-device",
"ffmpeg-next",
diff --git a/apps/desktop-gpui/Cargo.toml b/apps/desktop-gpui/Cargo.toml
index 83aa68e187..b2411ea5a9 100644
--- a/apps/desktop-gpui/Cargo.toml
+++ b/apps/desktop-gpui/Cargo.toml
@@ -18,6 +18,10 @@ publish = false
name = "cap-gpui"
path = "src/main.rs"
+[[example]]
+name = "studio-finalization-benchmark"
+path = "../../crates/recording/examples/studio-finalization-benchmark.rs"
+
[package.metadata.bundle]
name = "Cap GPUI"
identifier = "so.cap.desktop.gpui"
@@ -28,6 +32,7 @@ osx_info_plist_exts = ["resources/Info.plist"]
osx_url_schemes = ["cap-desktop"]
[dependencies]
+cap-audio = { path = "../../crates/audio" }
# gpui — the wingleeio/zed fork Comet ships. The pinned rev carries f596cde
# ("destination alpha on transparent windows: Porter-Duff OVER, not additive"),
# which our transparent rounded main-window shell depends on.
@@ -183,6 +188,7 @@ windows-sys = { version = "0.59", features = [
"Win32_Security",
"Win32_System_SystemInformation",
"Win32_System_Threading",
+ "Win32_UI_Shell",
"Win32_UI_WindowsAndMessaging",
] }
diff --git a/apps/desktop-gpui/dev.sh b/apps/desktop-gpui/dev.sh
index 8dff625127..cd92c3edd6 100755
--- a/apps/desktop-gpui/dev.sh
+++ b/apps/desktop-gpui/dev.sh
@@ -4,17 +4,12 @@
# app persists its window state through CAP_GPUI_DEV_RESTORE and reopens where
# it was, and the swap waits out an in-flight recording (see dev_restore.rs).
set -uo pipefail
-cd "$(dirname "$0")"
+cd "$(dirname "$0")" || exit 1
STATE_FILE="$PWD/target/dev-restore.json"
BIN="$PWD/target/debug/cap-gpui"
BUILD=cargo
-# Cargo.toml turns incremental off to keep the dep tree's caches off a full
-# disk, but deps never rebuild in this loop -- the cache this creates is the
-# app crate's only, and it takes a warm rebuild from ~41s to 3-23s.
-export CARGO_INCREMENTAL=1
-
WATCH_PATHS=(src assets Cargo.toml)
[ -d resources ] && WATCH_PATHS+=(resources)
for crate in camera scap-targets recording timestamp utils project rendering editor export; do
@@ -84,7 +79,7 @@ while true; do
if [ "$CURRENT" != "$LAST" ]; then
LAST="$CURRENT"
echo "[dev] building..."
- if "$BUILD" build; then
+ if "$BUILD" build --config profile.dev.package.cap-desktop-gpui.incremental=true; then
if [ -n "$APP_PID" ] || gpui_owns_session || instance_live; then
stop_app
start_app
diff --git a/apps/desktop-gpui/examples/audio-readiness-benchmark.rs b/apps/desktop-gpui/examples/audio-readiness-benchmark.rs
new file mode 100644
index 0000000000..e0fcf62312
--- /dev/null
+++ b/apps/desktop-gpui/examples/audio-readiness-benchmark.rs
@@ -0,0 +1,302 @@
+use std::{
+ path::PathBuf,
+ sync::{Arc, atomic::AtomicBool},
+ time::Instant,
+};
+
+use cap_audio::{AudioData, AudioStream, ChunkRead};
+use sha2::{Digest, Sha256};
+use tokio::sync::watch;
+
+fn main() -> anyhow::Result<()> {
+ let path = std::env::args_os()
+ .nth(1)
+ .map(PathBuf::from)
+ .ok_or_else(|| anyhow::anyhow!("Pass an audio path"))?;
+ if std::env::var_os("CAP_BENCH_PROGRESSIVE_AUDIO").is_some() {
+ return progressive_audio(path);
+ }
+ background_audio(path)
+}
+
+#[derive(Clone)]
+struct PreviousAudioLoader {
+ rx: watch::Receiver