refactor(desktop): replace the native voice engine with a standalone hardware encoder (#1677)

This commit is contained in:
Hampus authored and GitHub committed 2026-08-16 19:24:31 +02:00
1 parent 98c40c6979
commit ccdd85b099
893 files changed
+620 -371790

No files matched your search

+296
View File
@@ -0,0 +1,296 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "bitflags"
version = "2.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "convert_case"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "affbf0190ed2caf063e3def54ff444b449371d55c58e513a95ab98eca50adb49"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "ctor"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "914a755b7c2d4af2bdcff7ce1739e2db9a1b81a9b07123d8015786ae03c0980d"
[[package]]
name = "fluxer_hardware_encoder"
version = "0.0.0"
dependencies = [
"libloading",
"napi",
"napi-build",
"napi-derive",
]
[[package]]
name = "futures"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e"
[[package]]
name = "futures-executor"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed"
[[package]]
name = "futures-macro"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44"
dependencies = [
"proc-macro2",
"quote",
"syn 3.0.3",
]
[[package]]
name = "futures-sink"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d"
[[package]]
name = "futures-task"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd"
[[package]]
name = "futures-util"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"slab",
]
[[package]]
name = "libc"
version = "0.2.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
[[package]]
name = "libloading"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60"
dependencies = [
"cfg-if",
"windows-link",
]
[[package]]
name = "memchr"
version = "2.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
[[package]]
name = "napi"
version = "3.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "459197f1592f4c3dbbf9c1b13f5a4599a343e4ef66b96bc340e2a518b36a6662"
dependencies = [
"bitflags",
"ctor",
"futures",
"libc",
"napi-build",
"napi-sys",
"nohash-hasher",
"rustc-hash",
]
[[package]]
name = "napi-build"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60fdf9b392c50e7c4170fa633bd909490ed7835cea4c046776d1a4dd8d2ae0ab"
[[package]]
name = "napi-derive"
version = "3.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa55ea69990c90b888e9e77044410e304ce7f35de599dc6d0b5c1923d2e59af"
dependencies = [
"convert_case",
"ctor",
"napi-derive-backend",
"proc-macro2",
"quote",
"syn 2.0.119",
]
[[package]]
name = "napi-derive-backend"
version = "6.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df4056ac7c18e4438ccf0edaed4340ca0d269278c8ec19284f7b23cb039fd0ae"
dependencies = [
"convert_case",
"proc-macro2",
"quote",
"semver",
"syn 2.0.119",
]
[[package]]
name = "napi-sys"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85fbf1fa9f1babfe396d74bbbf52b3643770243e8f5b0b46715d4caf7f0dfc9a"
dependencies = [
"libloading",
]
[[package]]
name = "nohash-hasher"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
[[package]]
name = "pin-project-lite"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
name = "proc-macro2"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustc-hash"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d"
[[package]]
name = "semver"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]]
name = "slab"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
[[package]]
name = "syn"
version = "2.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "unicode-segmentation"
version = "1.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8"
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
@@ -0,0 +1,22 @@
[package]
name = "fluxer_hardware_encoder"
version = "0.0.0"
edition = "2024"
license = "AGPL-3.0-or-later"
publish = false
[workspace]
resolver = "2"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
napi = {version = "3.9.1", default-features = false, features = ["dyn-symbols", "napi8"]}
napi-derive = "3.5.6"
[target.'cfg(any(target_os = "linux", target_os = "windows"))'.dependencies]
libloading = "0.9.0"
[build-dependencies]
napi-build = "2.3.2"
@@ -0,0 +1,56 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
use std::env;
fn main() {
println!("cargo:rustc-check-cfg=cfg(fluxer_linux_nvenc)");
println!("cargo:rustc-check-cfg=cfg(fluxer_windows_nvenc)");
println!("cargo:rustc-check-cfg=cfg(fluxer_windows_nvenc_encoder)");
println!("cargo:rustc-check-cfg=cfg(fluxer_macos_videotoolbox)");
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
let is_macos = target_os == "macos";
let has_linux_nvenc = target_os == "linux" && supports_nvenc_arch();
let has_windows_nvenc = target_os == "windows" && supports_nvenc_arch();
let has_windows_nvenc_encoder = has_windows_nvenc;
println!(
"cargo:rustc-env=FLUXER_LINUX_NVENC_COMPILED={}",
if has_linux_nvenc { "1" } else { "0" }
);
println!(
"cargo:rustc-env=FLUXER_WINDOWS_NVENC_COMPILED={}",
if has_windows_nvenc { "1" } else { "0" }
);
println!(
"cargo:rustc-env=FLUXER_WINDOWS_NVENC_ENCODER_COMPILED={}",
if has_windows_nvenc_encoder { "1" } else { "0" }
);
if has_linux_nvenc {
println!("cargo:rustc-cfg=fluxer_linux_nvenc");
}
if has_windows_nvenc {
println!("cargo:rustc-cfg=fluxer_windows_nvenc");
}
if has_windows_nvenc_encoder {
println!("cargo:rustc-cfg=fluxer_windows_nvenc_encoder");
}
println!(
"cargo:rustc-env=FLUXER_MACOS_VIDEOTOOLBOX_COMPILED={}",
if is_macos { "1" } else { "0" }
);
if is_macos {
println!("cargo:rustc-cfg=fluxer_macos_videotoolbox");
println!("cargo:rustc-link-lib=framework=CoreFoundation");
println!("cargo:rustc-link-lib=framework=CoreMedia");
println!("cargo:rustc-link-lib=framework=VideoToolbox");
}
napi_build::setup();
}
fn supports_nvenc_arch() -> bool {
let Ok(arch) = env::var("CARGO_CFG_TARGET_ARCH") else {
return false;
};
matches!(arch.as_str(), "x86_64" | "i686" | "aarch64") || arch.contains("arm")
}
+17
View File
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
export interface HardwareEncoderCapability {
available: boolean;
backend: 'nvenc' | 'videotoolbox' | 'none';
compiled: boolean;
runtime: boolean;
codecs: Array<string>;
zeroCopy: boolean;
nativeInputs: Array<'dmabuf' | 'd3d11-texture' | string>;
reason?: string;
detail?: string;
}
export declare function isSupported(): boolean;
export declare function getHardwareEncoderCapability(): HardwareEncoderCapability;
export declare function getHardwareEncoderCapabilities(): HardwareEncoderCapability;
@@ -0,0 +1,84 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
const {existsSync} = require('node:fs');
const {join, sep} = require('node:path');
const MODULE_NAME = '@fluxer/hardware-encoder';
function resolveNativeRoot() {
const asarSegment = `${sep}app.asar${sep}`;
if (!__dirname.includes(asarSegment)) return __dirname;
const unpackedDir = __dirname.replace(asarSegment, `${sep}app.asar.unpacked${sep}`);
return existsSync(unpackedDir) ? unpackedDir : __dirname;
}
function nativeFileName(platform = process.platform, arch = process.arch) {
if ((arch !== 'x64' && arch !== 'arm64') || !['darwin', 'linux', 'win32'].includes(platform)) {
throw new Error(`${MODULE_NAME} not supported on ${platform}-${arch}`);
}
if (platform === 'darwin') return `hardware-encoder.darwin-${arch}.node`;
if (platform === 'linux') return `hardware-encoder.linux-${arch}-gnu.node`;
return `hardware-encoder.win32-${arch}-msvc.node`;
}
let binding = null;
let loadError = null;
try {
const nativePath = join(resolveNativeRoot(), nativeFileName());
if (existsSync(nativePath)) {
try {
binding = require(nativePath);
} catch (error) {
loadError = error instanceof Error ? error : new Error(String(error));
}
} else {
loadError = new Error(`${MODULE_NAME} native binary missing: ${nativePath}`);
}
} catch (error) {
loadError = error instanceof Error ? error : new Error(String(error));
}
function isSupported() {
return Boolean(binding);
}
function unavailableHardwareEncoderCapability(reason, detail) {
return {
available: false,
backend: 'none',
compiled: false,
runtime: false,
codecs: [],
zeroCopy: false,
nativeInputs: [],
reason,
detail,
};
}
function getHardwareEncoderCapability() {
if (!binding) {
return unavailableHardwareEncoderCapability(
'native_binding_unavailable',
loadError ? loadError.message : `${MODULE_NAME} binding unavailable`,
);
}
if (typeof binding.getHardwareEncoderCapability !== 'function') {
return unavailableHardwareEncoderCapability(
'native_capability_unavailable',
`${MODULE_NAME} native binding does not export getHardwareEncoderCapability`,
);
}
return binding.getHardwareEncoderCapability();
}
function getHardwareEncoderCapabilities() {
return getHardwareEncoderCapability();
}
module.exports = {
isSupported,
getHardwareEncoderCapability,
getHardwareEncoderCapabilities,
};
@@ -0,0 +1,27 @@
{
"name": "@fluxer/hardware-encoder",
"version": "0.0.0",
"description": "",
"private": true,
"license": "AGPL-3.0-or-later",
"cpu": [
"x64",
"arm64"
],
"main": "index.js",
"types": "index.d.ts",
"files": [
"index.js",
"index.d.ts",
"hardware-encoder.darwin-x64.node",
"hardware-encoder.darwin-arm64.node",
"hardware-encoder.win32-x64-msvc.node",
"hardware-encoder.win32-arm64-msvc.node",
"hardware-encoder.linux-x64-gnu.node",
"hardware-encoder.linux-arm64-gnu.node"
],
"scripts": {
"build": "cargo run --locked --quiet --manifest-path ../../../tools/ci/Cargo.toml -- build-desktop-native-addon",
"test": "cargo test --manifest-path Cargo.toml"
}
}
File diff suppressed because it is too large. Load diff