veodl 1.12.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE +21 -21
  3. package/README.md +178 -97
  4. package/bin/veo.js +47 -2
  5. package/docs/AGENT_GUIDE.md +1 -1
  6. package/native/android-arm64/veo +0 -0
  7. package/native/darwin-arm64/veo +0 -0
  8. package/native/darwin-x64/veo +0 -0
  9. package/native/linux-arm64/veo +0 -0
  10. package/native/linux-x64/veo +0 -0
  11. package/native/win32-arm64/veo.exe +0 -0
  12. package/native/win32-x64/veo.exe +0 -0
  13. package/package.json +53 -57
  14. package/src/alias.js +0 -258
  15. package/src/backend-update.js +0 -191
  16. package/src/backend.js +0 -572
  17. package/src/changes.js +0 -278
  18. package/src/cli.js +0 -785
  19. package/src/compatibility.js +0 -39
  20. package/src/config-clipboard.js +0 -67
  21. package/src/config-diagnostics.js +0 -155
  22. package/src/config-editor.js +0 -404
  23. package/src/config-errors.js +0 -64
  24. package/src/config-reset.js +0 -39
  25. package/src/config-template.js +0 -227
  26. package/src/config.js +0 -307
  27. package/src/disk-space.js +0 -68
  28. package/src/doctor.js +0 -306
  29. package/src/download-cache.js +0 -31
  30. package/src/downloader.js +0 -704
  31. package/src/execution.js +0 -68
  32. package/src/experimental-fragments.js +0 -29
  33. package/src/flush.js +0 -66
  34. package/src/history.js +0 -173
  35. package/src/inline-region.js +0 -72
  36. package/src/inspect-media.js +0 -179
  37. package/src/interactive.js +0 -120
  38. package/src/jobs.js +0 -218
  39. package/src/legacy-config-comments.js +0 -106
  40. package/src/media-assets.js +0 -272
  41. package/src/naming.js +0 -54
  42. package/src/open-file.js +0 -15
  43. package/src/option-suggestions.js +0 -43
  44. package/src/output.js +0 -81
  45. package/src/path-links.js +0 -53
  46. package/src/paths.js +0 -26
  47. package/src/playlist.js +0 -31
  48. package/src/progress.js +0 -341
  49. package/src/run-archive.js +0 -148
  50. package/src/runs.js +0 -346
  51. package/src/source-discovery.js +0 -305
  52. package/src/state.js +0 -27
  53. package/src/stats.js +0 -63
  54. package/src/terminal-size.js +0 -8
  55. package/src/terminal-title.js +0 -19
  56. package/src/tool-setup.js +0 -289
  57. package/src/uninstall.js +0 -222
  58. package/src/updater.js +0 -229
  59. package/src/utils.js +0 -208
  60. package/src/version.js +0 -38
