Repository navigation
Add Swift SDK support via UniFFI bridge - #1
Conversation
|
siGit Code Review is paused because the linked siGit account has reached its monthly cloud allowance. |
94f7c16 to
699fc60
Compare
There was a problem hiding this comment.
This PR adds the demucs-ffi crate, a UniFFI translation layer over demucs-core that exposes model loading, warmup, separation, and cache management to Swift. The engine wraps a Demucs<Wgpu> behind a Mutex (burn modules are Send but not Sync), runs all blocking work on dedicated 8 MB worker threads via run_blocking, and bridges ForwardListener events into monotonic progress fractions for UI consumption. Downloads write to a .part file and rename atomically, with listener-based cancellation. A build.rs stubs out ___chkstk_darwin for tier-3 Apple targets, and a thin uniffi-bindgen wrapper crate is added for Swift codegen. The workspace Cargo.toml registers the two new crates. Overall the design is clean and the concurrency reasoning is sound; the findings below are about robustness of the download path and a maintenance hazard in model mapping.
Automated review by siGit Code Review · commit 699fc60 · see the review dashboard
demucs-ffi exposes demucs-core over UniFFI for the demucs-swift package: model catalog and cache management, weight download with progress, and a DemucsEngine object that loads, warms up and separates on the wgpu/Metal backend. Blocking work runs on dedicated 8 MB-stack threads behind async exports, so no async runtime is needed; progress callbacks can cancel. uniffi-bindgen pins the generator to the same UniFFI version so the Swift bindings always match the scaffolding. Co-Authored-By: siGit Code <noreply@sigit.si> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
burn's metal feature turns on cubecl-wgpu's MSL codegen, which cubecl-wgpu 0.9 implements only for macOS. On iOS, tvOS and visionOS it leaves backend::request_device and register_features undefined, so the XCFramework build failed at the first iOS target. Those platforms still run on Metal through wgpu's WGSL path. Co-Authored-By: siGit Code <noreply@sigit.si> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A stalled connection blocked reader.read() on the download thread forever, and the cancel callback only runs between reads, so nothing could stop it. Add 30 s connect and 60 s per-read timeouts. There is no overall timeout, since the fine-tuned weights are 333 MB. all_models() mapped any unknown model id to FourStem. It now lists the three variants directly, so a model added to demucs-core without an FFI variant fails all_models_matches_core_metadata instead of being mislabelled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017hgnUBegVyTQzrjT5zjBB7
8454a82 to
857d669
Compare
There was a problem hiding this comment.
The PR adds the demucs-ffi crate, a UniFFI translation layer over demucs-core exposing model download, cache management, loading, warmup, and audio separation to Swift. The engine wraps burn's Wgpu backend behind a Mutex, runs all blocking work on dedicated 8 MB worker threads via run_blocking, and bridges ForwardListener events into monotonic progress fractions. Downloads write to a .part file and rename atomically. A build.rs stub provides ___chkstk_darwin for tier-3 Apple targets, and a thin uniffi-bindgen wrapper crate is included for Swift code generation. Earlier review items (download timeouts and explicit all_models listing) were addressed in a follow-up commit.
Automated review by siGit Code Review · commit 857d669 · see the review dashboard
Two download_model calls for the same file both passed the exists check and wrote into the same .part path, so the renamed file could be a mix of both. The fine-tuned stem selections share one file, which makes this easy to hit from Swift. A per-file lock now makes the second caller wait and then return early once the file is cached. Also drop ureq's gzip feature. Content-Length is the compressed size when the server gzips, which threw off the progress fraction, and safetensors barely compress anyway. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-Authored-By: siGit Code <noreply@sigit.si>
This PR adds the UniFFI-based
demucs-fficrate that the demucs-swift XCFramework is built from.It is the second PR in a stack: #2 (Clippy fix) → #1 → #3 (XCFramework build script) → #4 (release workflow).
Summary
Introduces the
demucs-fficrate as a thin translation layer overdemucs-core, exposing audio separation functionality to Swift through UniFFI.Key Changes
New
demucs-fficrate (demucs-ffi/src/lib.rs):demucs-coretypes in FFI-safe records and enums (prefixedFfi)FfiDemucsEnginefor model loading, warmup, and audio separationBuild infrastructure:
demucs-ffi/build.rs: Compiles tvOS/visionOS stack probe stub (workaround for tier-3 targets)demucs-ffi/scripts/tvos_chkstk.s: No-op stack probe helper for embedded Apple platformsuniffi-bindgen/: Thin wrapper around UniFFI's CLI for generating Swift bindingsConfiguration:
Cargo.tomlworkspace to include new cratesmetalfeature (MSL codegen) on macOS only. cubecl-wgpu 0.9 implements it only for macOS, so enabling it for every Apple target broke the iOS, tvOS and visionOS builds. Those platforms still run on Metal through wgpu's WGSL path.Notable Implementation Details
Mutex(notSync) since burn modules aren't thread-safe; status queries use a separateArc<Mutex<Option<FfiDemucsModel>>>to avoid blocking on inferenceForwardListenerevents into monotonic fractions for UI consumption.part, rename on completion) to prevent truncated files from being trusted as cachedhttps://claude.ai/code/session_017hgnUBegVyTQzrjT5zjBB7