[package] name = "catacomb" version = "0.1.0" edition = "2021" description = "Self-hosted archive for YouTube, TikTok, Twitch, Vimeo, Bandcamp, SoundCloud, Odysee and more. Desktop GUI + web UI, bundled yt-dlp with curl_cffi impersonation, Plex export, SQLite-backed resume tracking. AGPL-3.0." license = "AGPL-3.0-only" repository = "https://codeberg.org/anassaeneroi/catacomb" homepage = "https://codeberg.org/anassaeneroi/catacomb" authors = ["InannaBeloved "] readme = "README.md" [dependencies] # Default to the wgpu (Vulkan/Metal/DX) renderer instead of the default glow # (OpenGL) one. NVIDIA + Wayland crashes the GL surface on window resize # (Glutin EGL_BAD_ALLOC / OutOfMemory on maximize); wgpu's Vulkan path # reconfigures the swapchain cleanly. Keep glow compiled in as an escape # hatch for machines where wgpu/Vulkan creates a window but never presents # a frame (`YT_OFFLINE_RENDERER=glow` or `--renderer glow`). eframe = { version = "0.29", default-features = false, features = ["accesskit", "default_fonts", "wayland", "x11", "wgpu", "glow"] } image = { version = "0.25", default-features = false, features = ["webp", "jpeg", "png"] } toml = "0.8" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" rusqlite = { version = "0.31", features = ["bundled"] } r2d2 = "0.8" r2d2_sqlite = "0.24" notify-rust = { version = "4", default-features = false, features = ["z"] } axum = { version = "0.7", features = ["macros", "ws"] } tokio = { version = "1", features = ["full"] } tokio-util = { version = "0.7", features = ["io"] } tokio-stream = "0.1" tower-http = { version = "0.5", features = ["cors", "fs", "compression-gzip"] } argon2 = "0.5" rand = "0.8" # HTTP client for federation (remote-library mode). Pure-Rust TLS (rustls, no # system OpenSSL) to match the bundled-everything posture. Blocking API + a # cookie store so RemoteClient can log into a password-protected peer and # reuse the session; the web layer calls it under spawn_blocking, desktop # calls it directly. reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "blocking", "json", "cookies"] } libc = "0.2.186" # Platform-specific desktop deps. On Linux the tray (ksni — StatusNotifierItem # over zbus) and the rfd file picker (xdg-portal backend) stay pure-Rust with no # GTK build dep, matching notify-rust. On Windows/macOS there's no SNI tray yet # (tray::start is a compiled-out no-op) and rfd falls back to its native backend # (Win32 / AppKit) via its default features. [target.'cfg(target_os = "linux")'.dependencies] ksni = { version = "0.3.4", features = ["tokio"] } rfd = { version = "0.15", default-features = false, features = ["xdg-portal", "tokio"] } [target.'cfg(not(target_os = "linux"))'.dependencies] rfd = { version = "0.15", features = ["tokio"] } # Release Windows builds are linked as a GUI subsystem app (no console window — # see the windows_subsystem attribute in main.rs), which is right for the egui # GUI but means a `--web`/CLI run launched from a terminal has nowhere to print. # windows-sys gives us AttachConsole to reattach to the launching console at # runtime (see attach_windows_console in main.rs). [target.'cfg(windows)'.dependencies] windows-sys = { version = "0.59", features = ["Win32_System_Console"] } [profile.release] opt-level = 3 # Thin LTO does cross-crate inlining without the rust-lld + bundled-sqlite # link breakage that full `lto = true` triggered (the previous !lto note # was about full LTO; thin works with the current toolchain). Worth ~5-10% # on hot paths. lto = "thin" # Codegen-units = 1 trades build time (~30s extra) for tighter inlining # across the whole crate. Worth it for release binaries. codegen-units = 1 # Strip debuginfo from release binaries — cuts binary size by ~30 MB # without affecting runtime. The crash log still captures backtraces at # runtime; those are less informative without symbols but usable with # addr2line against the unstripped build artifact. strip = "debuginfo" # No unwinding tables/landing pads: smaller binary, marginally faster hot # paths. The crash handler (crash.rs panic hook) still fires before the # abort, so crash logging is preserved. Cargo forces `panic=unwind` for # test/bench harnesses automatically, so `cargo test --release` and the # #[cfg(test)] catch_unwind in crash.rs are unaffected. Tradeoff: a panic # in a parallel scan worker aborts the process instead of one worker — # acceptable, those workers treat all fallible I/O with .ok() already. panic = "abort" # ── Debian / Ubuntu package (cargo-deb) ────────────────────────────────────── # `cargo deb` reads this to build a .deb. Runtime deps mirror the PKGBUILD: # yt-dlp + ffmpeg + mpv are invoked as subprocesses, xdg-utils provides # xdg-open, and libxcb is needed by the eframe/winit windowing stack. [package.metadata.deb] maintainer = "InannaBeloved " copyright = "2026, InannaBeloved " license-file = ["LICENSE", "0"] extended-description = """\ Self-hosted archive for YouTube, TikTok, Twitch, Vimeo, Bandcamp, \ SoundCloud, Odysee and more. Ships a desktop GUI and a mobile-friendly \ web UI, with a bundled yt-dlp (curl_cffi impersonation), Plex export, \ and SQLite-backed resume tracking.""" section = "video" priority = "optional" # yt-dlp / ffmpeg / mpv are runtime subprocess deps, not link-time, so # cargo-deb's auto-detection won't find them — list explicitly. libxcb # is the one shared library the GUI actually dlopens. depends = "libc6, libxcb1, yt-dlp, ffmpeg, mpv, xdg-utils" recommends = "libnotify4" assets = [ ["target/release/catacomb", "usr/bin/", "755"], ["catacomb.desktop", "usr/share/applications/catacomb.desktop", "644"], ["icon.png", "usr/share/pixmaps/catacomb.png", "644"], ["README.md", "usr/share/doc/catacomb/README.md", "644"], ] # ── Fedora / RHEL / openSUSE package (cargo-generate-rpm) ───────────────────── # `cargo generate-rpm` reads this. Run `cargo build --release` first; it # packages the already-built binary rather than building itself. [package.metadata.generate-rpm] summary = "Self-hosted multi-platform video archiver with desktop + web UI" license = "AGPLv3" # RPM distro package names differ from Debian's. yt-dlp is `yt-dlp` on # Fedora; ffmpeg lives in RPM Fusion but we still declare the dep. requires = { yt-dlp = "*", ffmpeg = "*", mpv = "*", "xdg-utils" = "*" } assets = [ { source = "target/release/catacomb", dest = "/usr/bin/catacomb", mode = "755" }, { source = "catacomb.desktop", dest = "/usr/share/applications/catacomb.desktop", mode = "644" }, { source = "icon.png", dest = "/usr/share/pixmaps/catacomb.png", mode = "644" }, { source = "README.md", dest = "/usr/share/doc/catacomb/README.md", mode = "644" }, { source = "LICENSE", dest = "/usr/share/licenses/catacomb/LICENSE", mode = "644" }, ]