package/CHANGELOG.md CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  All notable changes to veo. This project follows [Semantic Versioning](https://semver.org/).
4
4
 
5
+ ## 2.0.0
6
+
7
+ ### Changed
8
+
9
+ - **Native Rust binary**: veo is rewritten in Rust and ships as a single native executable per platform. Node.js is no longer required to run veo; `npm install -g veodl` keeps working and installs the matching prebuilt binary from the single veodl package. Commands, flags, JSON output, config files, profiles, run records, history, statistics and retry jobs stay compatible, including resumable staging directories of 1.x.
10
+ - Startup is about ten times faster, and SHA-256 checks of yt-dlp, FFmpeg and FFprobe run in parallel with hardware acceleration, so every run still verifies the managed tools before use.
11
+ - A single-URL download reuses the metadata read while checking the page, so the backend starts once instead of twice per URL. Dry runs, quality and subtitle listings benefit the same way.
12
+ - First-use FFmpeg/FFprobe setup downloads both tools in parallel and publishes them by rename instead of copying them again.
13
+ - yt-dlp receives an installed Node.js, Deno or Bun as JavaScript runtime for YouTube challenges; `VEO_JS_RUNTIME=name:path` selects one explicitly. `veo doctor` reports the runtime instead of the Node.js version.
14
+ - Cancelling a download stops yt-dlp together with the FFmpeg processes it started.
15
+
16
+ ### Removed
17
+
18
+ - Unused compatibility code for configuration comments of the former German template.
19
+
5
20
  ## 1.12.1
6
21
 
7
22
  ### Fixed
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 veo contributors
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 veo contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -8,9 +8,12 @@ Automating with an agent? Start with the [agent guide](docs/AGENT_GUIDE.md) for
8
8
 
9
9
  ## Install and run
10
10
 
11
- Requires **Node.js 22+** and npm. Internet access is needed for installation and first-use backend setup.
11
+ veo is a single native executable (written in Rust) for Windows, macOS, Linux and
12
+ Android/Termux. Internet access is needed for installation and first-use backend setup.
12
13
 
13
- The npm package is `veodl`; the installed commands are `veo` and `veodl`.
14
+ The npm package is `veodl`; the installed commands are `veo` and `veodl`. npm installs the
15
+ prebuilt binary for your platform from a matching `veodl-<platform>-<arch>` package; no
16
+ install scripts run. Node.js is only needed for npm itself, not to run downloads.
14
17
 
15
18
  ```bash
16
19
  npx veodl "https://example.com/video.mp4"
@@ -30,16 +33,22 @@ JavaScript support with `pkg install -y`. On desktop systems, missing media tool
30
33
  are downloaded into veo's own cache. Run `veo doctor fix` to prepare everything
31
34
  before downloading. Plain `veo doctor`, help and version do not install tools.
32
35
 
33
- From this checkout, without publishing:
36
+ Without npm, download the binary for your platform from the GitHub releases page, or
37
+ build it with Rust 1.85+:
34
38
 
35
39
  ```bash
36
- npm install
37
- node bin/veo.js --help
38
- npm link
39
- veo "https://example.com/video.mp4"
40
+ cargo install --git https://github.com/Mailo037/veodl
41
+ ```
42
+
43
+ From this checkout:
44
+
45
+ ```bash
46
+ cargo build --release # target/release/veo
47
+ cargo test # unit and offline end-to-end tests
48
+ cargo test --test smoke -- --ignored # real downloads with yt-dlp and FFmpeg
40
49
  ```
41
50
 
42
- `package.json` maps `"veo": "./bin/veo.js"`; npm creates the executable/shim automatically. No custom command prefix is needed. Use only trusted URLs, and quote URLs to protect query strings from your shell.
51
+ Use only trusted URLs, and quote URLs to protect query strings from your shell.
43
52
 
44
53
  If something does not work, run `veo doctor` first: it inspects the whole local setup and prints one line per check.
45
54
 
@@ -54,50 +63,109 @@ regular command arguments; veo never starts a prompt in a script.
54
63
  ## Usage
55
64
 
56
65
  ```text
57
- veo <url> [<url>...] [options]
58
-
59
- Options:
60
- -q, --quality <quality> best, 2160p, 1440p, 1080p, 720p, 480p, 360p
61
- -o, --output <path> Output directory (default: current working directory)
62
- -r, --rename <name> Filename without extension; * inserts the original title
63
- --closest-quality Nearest available resolution instead of an upper bound
64
- --open Open the saved file with your default app
65
- --audio Audio only (MP3 by default)
66
- --format <format> Video: mp4, mkv, webm, mov
67
- Audio: mp3, m4a, aac, opus, flac, wav
68
- --recode Explicit video conversion (requires --format)
69
- --playlist-concurrency <n> Parallel playlist entries, 1-4 (default: 2)
70
- --playlist Download every entry of a playlist or channel URL
71
- -N, --concurrent-fragments <n> Parallel fragments, 1-64 (default: 8; 17-64 experimental)
72
- --experimental-fragments Explicitly accept experimental values above 16
73
- --subs Download subtitles (default languages: en)
74
- --auto-subs Include automatically generated subtitles
75
- --sub-langs <langs> Subtitle languages, e.g. "de,en" (manual unless --auto-subs)
76
- --sub-format <format> Prefer subtitle formats, e.g. srt/vtt/best
77
- --list-subs Show manual and automatic subtitle availability
78
- --embed-subs Embed subtitles into the video file
79
- --embed-metadata Embed title, date and other metadata
80
- --embed-thumbnail Embed the thumbnail
81
- --sponsorblock-remove <categories> e.g. "sponsor,selfpromo"
82
- --section <range> Only a time range, e.g. "*10:00-12:00"
83
- --cookies <file> Netscape cookie file, for content you may access
66
+ Usage:
67
+ veo <url> [<url>...] [options]
68
+
69
+ Download:
70
+ -q, --quality <quality> Video quality (best, 2160p, 1440p, 1080p, 720p, 480p, 360p)
71
+ Numeric qualities are an upper bound: -q 720p never
72
+ downloads 2160p.
73
+ --closest-quality Pick the nearest available resolution, above or below
74
+ -o, --output <path> Output directory (default: current directory)
75
+ -r, --rename <name> Filename without extension; * inserts the original title
76
+ --audio Download audio only (default: mp3)
77
+ --format <format> Video: mp4, mkv, webm, mov; audio: mp3, m4a, aac, opus, flac, wav
78
+ Video uses lossless remux; incompatible codecs fail.
79
+ --compatible Ensure MP4 H.264/AAC; converts only when needed (may lose quality)
80
+ --recode Allow video conversion (requires --format; may lose quality)
81
+ --open Open the saved file with your default app
82
+ --resume Keep partial data and continue an interrupted download
83
+ --skip-existing Skip matching downloads still present on disk
84
+ --section <range> Download only a time range, e.g. "*10:00-12:00"
85
+ --sponsorblock-remove <categories>
86
+ Remove sponsor segments, e.g. "sponsor,selfpromo"
87
+
88
+ Subtitles and metadata:
89
+ --subs Download subtitles (default languages: en)
90
+ --auto-subs Include automatically generated subtitles
91
+ --sub-langs <langs> Subtitle languages, e.g. "de,en" (manual unless --auto-subs)
92
+ --sub-format <format> Preferred subtitle format, e.g. srt/vtt/best
93
+ --list-subs Show manual and automatic subtitle languages, then exit
94
+ --embed-subs Embed subtitles into the video file
95
+ --embed-metadata Embed title, date and other metadata
96
+ --embed-thumbnail Embed the thumbnail
97
+
98
+ Playlists and batches:
99
+ --playlist Download every entry of a playlist or channel URL
100
+ --playlist-items <list> Select playlist entries, e.g. 1,3-5 (implies --playlist)
101
+ --playlist-concurrency <n> Simultaneous playlist downloads (1-4; default: 2)
102
+ --concurrent-downloads <n> Parallel URLs/batch entries (1-4; default: 2)
103
+ --batch-file <file> Read URLs from a file (one per line; # comments)
104
+ --retry-failed <id|file> Retry failed/unfinished items by run ID or job file
105
+
106
+ Naming and privacy:
107
+ --filename-template <s> Filename without extension, e.g. {index} - {title}
108
+ --folder-template <s> Relative folders, e.g. {channel}/{year}
109
+ --neutral-filename Use a random video name; omit title and naming templates
110
+ --incognito Save media without run IDs, history, stats or retry data
111
+
112
+ Inspect before downloading:
113
+ --list-qualities Show available video resolutions and exit
114
+ --list-qualitys Alias for --list-qualities
115
+ --list-formats Show the available formats and exit
116
+ --list-sources Find video sources loaded by a web page and exit
117
+ --auto-list-sources Search after no video is found (default: on)
118
+ --source <n> Select source number from that page (also for scripts)
119
+ --deep-scan Check every media candidate found during source search
120
+ --timeout <duration> Source search deadline, e.g. 30, 30s or 2m (5s-10m)
121
+ --dry-run Show what would be downloaded and exit
122
+
123
+ Network and performance:
124
+ -N, --concurrent-fragments <n>
125
+ Parallel fragments (1-64; default: 8); 17-64 are experimental
126
+ --experimental-fragments Explicitly accept experimental values above 16
127
+ Otherwise requires terminal confirmation before download
128
+ --adaptive-concurrency Reduce connections and retry temporary failures (default: on)
129
+ --check-space Estimate cache/output space before downloading (default: on)
130
+ --cookies <file> Netscape cookie file, for content you may access
84
131
  --cookies-from-browser <browser[:profile]>
85
- --resume Keep partial data and continue an interrupted download
86
- --incognito Save media without run ID, history, stats or retry data
87
- --neutral-filename Optional random filename instead of title and templates
88
- --list-qualities Show available video resolutions and exit
89
- --list-formats Show available formats and exit
90
- --dry-run Show what would be downloaded and exit
91
- --verify Probe saved media files with FFprobe (default: off)
92
- --json One JSON object per URL instead of prose
93
- --profile <name> Use a named profile from the config file
94
- --batch-file <file> Read one URL per line (blank lines and # comments ignored)
95
- --retry-failed <id|file> Retry failed/unfinished downloads by run ID or job file
96
- --playlist-items <list> Select entries, e.g. 1,3-5 (implies --playlist)
97
- --skip-existing Skip matching downloads that are still on disk
98
- --no-<boolean-option> Disable a default, e.g. --no-open or --no-audio
99
- -v, --version Show installed version (also: veo version)
100
- -h, --help Show help
132
+ Read cookies from an installed browser
133
+
134
+ Output and scripting:
135
+ --json Print one JSON object per URL instead of prose
136
+ --verify Probe saved media files with FFprobe (default: off)
137
+ --timings Show phase timings (default: on; --no-timings disables)
138
+ --no-color Disable terminal colors (also respects NO_COLOR)
139
+ --profile <name> Apply a named config profile
140
+ --no-<boolean-option> Disable a stored boolean default, e.g. --no-open
141
+ -v, --version Show installed version (also: veo version)
142
+ -h, --help Show help; veo help all lists every option and command
143
+
144
+ Commands:
145
+ veo doctor Diagnose the local setup
146
+ veo update|up [--check] Update veo itself with npm (up is a short alias)
147
+ veo history Show the last 5 downloads (--json for scripting)
148
+ veo history --failed --limit 20
149
+ Filter and extend download history
150
+ veo retry --last Retry the newest failed or unfinished job
151
+ veo runs [id] List active runs; add --json for metadata and progress
152
+ veo stop [id] Stop one run, or every active run
153
+ veo stats Show persistent download statistics
154
+ veo changes [<version>] List release notes; --since <version> for newer changes
155
+ veo subs <url> List available manual and automatic subtitles
156
+ veo inspect <file> Read media metadata; --check-audio measures audio signal
157
+ veo inspect run <id> Inspect saved files from a finished run by its id
158
+ veo backend update Install a newer yt-dlp release (see veo backend --help)
159
+ veo flush Stop veo runs and clear temporary downloads and jobs
160
+ veo config edit|path|profiles|guide|check|show|reset
161
+ Manage defaults and named profiles
162
+ veo config edit [--external|--terminal]
163
+ Choose the configuration editor
164
+ veo profile [list|reset|name]
165
+ Show, list or change the default profile
166
+ veo alias list|add|remove Manage extra command names (wrappers calling veo)
167
+ veo uninstall [-p <name>] Remove one alias, or everything with --yes
168
+ veo version Show the installed version
101
169
  ```
102
170
 
103
171
  ```bash
@@ -224,7 +292,7 @@ example through `veo config edit`. Enable it with `veo URL --profile kompatibel`
224
292
  `"profiles": { "default": { "color": true }, "plain": { "color": false } }`.
225
293
  Use `veo stats --profile plain` or `veo URL --profile plain`; `--color` or
226
294
  `--no-color` overrides the profile for one invocation (except `NO_COLOR`).
227
- External npm/editor output and Node runtime warnings keep their own formatting.
295
+ External npm and editor output keeps its own formatting.
228
296
 
229
297
  ### Filename templates and folders
230
298
 
@@ -750,7 +818,8 @@ because a single stray file in the cache must never stop later runs.
750
818
 
751
819
  ### `veo doctor`
752
820
 
753
- Prints one line per check: `ok`, `warn` or `fail`. It inspects Node.js, the platform, the
821
+ Prints one line per check: `ok`, `warn` or `fail`. It inspects the JavaScript runtime used by
822
+ yt-dlp, the platform, the
754
823
  output directory, the backend cache, yt-dlp (including the SHA-256 of the cached binary and
755
824
  the version it reports), FFmpeg/FFprobe, a system FFmpeg fallback, the config file, leftover
756
825
  partial downloads, stale duplicate-detection records, the npm registry and the yt-dlp release host. It downloads no backend and
@@ -759,8 +828,8 @@ at least one check fails.
759
828
 
760
829
  Run `veo doctor fix` to restore missing or damaged managed tools and check again.
761
830
  It stages bundled FFmpeg/FFprobe and downloads verified yt-dlp when needed. Missing
762
- desktop media tools are installed in veo's cache using npm and the pinned media
763
- packages. On Termux it installs missing native tools with the package manager.
831
+ desktop media tools are downloaded into veo's cache from the pinned media releases and
832
+ verified before use. On Termux it installs missing native tools with the package manager.
764
833
  With `--offline`, it only uses local binaries; missing tools are reported for an online retry.
765
834
  Use `-o PATH` to create and check an output directory. Config errors and invalid overrides
766
835
  are reported for manual correction; PATH and config values are never rewritten.
@@ -770,13 +839,13 @@ A missing system FFmpeg is not a warning when the selected media tools work.
770
839
 
771
840
  YouTube, X/Twitter, TikTok, Vimeo, Reddit, Instagram, and [many other yt-dlp sites](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md) are supported **when publicly accessible and technically available**. Support changes with websites, regions, rate limits, and backend versions; it is not a guarantee that every URL will work.
772
841
 
773
- Official standalone yt-dlp is acquired on first download and cached outside the package directory; help, version and plain doctor never download the backend. The release is pinned and SHA-256 verified against hashes shipped with this package. The npm package has no runtime dependencies and runs no installation scripts.
842
+ Official standalone yt-dlp is acquired on first download and cached outside the package directory; help, version and plain doctor never download the backend. The release is pinned and SHA-256 verified against hashes shipped with this package. The npm package runs no installation scripts; its only dependencies are the optional per-platform packages that carry the veo binary.
774
843
 
775
844
  When no trusted local FFmpeg/FFprobe pair is available, veo downloads both tools directly from the upstream [ffmpeg-static binary releases](https://github.com/eugeneware/ffmpeg-static/releases/tag/b6.1.1). Release URLs, compressed and executable SHA-256 hashes, and byte counts are pinned in the package. The complete pair and its license and README must pass verification before either executable is started. Later uses verify the cached pair again; legacy or damaged cached binaries are not accepted merely because they are executable. Most targets use FFmpeg 6.1.1; Windows ia32 uses the last available pair, FFmpeg 6.0. Old `FFMPEG_BINARIES_URL`, `FFMPEG_BINARY_RELEASE` and `FFMPEG_BIN` variables do not change these downloads. Use `VEO_FFMPEG_PATH` to choose a trusted installed pair explicitly.
776
845
 
777
- The downloaded binaries retain their separate upstream licenses. `FFmpeg.LICENSE` and `FFmpeg.README` are saved next to the cached tools, including upstream source and build information. The JavaScript CLI remains MIT licensed. No Python installation is needed on supported standalone platforms.
846
+ The downloaded binaries retain their separate upstream licenses. `FFmpeg.LICENSE` and `FFmpeg.README` are saved next to the cached tools, including upstream source and build information. veo itself is MIT licensed. No Python installation is needed on supported standalone platforms.
778
847
 
779
- The existing Node executable is explicitly enabled as yt-dlp's JavaScript runtime for YouTube. Local yt-dlp configuration and plugins are disabled for predictable execution. Arguments are passed without a shell.
848
+ An installed Node.js, Deno or Bun (found on PATH, in that order) is passed to yt-dlp as its JavaScript runtime for YouTube; `VEO_JS_RUNTIME=deno:/path/to/deno` selects one explicitly. Without one, yt-dlp uses its own default. Local yt-dlp configuration and plugins are disabled for predictable execution. Arguments are passed without a shell.
780
849
 
781
850
  Windows ARM64 uses an FFmpeg/FFprobe pair found on `PATH`, including the usual
782
851
  WinGet, Chocolatey and `C:\ffmpeg\bin` locations, or automatically downloads x64
@@ -784,7 +853,8 @@ media tools for Windows 11's x64 emulation.
784
853
 
785
854
  ### Android / Termux
786
855
 
787
- With Node.js 22+ and npm already installed in Termux:
856
+ With npm installed in Termux (`pkg install nodejs`), npm fetches the native
857
+ Android binary:
788
858
 
789
859
  ```sh
790
860
  npm install -g veodl
@@ -831,11 +901,15 @@ if you need them on subsequent launches of 1.6.1.
831
901
  - `VEO_FFMPEG_PATH`: directory containing both `ffmpeg` and `ffprobe` executables (with
832
902
  `.exe` on Windows).
833
903
  - `VEO_CONFIG`: path to the config file.
904
+ - `VEO_JS_RUNTIME`: `name:path` of the JavaScript runtime passed to yt-dlp, for example
905
+ `deno:/usr/local/bin/deno` (`node`, `deno`, `bun` or `quickjs`).
906
+ - `VEO_BINARY`: path to a veo executable the npm launcher should start instead of the
907
+ installed platform package (for testing a local build).
834
908
 
835
909
  Automatic setup covers Windows x64/ia32/ARM64, macOS x64/ARM64, Linux x64/ARM64,
836
910
  and Android through Termux. Windows ARM64 media tools require x64 emulation.
837
911
  `--open` uses `termux-open` in Termux; another Android app must be available to view the file.
838
- Other systems should supply trusted native binaries. Node.js 22+, npm, internet
912
+ Other systems should supply trusted native binaries. Internet
839
913
  access, executable private storage and working OS libraries are prerequisites;
840
914
  network blocks or unavailable repositories can still prevent setup. Android's
841
915
  shared-storage permission must be granted by the user. Maintainers should update
@@ -861,46 +935,53 @@ silently falls back to the pinned release.
861
935
 
862
936
  ## Develop and publish
863
937
 
938
+ veo is a Rust crate (Rust 1.85+). The npm package `veodl` contains only a small launcher
939
+ (`bin/veo.js`); the binaries ship in `veodl-<platform>-<arch>` packages generated from
940
+ `Cargo.toml` by `scripts/npm-packages.mjs`.
941
+
864
942
  ```bash
865
- npm install
866
- npm test # unit tests, no network
867
- npm run test:smoke # real downloads: local HTTP server, real yt-dlp, real FFmpeg
868
- npm run test:open # real download plus a controlled desktop-opener replacement
869
- npm pack
870
- npm run check:package # inspect the packed tarball
871
- npm link
872
- veo --version
873
- # Then, authenticated as the account that owns the name:
874
- npm publish
943
+ cargo build --release # target/release/veo
944
+ cargo test # unit tests and offline CLI tests, no network
945
+ cargo test --test smoke -- --ignored # real downloads: local HTTP server, real yt-dlp, real FFmpeg
946
+ cargo clippy --all-targets -- -D warnings
947
+ node scripts/npm-packages.mjs # sync npm package versions after a version bump
948
+ npm pack && node scripts/check-package.js
875
949
  ```
876
950
 
877
- The smoke test generates a two-second synthetic video with FFmpeg, serves it on loopback,
878
- and runs real yt-dlp downloads. It checks default output, the quality cap, duplicate names,
879
- audio extraction, conversion, dry-run, format listing, JSON output, metadata embedding,
880
- resume, batch behaviour, playlist selection and nonzero failures, and verifies that a
881
- finished download whose destination was unavailable is retried from the local cache
882
- without contacting the source again. It also confirms that real runs leave `veo history`
883
- entries, that finished runs clean up their record, and that `veo runs`/`veo stop` report
884
- nothing left behind. It needs network access once for yt-dlp acquisition; it downloads no
885
- third-party video. Prepare media tools with `veo doctor fix` before `npm test` on a fresh checkout; the tests themselves use local fixtures and require no network. CI explicitly prepares and verifies the native binary pair before testing.
886
-
887
- The published tarball only includes `bin/`, `src/`, package metadata, README and LICENSE.
888
- The lockfile is kept for reproducible development. There is no build step. npm makes the
889
- shebang-bearing bin executable on installation (on Unix, `chmod +x bin/veo.js` also enables
890
- direct checkout execution).
891
-
892
- Continuous integration runs the unit tests on Windows, macOS and Linux for Node 22 and 24,
893
- runs the end-to-end smoke test on Node 22, and verifies the packed tarball.
894
-
895
- Modules separate argument parsing (`src/cli.js`), configuration (`src/config.js`,
896
- `src/config-errors.js`, `src/config-template.js`), backend setup (`src/backend.js`),
897
- backend updates (`src/backend-update.js`), download orchestration (`src/downloader.js`,
898
- `src/download-cache.js`), retry jobs (`src/jobs.js`), playlists (`src/playlist.js`),
899
- statistics, download history, the run registry and cleanup (`src/stats.js`,
900
- `src/history.js`, `src/runs.js`, `src/flush.js`), diagnostics (`src/doctor.js`),
901
- progress (`src/progress.js`), and helpers (`src/utils.js`, `src/paths.js`,
902
- `src/state.js`, `src/version.js`) so new options and providers can be added without
903
- replacing the CLI.
951
+ The offline tests (`tests/cli.rs`) run the real binary against `tests/fake-backend`, a
952
+ small stand-in for yt-dlp, ffmpeg and ffprobe, in isolated cache and config directories.
953
+ They cover downloads, duplicate names, skip-existing, playlists and entry selection,
954
+ audio, subtitles, naming templates, dry runs and listings, incognito mode, retries by run
955
+ ID, transient-failure back-off, profiles and release notes.
956
+
957
+ The smoke test prepares the pinned tools with `veo doctor fix`, generates a two-second
958
+ synthetic video with FFmpeg, serves it on loopback and runs real yt-dlp downloads. It checks
959
+ default output, the quality cap, duplicate names, audio extraction, conversion, remuxing,
960
+ dry-run, format listing, JSON output, audio inspection, batch failures, profiles with URL
961
+ lists, retry by run ID from another directory, playlist selection, and that a finished
962
+ download whose destination was unavailable is transferred later without contacting the
963
+ source again. It downloads no third-party video.
964
+
965
+ Continuous integration runs formatting, Clippy, the unit and offline tests, and the smoke
966
+ test on Windows, macOS and Linux, and verifies the npm package. Pushing a tag `vX.Y.Z`
967
+ (matching `Cargo.toml`) builds the binaries for Windows x64/ARM64, macOS x64/ARM64,
968
+ static Linux x64/ARM64 (musl) and Android ARM64 and uploads the eight npm tarballs
969
+ as an Actions artifact. The `rust-port` branch also triggers this build.
970
+
971
+ GitHub builds all seven native targets and bundles them into the single veodl npm
972
+ package. No platform packages or npm credentials are needed on GitHub. Download
973
+ its npm-2.0.0 artifact and publish locally with npm run release. Users only need
974
+ npm install -g veodl; the launcher automatically selects the bundled binary.
975
+
976
+ Modules mirror the commands and stay small (larger ones are directories of focused
977
+ submodules): argument parsing and dispatch (`src/cli/`), configuration (`src/config*.rs`,
978
+ `src/config_editor/`), backend setup and updates (`src/backend/`, `src/tool_setup.rs`,
979
+ `src/backend_update.rs`), downloads (`src/downloader/`, `src/download_cache.rs`,
980
+ `src/jobs/`, `src/playlist.rs`), records (`src/runs/`, `src/history.rs`, `src/stats.rs`,
981
+ `src/run_archive.rs`, `src/flush.rs`), diagnostics (`src/doctor.rs`,
982
+ `src/inspect_media.rs`), source discovery over the Chrome DevTools Protocol
983
+ (`src/source_discovery/`), terminal output (`src/output.rs`, `src/progress/`,
984
+ `src/terminal.rs`) and helpers.
904
985
 
905
986
  ## License
906
987
 
package/bin/veo.js CHANGED
@@ -1,4 +1,49 @@
1
1
  #!/usr/bin/env node
2
- import { main } from '../src/cli.js';
2
+ // Starts the native veo binary that npm installed from the matching platform
3
+ // package (veodl-<platform>-<arch>). Exit codes and signals pass through.
4
+ import { spawn } from 'node:child_process';
5
+ import { existsSync } from 'node:fs';
6
+ import { fileURLToPath } from 'node:url';
7
+ import path from 'node:path';
3
8
 
4
- process.exitCode = await main();
9
+ const root = fileURLToPath(new URL('../', import.meta.url));
10
+ const target = `${process.platform}-${process.arch}`;
11
+ const executable = process.platform === 'win32' ? 'veo.exe' : 'veo';
12
+
13
+ function binaryPath() {
14
+ if (process.env.VEO_BINARY) return process.env.VEO_BINARY;
15
+ // Windows on ARM can run the x64 build through emulation.
16
+ const candidates = [target, ...(target === 'win32-arm64' ? ['win32-x64'] : [])];
17
+ for (const candidate of candidates) {
18
+ const file = path.join(root, 'native', candidate, executable);
19
+ if (existsSync(file)) return file;
20
+ }
21
+ return null;
22
+ }
23
+
24
+ const binary = binaryPath();
25
+ if (!binary) {
26
+ process.stderr.write(`veo: no prebuilt binary for ${target} is installed.\n`
27
+ + 'Reinstall with npm install -g veodl\n'
28
+ + 'Or build from source: cargo install --git https://github.com/Mailo037/veodl\n');
29
+ process.exit(1);
30
+ }
31
+
32
+ const child = spawn(binary, process.argv.slice(2), { stdio: 'inherit', windowsHide: false });
33
+ // The terminal already delivers Ctrl+C to veo itself; keep this launcher alive
34
+ // until veo has cleaned up, and forward termination requests sent only to it.
35
+ for (const signal of ['SIGINT', 'SIGTERM', 'SIGHUP']) {
36
+ process.on(signal, () => { if (signal !== 'SIGINT') child.kill(signal); });
37
+ }
38
+ child.on('error', error => {
39
+ process.stderr.write(`veo: could not start ${binary}: ${error.message}\n`);
40
+ process.exit(1);
41
+ });
42
+ child.on('close', (code, signal) => {
43
+ if (signal) {
44
+ process.removeAllListeners(signal);
45
+ process.kill(process.pid, signal);
46
+ return;
47
+ }
48
+ process.exit(code ?? 1);
49
+ });
@@ -116,7 +116,7 @@ The run record is stored in veo's per-user cache on the device that ran the down
116
116
  - Example profile: `"experimental": { "concurrentFragments": 32, "experimentalFragments": true }`. Run with `veo <URL> --profile experimental`; use `--no-experimental-fragments` to revoke a stored opt-in.
117
117
 
118
118
  - Run `veo doctor --offline` to check the local setup without network repair. `veo doctor fix` may install missing tools.
119
- - Desktop media downloads use fixed release URLs and shipped SHA-256 hashes; both FFmpeg and FFprobe are verified before execution and on cache reuse. A rejected legacy cache requires `veo doctor fix`. Trusted PATH tools and `VEO_FFMPEG_PATH` remain explicit alternatives. The npm package has no runtime dependencies or install scripts.
119
+ - Desktop media downloads use fixed release URLs and shipped SHA-256 hashes; both FFmpeg and FFprobe are verified before execution and on cache reuse. A rejected legacy cache requires `veo doctor fix`. Trusted PATH tools and `VEO_FFMPEG_PATH` remain explicit alternatives. The npm package runs no install scripts; it includes the native veo binaries and selects your platform automatically.
120
120
  - Use `--resume` for interrupted downloads and `--skip-existing` when repeated saves should be avoided.
121
121
  - `veo flush` removes temporary downloads and retry jobs; do not run it as routine maintenance in an agent workflow.
122
122
  - Do not call bare `veo` in an interactive terminal from automation: it opens a wizard. Use explicit URLs and flags.
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file