-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathflake.nix
More file actions
174 lines (163 loc) · 8 KB
/
Copy pathflake.nix
File metadata and controls
174 lines (163 loc) · 8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
{
description = "videoeditor — scripted short-video renderer for developers (Rust + web + ffmpeg)";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
# rust with the wasm32-unknown-unknown target for the Leptos recorder UI
# (nixpkgs' rustc ships host-only std)
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, rust-overlay }:
let
systems = [ "aarch64-darwin" "x86_64-darwin" "x86_64-linux" "aarch64-linux" ];
forAllSystems = f: nixpkgs.lib.genAttrs systems (system:
f (import nixpkgs { inherit system; overlays = [ rust-overlay.overlays.default ]; }));
# Pinned voice models — the local-by-default speech stack:
# whisper.cpp STT (ggml weights) + a piper voice for sherpa-onnx TTS.
# Shared by the installed package and the dev shell so both transcribe
# and narrate offline, no API key.
voiceModels = pkgs: {
whisper = pkgs.fetchurl {
url = "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.en.bin";
hash = "sha256-oDd5yG3zMjB19eeWyyzlAp8A7Ihp7uP9+4l6/jbG0AI=";
};
piperVoice = pkgs.fetchzip {
url = "https://github.com/k2-fsa/sherpa-onnx/releases/download/tts-models/vits-piper-en_US-lessac-medium.tar.bz2";
hash = "sha256-/iu4rTEC7716gmVcemQs4mHcChiyB0zadO4ikPNLzcs=";
};
};
in
{
# The preferred install path: `nix profile install github:security-union/videoeditor`
# (or `nix run` it). Builds the pinned workspace and wraps the binary so
# EVERY runtime dependency is pinned: ffmpeg, whisper.cpp + sherpa-onnx
# (and their models) for local STT/TTS on all systems, chromium
# (nixpkgs build) on Linux, and playwright's free-licensed Chrome for
# Testing bundle on macOS — nixpkgs' own `chromium` is Linux-only and
# `google-chrome` is unfree. CHROME_BIN still overrides everywhere.
packages = forAllSystems (pkgs:
let
lib = pkgs.lib;
runtimeDeps = [ pkgs.ffmpeg pkgs.whisper-cpp pkgs.sherpa-onnx ]
++ lib.optionals pkgs.stdenv.isLinux [ pkgs.chromium ];
pwBrowsers = pkgs.playwright-driver.browsers-chromium;
models = voiceModels pkgs;
in
rec {
videoeditor = pkgs.rustPlatform.buildRustPackage {
pname = "videoeditor";
version = (builtins.fromTOML (builtins.readFile ./Cargo.toml)).workspace.package.version;
src = ./.;
cargoLock.lockFile = ./Cargo.lock;
nativeBuildInputs = [ pkgs.makeWrapper ];
# Tests that shell out to ffmpeg/Chrome don't exist yet; unit tests
# (parser, fit-check) run in the sandbox as-is.
# On darwin the Chrome-for-Testing binary path embeds a playwright
# revision (chromium-NNNN/chrome-mac-<arch>/…), so locate it at
# build time and bake the store path — the build fails loudly if
# the bundle layout ever changes.
postInstall = ''
${lib.optionalString pkgs.stdenv.isDarwin ''
chromeBin="$(find -L ${pwBrowsers} -type f \
\( -name "Google Chrome for Testing" -o -name "Chromium" \) | head -1)"
test -n "$chromeBin" || { echo "no chromium in playwright bundle"; exit 1; }
''}
# Ship templates/formats as a store path instead of relying on
# the first-run cache extraction — fully pinned, never stale.
mkdir -p $out/share/videoeditor
cp -R crates/videoeditor/templates crates/videoeditor/formats $out/share/videoeditor/
wrapProgram $out/bin/videoeditor \
--prefix PATH : ${lib.makeBinPath runtimeDeps} \
--set-default VIDEOEDITOR_ROOT $out/share/videoeditor \
--set-default WHISPER_MODEL ${models.whisper} \
--set-default PIPER_VOICE ${models.piperVoice} ${lib.optionalString pkgs.stdenv.isDarwin ''\
--set-default CHROME_BIN "$chromeBin"''}
'';
meta = {
description = "Scripted short-video renderer: markdown in, vertical video out";
homepage = "https://github.com/security-union/videoeditor";
license = lib.licenses.mit;
mainProgram = "videoeditor";
};
};
default = videoeditor;
});
apps = forAllSystems (pkgs: {
default = {
type = "app";
program = "${self.packages.${pkgs.system}.videoeditor}/bin/videoeditor";
};
});
devShells = forAllSystems (pkgs:
let
pwBrowsers = pkgs.playwright-driver.browsers-chromium;
models = voiceModels pkgs;
# one toolchain for host AND wasm: the recorder UI
# (videoeditor-record-ui) compiles to wasm32-unknown-unknown
rustToolchain = pkgs.rust-bin.stable.latest.default.override {
targets = [ "wasm32-unknown-unknown" ];
};
# `videoeditor` inside the dev shell = cargo run over THIS checkout,
# so the command always matches the source you're editing (a
# store-built binary here would silently go stale). First call
# compiles; cargo caches after that.
videoeditorDev = pkgs.writeShellScriptBin "videoeditor" ''
exec cargo run --release --quiet \
--manifest-path "''${VIDEOEDITOR_SRC:?nix develop must start at the repo root}/Cargo.toml" \
-p videoeditor -- "$@"
'';
in
{
default = pkgs.mkShell {
packages = with pkgs; [
# Rust toolchain — the orchestrator (host + wasm32 targets)
rustToolchain
rust-analyzer
# Recorder UI: Leptos → wasm. wasm-bindgen-cli must match the
# workspace's pinned wasm-bindgen crate — bump them together.
trunk
wasm-bindgen-cli
# Recorder e2e: playwright runner + pinned browsers
nodejs
playwright-test
# Media pipeline
ffmpeg
yt-dlp
# Local speech stack: whisper.cpp STT + piper-voice TTS via
# sherpa-onnx (models exported in the shellHook)
whisper-cpp
sherpa-onnx
# Repo tooling
git
just
jq
videoeditorDev
] ++ pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.chromium ];
shellHook = ''
export VIDEOEDITOR_SRC="$PWD"
echo "videoeditor dev shell — rustc $(rustc --version | cut -d' ' -f2), ffmpeg $(ffmpeg -version 2>/dev/null | head -1 | cut -d' ' -f3)"
echo "\`videoeditor\` builds+runs this checkout (cargo run); first call compiles"
# Playwright e2e (just e2e): pinned browser bundle + resolvable
# @playwright/test for the config/spec imports.
export PLAYWRIGHT_BROWSERS_PATH=${pwBrowsers}
# Local STT/TTS models, same pins as the installed package.
export WHISPER_MODEL="''${WHISPER_MODEL:-${models.whisper}}"
export PIPER_VOICE="''${PIPER_VOICE:-${models.piperVoice}}"
export PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS=true
export NODE_PATH=${pkgs.playwright-test}/lib/node_modules
# Rendering uses the same pinned browser as the installed
# package: chromium from nixpkgs on Linux (found via PATH),
# playwright's Chrome for Testing on darwin. CHROME_BIN overrides.
${pkgs.lib.optionalString pkgs.stdenv.isDarwin ''
if [ -z "$CHROME_BIN" ]; then
CHROME_BIN="$(find -L ${pwBrowsers} -type f \( -name "Google Chrome for Testing" -o -name "Chromium" \) 2>/dev/null | head -1)"
export CHROME_BIN
fi
''}
'';
};
});
};
}