veodl 1.12.1 → 2.0.1

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 (61) hide show
  1. package/AGENTS.md +12 -12
  2. package/CHANGELOG.md +404 -373
  3. package/LICENSE +21 -21
  4. package/README.md +1040 -910
  5. package/bin/veo.js +47 -2
  6. package/docs/AGENT_GUIDE.md +135 -122
  7. package/native/android-arm64/veo +0 -0
  8. package/native/darwin-arm64/veo +0 -0
  9. package/native/darwin-x64/veo +0 -0
  10. package/native/linux-arm64/veo +0 -0
  11. package/native/linux-x64/veo +0 -0
  12. package/native/win32-arm64/veo.exe +0 -0
  13. package/native/win32-x64/veo.exe +0 -0
  14. package/package.json +53 -57
  15. package/src/alias.js +0 -258
  16. package/src/backend-update.js +0 -191
  17. package/src/backend.js +0 -572
  18. package/src/changes.js +0 -278
  19. package/src/cli.js +0 -785
  20. package/src/compatibility.js +0 -39
  21. package/src/config-clipboard.js +0 -67
  22. package/src/config-diagnostics.js +0 -155
  23. package/src/config-editor.js +0 -404
  24. package/src/config-errors.js +0 -64
  25. package/src/config-reset.js +0 -39
  26. package/src/config-template.js +0 -227
  27. package/src/config.js +0 -307
  28. package/src/disk-space.js +0 -68
  29. package/src/doctor.js +0 -306
  30. package/src/download-cache.js +0 -31
  31. package/src/downloader.js +0 -704
  32. package/src/execution.js +0 -68
  33. package/src/experimental-fragments.js +0 -29
  34. package/src/flush.js +0 -66
  35. package/src/history.js +0 -173
  36. package/src/inline-region.js +0 -72
  37. package/src/inspect-media.js +0 -179
  38. package/src/interactive.js +0 -120
  39. package/src/jobs.js +0 -218
  40. package/src/legacy-config-comments.js +0 -106
  41. package/src/media-assets.js +0 -272
  42. package/src/naming.js +0 -54
  43. package/src/open-file.js +0 -15
  44. package/src/option-suggestions.js +0 -43
  45. package/src/output.js +0 -81
  46. package/src/path-links.js +0 -53
  47. package/src/paths.js +0 -26
  48. package/src/playlist.js +0 -31
  49. package/src/progress.js +0 -341
  50. package/src/run-archive.js +0 -148
  51. package/src/runs.js +0 -346
  52. package/src/source-discovery.js +0 -305
  53. package/src/state.js +0 -27
  54. package/src/stats.js +0 -63
  55. package/src/terminal-size.js +0 -8
  56. package/src/terminal-title.js +0 -19
  57. package/src/tool-setup.js +0 -289
  58. package/src/uninstall.js +0 -222
  59. package/src/updater.js +0 -229
  60. package/src/utils.js +0 -208
  61. package/src/version.js +0 -38
package/CHANGELOG.md CHANGED
@@ -1,373 +1,404 @@
1
- # Changelog
2
-
3
- All notable changes to veo. This project follows [Semantic Versioning](https://semver.org/).
4
-
5
- ## 1.12.1
6
-
7
- ### Fixed
8
-
9
- - Remove the optional FFmpeg npm dependency tree and its installation scripts.
10
- - Download desktop FFmpeg and FFprobe from fixed upstream releases and verify compressed and executable SHA-256 hashes before either program runs. Preserve upstream license and build information alongside the tools.
11
- - Verify managed media caches on reuse and reject legacy, corrupt or symlinked binaries. Preserve trusted system tools and explicit overrides.
12
- - Prevent rejected managed-cache binaries from being accepted again through PATH or a symlink alias; continue searching for external system tools.
13
- - Keep Smolish cookie environment variables out of media-tool probe processes.
14
- - Retry completed local transfers without contacting the original source, including selected-source retries, while retaining cache expiry and path validation.
15
- - Allow up to 30 seconds for Chromium's debugging connection on cold starts, while retaining the source scan's overall deadline and cancellation.
16
-
17
- ## 1.12.0
18
-
19
- ### Added
20
-
21
- - **Release Notes**: Added `veo changes [<version>]` (alias `veo changelog`) to list every released version, newest first, with the installed one marked. `veo changes <version>` (or `--version <version>`, and a partial version such as `1.10`) shows the notes of one release, `--latest` shows only the newest, and `--since <version>` with `--to <version>` or `--range <from>..<to>` shows everything between two versions. The notes are parsed from the `CHANGELOG.md` shipped with the installed version, so the command works offline, wraps long entries to the terminal width and prints no automatic update hint. `--json` returns the parsed sections, entries and nested entries unchanged for scripting.
22
-
23
- ## 1.11.0
24
-
25
- ### Added
26
-
27
- - **Incognito Downloads**: Added `--incognito` (and `"incognito": true` in configuration/profiles) to save media without creating run records, persistent retry jobs, run archives, download history, `.veo-history` records, or download statistics. Uses an isolated temporary staging directory and completely removes it upon completion, failure, or cancellation, and disables yt-dlp's filesystem cache.
28
- - **Neutral Filenames**: Added `--neutral-filename` (and `"neutralFilename": true`) to generate unidentifiable random filenames (e.g. `video-a1b2c3d4e5f6.mp4`), suppressing video titles, channel names, and custom folder templates in filesystem paths.
29
- - **Subtitle Inspection & Automatic Captions**:
30
- - Added `veo subs <url>` (alias `--list-subs` / `--list-subtitles`) to inspect available manual and automatically generated subtitle tracks, languages, and source formats without downloading.
31
- - Added `--auto-subs` (and `"autoSubs": true`) to download automatically generated captions/subtitles.
32
- - Added `--sub-format <format>` (and `"subFormat": string`) to express a preferred subtitle source format (e.g. `srt/vtt/best`).
33
- - **Post-Download Media Verification**: Added `--verify` (and `"verify": true`) to probe saved media files with FFprobe before recording success, verifying container integrity and stream presence. Retains saved files for inspection if verification fails.
34
-
35
- ## 1.10.1
36
-
37
- ### Added
38
-
39
- - Added `veo <url> --list-qualities` (alias `--list-qualitys`) to list available video resolutions ordered highest first without downloading media. Supports `--json` and discovered `--source <n>`.
40
- - Expanded `--concurrent-fragments` (or `-N`) to support values from 1 to 64. Experimental values between 17 and 64 require interactive `[y/N]` confirmation in terminals, or explicit opt-in via `--experimental-fragments` (or `"experimentalFragments": true` in configuration/profiles) for scripts and automated jobs. Values above 64 are rejected.
41
- - Added support for passing run IDs directly to `--retry-failed` (e.g. `veo --retry-failed <runId>`), automatically locating and resolving the corresponding retry job and rejecting active runs.
42
- - Added clickable OSC 8 directory links for saved file destinations, config paths, and editor headers in supported terminals (Windows Terminal, iTerm2, WezTerm, Kitty, VS Code, and VTE).
43
- - Added inline terminal region support (`createInlineRegion`) to smoothly render live progress and status in place without flickering, entering fullscreen, or wiping terminal scrollback.
44
-
45
- ### Fixed
46
-
47
- - Handled terminal window resize events during live progress display, dynamically refitting titles and status lines.
48
- - Improved terminal title and line wrapping to display up to three lines for long titles before truncating.
49
- - Improved interactive config editor footer layout for long status messages and ensured stdin is paused cleanly upon exit.
50
- - Preserved complete original values in JSON and redirected output while adapting prose output to the active terminal width.
51
-
52
- ## 1.10.0
53
-
54
- ### Added
55
-
56
- - **Persistent Profile Management**: Added `veo profile [NAME|list|reset]` commands to view the active configuration profile, inspect available profiles, switch defaults, or reset back to default without manual configuration edits.
57
- - **On-demand Config Guide**: Added `veo config guide` to display full configuration guidance, supported options, and templates in the terminal without opening the interactive editor.
58
- - **Interactive Config Editor enhancements**:
59
- - Full Undo (`Ctrl+Z`) and Redo (`Ctrl+Y`) history support when modifying settings.
60
- - Select All (`Ctrl+A`) shortcut to easily highlight and overwrite lines or entire sections.
61
- - Interactive F3 guide management prompt (`A` to add/refresh, `R` to strip documentation lines).
62
- - Mouse edge drag auto-scrolling when dragging selections past viewport bounds.
63
- - **Automatic Browser Source Discovery**: Enabled automatic source discovery fallback by default when direct extraction fails, automatically selecting and proceeding if a single verified media stream is found.
64
-
65
- ### Changed
66
-
67
- - Streamlined source discovery observation polling to immediately proceed once candidate streams are detected.
68
- - Enhanced progress output styling and ANSI handling across terminal status reporting.
69
-
70
- ## 1.9.1
71
-
72
- ### Added
73
-
74
- - Added typo and spelling suggestions for misspelled CLI options and subcommands (e.g. `--deepscan` suggests `--deep-scan`, `veo histroy` suggests `veo history`).
75
-
76
- ### Fixed
77
-
78
- - Improved browser-based player source discovery to continuously detect delayed play controls and overlays inside frames.
79
-
80
- ## 1.9.0
81
-
82
- ### Added
83
-
84
- - **Browser-based player source discovery**: Added `veo <page-url> --list-sources` to launch a temporary headless Chrome, Edge or Chromium session, simulate playback, and extract embedded media streams (HLS, DASH, direct MP4/WebM).
85
- - Added `--source <n>` to download or preview (`--dry-run`) a specific discovered source.
86
- - Added `--deep-scan` and `--timeout <duration>` (e.g. `30s`, `2m`) to configure source candidate search depth and deadlines.
87
- - Added interactive source discovery prompt in terminals when direct URL extraction finds no downloadable video.
88
- - Added `autoListSources`, `listSources`, `deepScan`, and `timeout` settings to config defaults and profiles.
89
- - **Config editor improvements**: Enhanced terminal layout with dynamic multi-line detail rows, compact status display, and automatic refresh of the marked template guide for new options.
90
-
91
- ### Fixed
92
-
93
- - Resolved active configuration path properly when running `veo uninstall`.
94
- - Ensured run cancellation requests are processed once per run to avoid race conditions.
95
-
96
- ## 1.8.3
97
-
98
- ### Added
99
-
100
- - Added `veo alias` commands (`list`, `add`, `remove`) to manage custom command names and shortcuts that forward to `veo`.
101
- - Added `veo uninstall` to remove individual aliases with `-p <name>`, or perform a full interactive/planned purge with `--yes`.
102
- - Added `veo up` as a short alias for `veo update`.
103
-
104
- ### Changed
105
-
106
- - Streamlined package binary commands to `veo` and `veodl`.
107
-
108
- ## 1.8.2
109
-
110
- ### Changed
111
-
112
- - Updated repository, issue tracker, and homepage URLs to `Mailo037/veodl`.
113
-
114
- ## 1.8.1
115
-
116
- ### Changed
117
-
118
- - Renamed package to `veodl` on npm.
119
- - Provided `veo`, `veod`, and `veodl` as parallel terminal commands (all execute the same CLI).
120
-
121
- ## 1.8.0
122
-
123
- ### Added
124
-
125
- - **`veo inspect <file>` and `veo inspect run <id>`**: Inspect local container and stream metadata with `--json`. Add `--check-audio` to decode audio tracks and verify signals above -60 dBFS. `veo inspect run <id>` locates saved run files by file identity, size, and sampled SHA-256 fingerprint, even after renames or moves (`--search <directory>`).
126
- - **`veo retry --last`**: Automatically retry the most recent failed or unfinished job without manually locating its job file.
127
- - **`veo history` improvements**: Added `--limit <1-1000>` to customize history entries and `--failed` to view only failed or cancelled attempts with their retry command and persistent `runId`.
128
- - **Config editor clipboard & mouse scrolling**: Added native system clipboard copy/paste (Ctrl+C / Ctrl+V) across Windows, macOS, Linux (Wayland/X11), and Termux, as well as mouse wheel and Ctrl+Up/Down scrolling.
129
- - **Termux desktop opener**: Supported `--open` in Android/Termux using `termux-open`.
130
- - **Agent guidelines**: Included AGENTS.md and docs/AGENT_GUIDE.md in the distributed package.
131
-
132
- ## 1.7.2
133
-
134
- ### Fixed
135
-
136
- - Stale download-history records referencing deleted files are automatically pruned on subsequent downloads, and empty `.veo-history` directories are removed.
137
- - `veo doctor` inspects `.veo-history` records, reports stale duplicate-detection records as warnings, and flags damaged history directories.
138
-
139
- ## 1.7.1
140
-
141
- ### Fixed
142
-
143
- - Progress adapts to narrow terminals, updates one line for parallel downloads, and marks estimated sizes instead of showing premature completion.
144
- - Download errors retain specific HTTP/network codes instead of replacing them with a generic network warning.
145
- - Files announced by a failed yt-dlp process are retained as unconfirmed, not treated as completed transfers; retry requires a successful backend exit.
146
-
147
- ## 1.7.0
148
-
149
- ### Added
150
-
151
- - Android/Termux automatically uses system yt-dlp and FFmpeg, with platform-specific doctor and backend-update instructions.
152
- - First downloads and `veo doctor fix` automatically install missing Termux tools (including JavaScript support) or acquire missing desktop media binaries in veo's cache; offline mode never installs packages.
153
-
154
- ### Changed
155
-
156
- - Static desktop media tools are optional dependencies so unsupported binaries do not prevent npm installation.
157
-
158
- ## 1.6.1
159
-
160
- ### Added
161
-
162
- - `veo config reset` restores the current template after confirmation and saves an exact backup of the previous configuration, including malformed files.
163
-
164
- ## 1.6.0
165
-
166
- ### Added
167
-
168
- - Parallel URL and batch downloads with serialized jobs, per-item statistics, and adaptive retries with reduced concurrency.
169
- - Parallel playlist downloads (two playlist entries concurrently by default, `--playlist-concurrency 1-4`), with per-entry progress, serialized job updates, and cancellation that waits for active workers.
170
- - Concurrent DASH/HLS fragment downloads (up to eight DASH/HLS fragments concurrently by default; `-N` overrides this).
171
- - Safe filename and folder templates, free-space estimates, and phase timings.
172
- - Offline config commands: `veo config check` and `veo config show`, and full option documentation in the config editor.
173
- - Prefer H.264/AAC for explicit MP4 downloads, report incompatible original codecs, and add opt-in `--compatible` / `kompatibel` profile with conditional H.264/AAC conversion.
174
- - `--recode` flag for explicitly converting video formats when remuxing is incompatible.
175
-
176
- ### Changed
177
-
178
- - Video `--format` now remuxes without quality loss; incompatible codecs fail instead of being converted silently.
179
- - Apply consistent terminal styling to all veo command reports and help, including stats; dim terminal status details and highlight titles, successful saves and failures; preserve plain JSON/piped output and honor `--no-color`, `NO_COLOR` and config color preferences.
180
-
181
- ### Fixed
182
-
183
- - Fix Node.js DEP0190 warnings during Windows self-updates by invoking cmd.exe explicitly with a fixed npm command.
184
-
185
- ## 1.5.0
186
-
187
- ### Added
188
-
189
- - **`veo runs` and `veo stop`**: every run registers itself with a **6-character id** while
190
- it works, so another terminal can watch and end it. `veo runs` lists active runs with PID,
191
- state, start time, progress and output directory, `veo runs <id>` shows one run in detail
192
- (URLs, media settings, job file and per-item state), `veo stop <id>` stops that run and
193
- `veo stop` stops every run. A stop request is polled by the run itself, so no signals or
194
- PIDs are needed; the stopped run exits like Ctrl+C and keeps its partial data and retry
195
- job. Records of crashed runs are marked `stale` and removed by `veo stop`. Run records
196
- never contain credentials or cookie settings, and an unknown or damaged record file is
197
- ignored instead of breaking later runs.
198
- - **`veo history`**: shows the last 5 download attempts, newest first, with title, status,
199
- media type, date, duration, URL and the saved files. Saved, skipped, failed and cancelled
200
- items are recorded, including the reported failure reason; playlist entries and retries
201
- count individually. `veo history --json` prints `{"count":N,"entries":[…]}` with the
202
- complete file list for scripting. Records live as one small file per attempt in the
203
- per-user veo cache's `history` directory and are kept by `veo flush`.
204
-
205
- ### Changed
206
-
207
- - The run registry moved out of `veo flush` into `src/runs.js`; `veo flush` and `veo stop`
208
- now stop the same registered runs, and `veo flush` keeps working with run records written
209
- by older versions.
210
-
211
- ## 1.4.0
212
-
213
- ### Added
214
-
215
- - **Local download cache**: downloads and media processing now finish in the per-user veo
216
- cache before the destination is written, so the output location is only touched once the
217
- media is ready. Saving uses a hard link where supported and an exclusive copy across
218
- drives or cloud mounts, with copied sizes verified. Existing files are still never
219
- overwritten. The local original is removed only after files and history are saved.
220
- - **Recoverable transfers**: if saving fails or is cancelled after processing completed, the
221
- finished local original and its sidecars are kept for **15 minutes** — with or without
222
- `--resume`. Repeat the same command, or use the printed `--retry-failed` command, to retry
223
- the transfer without contacting the source again. The same source, media settings and
224
- destination identify a cached transfer; a repeated failure starts a fresh retention
225
- period. Expired copies are removed on the next veo invocation, never by a background
226
- timer, and active transfers are never expired.
227
- - **`veo stats`**: persistent counters for saved videos and audio, failed attempts, skips,
228
- cancellations and total elapsed download-request time. `veo stats --json` prints the
229
- totals as JSON. Playlist entries count individually and retries are new attempts.
230
- Statistics hold counters and timestamps, not URLs or filenames.
231
- - **`veo flush [--stats]`**: stops active veo runs started with this version, then removes
232
- temporary local downloads — including the 15-minute retained copies and unfinished resume
233
- data — plus cached retry job files. Saved media, output history, config/profiles and
234
- backend binaries are kept, and `--stats` additionally resets the statistics.
235
- - **`veo doctor fix`**: restores missing or damaged managed tools and then checks again,
236
- staging bundled FFmpeg/FFprobe and downloading hash-verified yt-dlp when needed. With
237
- `--offline` only local binaries are used, and `-o PATH` creates and checks an output
238
- directory.
239
- - **Title placeholders** in `--rename` and the config/profile `rename` key: `-r "movie_*"`
240
- inserts the original title (`movie_My Film.mp4`), and every `*` is substituted. Placeholders
241
- make `--rename` usable with several URLs and playlists, where a plain name is still refused.
242
- - **`profiles.default`** is applied automatically when no profile is selected; other named
243
- profiles keep using the global defaults instead of inheriting `default`. `veo config edit`
244
- adds an empty `default` profile to existing configurations without changing settings, and
245
- the wizard preselects it.
246
- - Config syntax errors now name the line and column and explain the likely mistake, such as
247
- Markdown code fences, a trailing comma or an unescaped Windows path, without echoing
248
- private config values.
249
- - The packaged-tarball check now verifies that every relative import resolves inside the
250
- tarball and that the tarball, `package.json` and CHANGELOG versions agree, so an
251
- incompletely bumped or incompletely packed release fails before publishing.
252
-
253
- ### Changed
254
-
255
- - `veo doctor` no longer warns about a missing system FFmpeg when the selected FFmpeg and
256
- FFprobe work, and it reports retained local downloads and copied-size mismatches.
257
- - Resume state and partial data now live in the local per-user cache under `downloads`
258
- instead of the output directory, and the request hash also separates destinations,
259
- playlist entries and source URLs. Legacy `.veo-part-<video id>` folders in the output
260
- directory are left untouched and are not migrated automatically.
261
- - Unfinished downloads are discarded on failure or cancellation unless `--resume` is given;
262
- a completed download is the only thing retained for a transfer retry. Local disk space is
263
- therefore needed for the complete download and its processing files.
264
-
265
- ## 1.3.0
266
-
267
- ### Added
268
-
269
- - **Interactive wizard**: run `veo` without arguments in a terminal to be guided through a
270
- download — profile, link, video or audio, available resolution, output directory, and
271
- playlist entry selection. It enables resume and offers to skip already downloaded files.
272
- Redirected input never starts a prompt.
273
- - **Named profiles** in the config file (`"profiles": { "music": {...} }`) plus
274
- `veo config edit|path|profiles`. Global defaults are merged first, then the profile
275
- selected with `--profile`, then explicit flags.
276
- - **Negated boolean flags** such as `--no-open`, `--no-audio` or `--no-resume` switch off a
277
- stored default for one invocation; `--no-subs` also disables stored subtitle languages
278
- and subtitle embedding.
279
- - **URL list files** with `--batch-file <file>` (one URL per line, blank lines and `#`
280
- comments ignored), combinable with URLs on the command line.
281
- - **Durable batch jobs and `--retry-failed <file>`**: failed or cancelled runs print a
282
- ready-to-use retry command, and retries keep the resolved output directory and settings
283
- even from another working directory. Completed playlist jobs retry only failed indices.
284
- - **A final summary** per run, counting saved, skipped and failed items. With `--open`,
285
- successful files are opened even when another URL or playlist entry fails.
286
- - **Playlist entries one at a time**: a failed entry keeps previously saved files and does
287
- not stop the remaining entries. `--playlist-items 1,3-5` selects entries by original
288
- one-based index, and the selection count plus available size estimates are shown first.
289
- - **`--skip-existing`** reuses the recorded source and settings history and re-checks that
290
- the files are still on disk. A different quality or format, or a deleted output, is
291
- downloaded again.
292
- - **Resume by source and settings hash**: partial data lives in
293
- `.veo-part-<hash>`, guarded by a lock and a manifest that records backend-confirmed
294
- completion, so an unprocessed file is never mistaken for a finished video. Each playlist
295
- entry has its own state; completed entries are skipped on a later run and unfinished ones
296
- are preserved independently.
297
- - **Labelled phases** in the terminal title and progress output: current item, source title,
298
- video/audio/media stream, conversion or merge, and saving.
299
- - **Workflow regression tests** and real-backend smoke coverage for URL lists, profiles,
300
- retry, duplicate detection and playlist selection.
301
-
302
- ### Changed
303
-
304
- - Generated configuration comments, the example profiles (`music`, `archive`),
305
- documentation and sample filenames are English throughout. Previously generated German
306
- template comments are translated by the next `veo config edit`, preserving existing
307
- settings, paths and custom profile names.
308
- - `veo config edit` fills new or empty files with a commented template and gives existing
309
- files a one-time commented reference guide, without changing stored settings. Config
310
- files accept `//` line and `/* ... */` block comments.
311
- - Ambiguous "resume folders" are replaced by the source/settings hash layout; only
312
- backend-confirmed postprocessed media is reused.
313
- - Other positive numeric resolutions, such as `-q 540p`, are accepted instead of only the
314
- documented list.
315
-
316
- ## 1.2.0
317
-
318
- Everything below ships together: `1.1.0` was prepared but never published, so this
319
- release is the first to contain these changes.
320
-
321
- ### Changed
322
-
323
- - **`--quality` is now an upper bound.** `-q 720p` downloads the best resolution at or
324
- below 720p and never fetches 2160p instead. If a source offers nothing at or below the
325
- request, veo stops before downloading and names the resolutions that do exist. The
326
- historical "nearest available height" rule is still available as `--closest-quality`
327
- and may pick a resolution above the request. Sources without resolution metadata fall
328
- back to the best available stream, as before.
329
- - A finished download is now linked into place instead of copied. Staging lives inside
330
- the output directory, so a hard link is enough; filesystems without hard links still
331
- fall back to a copy. This removes a full extra read and write per download, roughly
332
- halves the peak disk usage, and makes saving cancellable.
333
- - Fewer duplicated downloads in `veo update`: an explicitly installed backend release
334
- is no longer pruned.
335
- - Metadata and media tools are prepared before any network work, so an unusable local
336
- setup fails before a backend download starts.
337
-
338
- ### Added
339
-
340
- - **Multiple URLs** in one invocation: `veo <url1> <url2> ...`. Downloads run
341
- sequentially, a failure does not stop the remaining URLs, and the exit status is `1`
342
- if any URL failed.
343
- - **`--playlist`** to download every entry of a playlist or channel URL. Each entry keeps
344
- its own title, and `--no-playlist` remains the default.
345
- - **Subtitles**: `--subs`, `--sub-langs <langs>`, `--embed-subs`.
346
- - **Metadata**: `--embed-metadata`, `--embed-thumbnail`, `--sponsorblock-remove <categories>`,
347
- `--section <range>`, and `-N/--concurrent-fragments <n>` for faster fragmented downloads.
348
- - **`--resume`** keeps partial data in `.veo-part-<video id>` and continues an interrupted
349
- download, including one that was cancelled with Ctrl+C.
350
- - **`--cookies <file>` and `--cookies-from-browser <browser[:profile]>`** for content you
351
- are authorized to access. Cookie files are validated before any network work and a
352
- world-readable file produces a warning.
353
- - **`--dry-run`** reports the title, quality and destination path without downloading.
354
- - **`--list-formats`** prints the backend's own format table.
355
- - **`--json`** prints one JSON object per URL for scripting.
356
- - **`veo doctor`** checks Node.js, the output directory, the backend cache, yt-dlp,
357
- FFmpeg/FFprobe, the config file, leftover partial downloads and network reachability.
358
- It downloads nothing and exits `1` when a check fails.
359
- - **`veo backend update [--check]`** installs a newer yt-dlp release without waiting for a
360
- new veo release, verified against that release's own `SHA2-256SUMS`. `veo backend reset`
361
- returns to the release pinned and hash-verified at build time.
362
- - **Config file** for defaults (output directory, quality, format, subtitle preferences,
363
- and so on). Explicit command-line flags always win.
364
- - **Windows on ARM** is no longer rejected: when the bundled static media tools are
365
- unavailable, veo uses a system FFmpeg installation found on `PATH`.
366
-
367
- ### Fixed
368
-
369
- - `--rename` is applied again; it had stopped affecting the saved filename.
370
-
371
- ## 1.0.2
372
-
373
- - Initial published release.
1
+ # Changelog
2
+
3
+ All notable changes to veo. This project follows [Semantic Versioning](https://semver.org/).
4
+
5
+ ## 2.0.1
6
+
7
+ ### Added
8
+
9
+ - Rust HTTP transfers for eligible direct media, with pooled connections, parallel byte ranges written into one file, strong-ETag resume validation and single-stream/backend fallbacks. `--http-connections` selects 1-16 connections; `--no-native-http` keeps the yt-dlp transfer path. Authenticated and transformed downloads continue through yt-dlp.
10
+ - `--staging-dir output` stages beside the destination, or an explicit path chooses another staging drive. Registered staging roots participate in expiration cleanup and `veo flush`; incognito staging stays private and unregistered.
11
+ - `--fast-cut` opts into faster, less precise keyframe-aligned section downloads. Precise cuts remain the default.
12
+
13
+ ### Changed
14
+
15
+ - Full extraction results are reused for downloading through a temporary private info file removed after the backend exits. Expired media information is refreshed automatically. Playlist entries use their direct page URL when available instead of repeatedly extracting the parent collection.
16
+ - Downloads and fragments share host-local connection budgets. Transient failures reduce capacity for that host; four successful operations restore one back-off step without retiring playlist workers.
17
+ - Compatibility checks and optional saved-media verification share their probe when saving preserves the file identity, size and modification time. Converted files and cross-filesystem copies are probed again.
18
+
19
+ - Release tags build and verify all seven native targets, then publish the single `veodl` npm package through GitHub Actions using OIDC trusted publishing. No npm token is stored in GitHub.
20
+
21
+ ## 2.0.0
22
+
23
+ ### Changed
24
+
25
+ - **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.
26
+ - 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.
27
+ - 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.
28
+ - First-use FFmpeg/FFprobe setup downloads both tools in parallel and publishes them by rename instead of copying them again.
29
+ - 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.
30
+ - Cancelling a download stops yt-dlp together with the FFmpeg processes it started.
31
+
32
+ ### Removed
33
+
34
+ - Unused compatibility code for configuration comments of the former German template.
35
+
36
+ ## 1.12.1
37
+
38
+ ### Fixed
39
+
40
+ - Remove the optional FFmpeg npm dependency tree and its installation scripts.
41
+ - Download desktop FFmpeg and FFprobe from fixed upstream releases and verify compressed and executable SHA-256 hashes before either program runs. Preserve upstream license and build information alongside the tools.
42
+ - Verify managed media caches on reuse and reject legacy, corrupt or symlinked binaries. Preserve trusted system tools and explicit overrides.
43
+ - Prevent rejected managed-cache binaries from being accepted again through PATH or a symlink alias; continue searching for external system tools.
44
+ - Keep Smolish cookie environment variables out of media-tool probe processes.
45
+ - Retry completed local transfers without contacting the original source, including selected-source retries, while retaining cache expiry and path validation.
46
+ - Allow up to 30 seconds for Chromium's debugging connection on cold starts, while retaining the source scan's overall deadline and cancellation.
47
+
48
+ ## 1.12.0
49
+
50
+ ### Added
51
+
52
+ - **Release Notes**: Added `veo changes [<version>]` (alias `veo changelog`) to list every released version, newest first, with the installed one marked. `veo changes <version>` (or `--version <version>`, and a partial version such as `1.10`) shows the notes of one release, `--latest` shows only the newest, and `--since <version>` with `--to <version>` or `--range <from>..<to>` shows everything between two versions. The notes are parsed from the `CHANGELOG.md` shipped with the installed version, so the command works offline, wraps long entries to the terminal width and prints no automatic update hint. `--json` returns the parsed sections, entries and nested entries unchanged for scripting.
53
+
54
+ ## 1.11.0
55
+
56
+ ### Added
57
+
58
+ - **Incognito Downloads**: Added `--incognito` (and `"incognito": true` in configuration/profiles) to save media without creating run records, persistent retry jobs, run archives, download history, `.veo-history` records, or download statistics. Uses an isolated temporary staging directory and completely removes it upon completion, failure, or cancellation, and disables yt-dlp's filesystem cache.
59
+ - **Neutral Filenames**: Added `--neutral-filename` (and `"neutralFilename": true`) to generate unidentifiable random filenames (e.g. `video-a1b2c3d4e5f6.mp4`), suppressing video titles, channel names, and custom folder templates in filesystem paths.
60
+ - **Subtitle Inspection & Automatic Captions**:
61
+ - Added `veo subs <url>` (alias `--list-subs` / `--list-subtitles`) to inspect available manual and automatically generated subtitle tracks, languages, and source formats without downloading.
62
+ - Added `--auto-subs` (and `"autoSubs": true`) to download automatically generated captions/subtitles.
63
+ - Added `--sub-format <format>` (and `"subFormat": string`) to express a preferred subtitle source format (e.g. `srt/vtt/best`).
64
+ - **Post-Download Media Verification**: Added `--verify` (and `"verify": true`) to probe saved media files with FFprobe before recording success, verifying container integrity and stream presence. Retains saved files for inspection if verification fails.
65
+
66
+ ## 1.10.1
67
+
68
+ ### Added
69
+
70
+ - Added `veo <url> --list-qualities` (alias `--list-qualitys`) to list available video resolutions ordered highest first without downloading media. Supports `--json` and discovered `--source <n>`.
71
+ - Expanded `--concurrent-fragments` (or `-N`) to support values from 1 to 64. Experimental values between 17 and 64 require interactive `[y/N]` confirmation in terminals, or explicit opt-in via `--experimental-fragments` (or `"experimentalFragments": true` in configuration/profiles) for scripts and automated jobs. Values above 64 are rejected.
72
+ - Added support for passing run IDs directly to `--retry-failed` (e.g. `veo --retry-failed <runId>`), automatically locating and resolving the corresponding retry job and rejecting active runs.
73
+ - Added clickable OSC 8 directory links for saved file destinations, config paths, and editor headers in supported terminals (Windows Terminal, iTerm2, WezTerm, Kitty, VS Code, and VTE).
74
+ - Added inline terminal region support (`createInlineRegion`) to smoothly render live progress and status in place without flickering, entering fullscreen, or wiping terminal scrollback.
75
+
76
+ ### Fixed
77
+
78
+ - Handled terminal window resize events during live progress display, dynamically refitting titles and status lines.
79
+ - Improved terminal title and line wrapping to display up to three lines for long titles before truncating.
80
+ - Improved interactive config editor footer layout for long status messages and ensured stdin is paused cleanly upon exit.
81
+ - Preserved complete original values in JSON and redirected output while adapting prose output to the active terminal width.
82
+
83
+ ## 1.10.0
84
+
85
+ ### Added
86
+
87
+ - **Persistent Profile Management**: Added `veo profile [NAME|list|reset]` commands to view the active configuration profile, inspect available profiles, switch defaults, or reset back to default without manual configuration edits.
88
+ - **On-demand Config Guide**: Added `veo config guide` to display full configuration guidance, supported options, and templates in the terminal without opening the interactive editor.
89
+ - **Interactive Config Editor enhancements**:
90
+ - Full Undo (`Ctrl+Z`) and Redo (`Ctrl+Y`) history support when modifying settings.
91
+ - Select All (`Ctrl+A`) shortcut to easily highlight and overwrite lines or entire sections.
92
+ - Interactive F3 guide management prompt (`A` to add/refresh, `R` to strip documentation lines).
93
+ - Mouse edge drag auto-scrolling when dragging selections past viewport bounds.
94
+ - **Automatic Browser Source Discovery**: Enabled automatic source discovery fallback by default when direct extraction fails, automatically selecting and proceeding if a single verified media stream is found.
95
+
96
+ ### Changed
97
+
98
+ - Streamlined source discovery observation polling to immediately proceed once candidate streams are detected.
99
+ - Enhanced progress output styling and ANSI handling across terminal status reporting.
100
+
101
+ ## 1.9.1
102
+
103
+ ### Added
104
+
105
+ - Added typo and spelling suggestions for misspelled CLI options and subcommands (e.g. `--deepscan` suggests `--deep-scan`, `veo histroy` suggests `veo history`).
106
+
107
+ ### Fixed
108
+
109
+ - Improved browser-based player source discovery to continuously detect delayed play controls and overlays inside frames.
110
+
111
+ ## 1.9.0
112
+
113
+ ### Added
114
+
115
+ - **Browser-based player source discovery**: Added `veo <page-url> --list-sources` to launch a temporary headless Chrome, Edge or Chromium session, simulate playback, and extract embedded media streams (HLS, DASH, direct MP4/WebM).
116
+ - Added `--source <n>` to download or preview (`--dry-run`) a specific discovered source.
117
+ - Added `--deep-scan` and `--timeout <duration>` (e.g. `30s`, `2m`) to configure source candidate search depth and deadlines.
118
+ - Added interactive source discovery prompt in terminals when direct URL extraction finds no downloadable video.
119
+ - Added `autoListSources`, `listSources`, `deepScan`, and `timeout` settings to config defaults and profiles.
120
+ - **Config editor improvements**: Enhanced terminal layout with dynamic multi-line detail rows, compact status display, and automatic refresh of the marked template guide for new options.
121
+
122
+ ### Fixed
123
+
124
+ - Resolved active configuration path properly when running `veo uninstall`.
125
+ - Ensured run cancellation requests are processed once per run to avoid race conditions.
126
+
127
+ ## 1.8.3
128
+
129
+ ### Added
130
+
131
+ - Added `veo alias` commands (`list`, `add`, `remove`) to manage custom command names and shortcuts that forward to `veo`.
132
+ - Added `veo uninstall` to remove individual aliases with `-p <name>`, or perform a full interactive/planned purge with `--yes`.
133
+ - Added `veo up` as a short alias for `veo update`.
134
+
135
+ ### Changed
136
+
137
+ - Streamlined package binary commands to `veo` and `veodl`.
138
+
139
+ ## 1.8.2
140
+
141
+ ### Changed
142
+
143
+ - Updated repository, issue tracker, and homepage URLs to `Mailo037/veodl`.
144
+
145
+ ## 1.8.1
146
+
147
+ ### Changed
148
+
149
+ - Renamed package to `veodl` on npm.
150
+ - Provided `veo`, `veod`, and `veodl` as parallel terminal commands (all execute the same CLI).
151
+
152
+ ## 1.8.0
153
+
154
+ ### Added
155
+
156
+ - **`veo inspect <file>` and `veo inspect run <id>`**: Inspect local container and stream metadata with `--json`. Add `--check-audio` to decode audio tracks and verify signals above -60 dBFS. `veo inspect run <id>` locates saved run files by file identity, size, and sampled SHA-256 fingerprint, even after renames or moves (`--search <directory>`).
157
+ - **`veo retry --last`**: Automatically retry the most recent failed or unfinished job without manually locating its job file.
158
+ - **`veo history` improvements**: Added `--limit <1-1000>` to customize history entries and `--failed` to view only failed or cancelled attempts with their retry command and persistent `runId`.
159
+ - **Config editor clipboard & mouse scrolling**: Added native system clipboard copy/paste (Ctrl+C / Ctrl+V) across Windows, macOS, Linux (Wayland/X11), and Termux, as well as mouse wheel and Ctrl+Up/Down scrolling.
160
+ - **Termux desktop opener**: Supported `--open` in Android/Termux using `termux-open`.
161
+ - **Agent guidelines**: Included AGENTS.md and docs/AGENT_GUIDE.md in the distributed package.
162
+
163
+ ## 1.7.2
164
+
165
+ ### Fixed
166
+
167
+ - Stale download-history records referencing deleted files are automatically pruned on subsequent downloads, and empty `.veo-history` directories are removed.
168
+ - `veo doctor` inspects `.veo-history` records, reports stale duplicate-detection records as warnings, and flags damaged history directories.
169
+
170
+ ## 1.7.1
171
+
172
+ ### Fixed
173
+
174
+ - Progress adapts to narrow terminals, updates one line for parallel downloads, and marks estimated sizes instead of showing premature completion.
175
+ - Download errors retain specific HTTP/network codes instead of replacing them with a generic network warning.
176
+ - Files announced by a failed yt-dlp process are retained as unconfirmed, not treated as completed transfers; retry requires a successful backend exit.
177
+
178
+ ## 1.7.0
179
+
180
+ ### Added
181
+
182
+ - Android/Termux automatically uses system yt-dlp and FFmpeg, with platform-specific doctor and backend-update instructions.
183
+ - First downloads and `veo doctor fix` automatically install missing Termux tools (including JavaScript support) or acquire missing desktop media binaries in veo's cache; offline mode never installs packages.
184
+
185
+ ### Changed
186
+
187
+ - Static desktop media tools are optional dependencies so unsupported binaries do not prevent npm installation.
188
+
189
+ ## 1.6.1
190
+
191
+ ### Added
192
+
193
+ - `veo config reset` restores the current template after confirmation and saves an exact backup of the previous configuration, including malformed files.
194
+
195
+ ## 1.6.0
196
+
197
+ ### Added
198
+
199
+ - Parallel URL and batch downloads with serialized jobs, per-item statistics, and adaptive retries with reduced concurrency.
200
+ - Parallel playlist downloads (two playlist entries concurrently by default, `--playlist-concurrency 1-4`), with per-entry progress, serialized job updates, and cancellation that waits for active workers.
201
+ - Concurrent DASH/HLS fragment downloads (up to eight DASH/HLS fragments concurrently by default; `-N` overrides this).
202
+ - Safe filename and folder templates, free-space estimates, and phase timings.
203
+ - Offline config commands: `veo config check` and `veo config show`, and full option documentation in the config editor.
204
+ - Prefer H.264/AAC for explicit MP4 downloads, report incompatible original codecs, and add opt-in `--compatible` / `kompatibel` profile with conditional H.264/AAC conversion.
205
+ - `--recode` flag for explicitly converting video formats when remuxing is incompatible.
206
+
207
+ ### Changed
208
+
209
+ - Video `--format` now remuxes without quality loss; incompatible codecs fail instead of being converted silently.
210
+ - Apply consistent terminal styling to all veo command reports and help, including stats; dim terminal status details and highlight titles, successful saves and failures; preserve plain JSON/piped output and honor `--no-color`, `NO_COLOR` and config color preferences.
211
+
212
+ ### Fixed
213
+
214
+ - Fix Node.js DEP0190 warnings during Windows self-updates by invoking cmd.exe explicitly with a fixed npm command.
215
+
216
+ ## 1.5.0
217
+
218
+ ### Added
219
+
220
+ - **`veo runs` and `veo stop`**: every run registers itself with a **6-character id** while
221
+ it works, so another terminal can watch and end it. `veo runs` lists active runs with PID,
222
+ state, start time, progress and output directory, `veo runs <id>` shows one run in detail
223
+ (URLs, media settings, job file and per-item state), `veo stop <id>` stops that run and
224
+ `veo stop` stops every run. A stop request is polled by the run itself, so no signals or
225
+ PIDs are needed; the stopped run exits like Ctrl+C and keeps its partial data and retry
226
+ job. Records of crashed runs are marked `stale` and removed by `veo stop`. Run records
227
+ never contain credentials or cookie settings, and an unknown or damaged record file is
228
+ ignored instead of breaking later runs.
229
+ - **`veo history`**: shows the last 5 download attempts, newest first, with title, status,
230
+ media type, date, duration, URL and the saved files. Saved, skipped, failed and cancelled
231
+ items are recorded, including the reported failure reason; playlist entries and retries
232
+ count individually. `veo history --json` prints `{"count":N,"entries":[…]}` with the
233
+ complete file list for scripting. Records live as one small file per attempt in the
234
+ per-user veo cache's `history` directory and are kept by `veo flush`.
235
+
236
+ ### Changed
237
+
238
+ - The run registry moved out of `veo flush` into `src/runs.js`; `veo flush` and `veo stop`
239
+ now stop the same registered runs, and `veo flush` keeps working with run records written
240
+ by older versions.
241
+
242
+ ## 1.4.0
243
+
244
+ ### Added
245
+
246
+ - **Local download cache**: downloads and media processing now finish in the per-user veo
247
+ cache before the destination is written, so the output location is only touched once the
248
+ media is ready. Saving uses a hard link where supported and an exclusive copy across
249
+ drives or cloud mounts, with copied sizes verified. Existing files are still never
250
+ overwritten. The local original is removed only after files and history are saved.
251
+ - **Recoverable transfers**: if saving fails or is cancelled after processing completed, the
252
+ finished local original and its sidecars are kept for **15 minutes** — with or without
253
+ `--resume`. Repeat the same command, or use the printed `--retry-failed` command, to retry
254
+ the transfer without contacting the source again. The same source, media settings and
255
+ destination identify a cached transfer; a repeated failure starts a fresh retention
256
+ period. Expired copies are removed on the next veo invocation, never by a background
257
+ timer, and active transfers are never expired.
258
+ - **`veo stats`**: persistent counters for saved videos and audio, failed attempts, skips,
259
+ cancellations and total elapsed download-request time. `veo stats --json` prints the
260
+ totals as JSON. Playlist entries count individually and retries are new attempts.
261
+ Statistics hold counters and timestamps, not URLs or filenames.
262
+ - **`veo flush [--stats]`**: stops active veo runs started with this version, then removes
263
+ temporary local downloads — including the 15-minute retained copies and unfinished resume
264
+ data — plus cached retry job files. Saved media, output history, config/profiles and
265
+ backend binaries are kept, and `--stats` additionally resets the statistics.
266
+ - **`veo doctor fix`**: restores missing or damaged managed tools and then checks again,
267
+ staging bundled FFmpeg/FFprobe and downloading hash-verified yt-dlp when needed. With
268
+ `--offline` only local binaries are used, and `-o PATH` creates and checks an output
269
+ directory.
270
+ - **Title placeholders** in `--rename` and the config/profile `rename` key: `-r "movie_*"`
271
+ inserts the original title (`movie_My Film.mp4`), and every `*` is substituted. Placeholders
272
+ make `--rename` usable with several URLs and playlists, where a plain name is still refused.
273
+ - **`profiles.default`** is applied automatically when no profile is selected; other named
274
+ profiles keep using the global defaults instead of inheriting `default`. `veo config edit`
275
+ adds an empty `default` profile to existing configurations without changing settings, and
276
+ the wizard preselects it.
277
+ - Config syntax errors now name the line and column and explain the likely mistake, such as
278
+ Markdown code fences, a trailing comma or an unescaped Windows path, without echoing
279
+ private config values.
280
+ - The packaged-tarball check now verifies that every relative import resolves inside the
281
+ tarball and that the tarball, `package.json` and CHANGELOG versions agree, so an
282
+ incompletely bumped or incompletely packed release fails before publishing.
283
+
284
+ ### Changed
285
+
286
+ - `veo doctor` no longer warns about a missing system FFmpeg when the selected FFmpeg and
287
+ FFprobe work, and it reports retained local downloads and copied-size mismatches.
288
+ - Resume state and partial data now live in the local per-user cache under `downloads`
289
+ instead of the output directory, and the request hash also separates destinations,
290
+ playlist entries and source URLs. Legacy `.veo-part-<video id>` folders in the output
291
+ directory are left untouched and are not migrated automatically.
292
+ - Unfinished downloads are discarded on failure or cancellation unless `--resume` is given;
293
+ a completed download is the only thing retained for a transfer retry. Local disk space is
294
+ therefore needed for the complete download and its processing files.
295
+
296
+ ## 1.3.0
297
+
298
+ ### Added
299
+
300
+ - **Interactive wizard**: run `veo` without arguments in a terminal to be guided through a
301
+ download — profile, link, video or audio, available resolution, output directory, and
302
+ playlist entry selection. It enables resume and offers to skip already downloaded files.
303
+ Redirected input never starts a prompt.
304
+ - **Named profiles** in the config file (`"profiles": { "music": {...} }`) plus
305
+ `veo config edit|path|profiles`. Global defaults are merged first, then the profile
306
+ selected with `--profile`, then explicit flags.
307
+ - **Negated boolean flags** such as `--no-open`, `--no-audio` or `--no-resume` switch off a
308
+ stored default for one invocation; `--no-subs` also disables stored subtitle languages
309
+ and subtitle embedding.
310
+ - **URL list files** with `--batch-file <file>` (one URL per line, blank lines and `#`
311
+ comments ignored), combinable with URLs on the command line.
312
+ - **Durable batch jobs and `--retry-failed <file>`**: failed or cancelled runs print a
313
+ ready-to-use retry command, and retries keep the resolved output directory and settings
314
+ even from another working directory. Completed playlist jobs retry only failed indices.
315
+ - **A final summary** per run, counting saved, skipped and failed items. With `--open`,
316
+ successful files are opened even when another URL or playlist entry fails.
317
+ - **Playlist entries one at a time**: a failed entry keeps previously saved files and does
318
+ not stop the remaining entries. `--playlist-items 1,3-5` selects entries by original
319
+ one-based index, and the selection count plus available size estimates are shown first.
320
+ - **`--skip-existing`** reuses the recorded source and settings history and re-checks that
321
+ the files are still on disk. A different quality or format, or a deleted output, is
322
+ downloaded again.
323
+ - **Resume by source and settings hash**: partial data lives in
324
+ `.veo-part-<hash>`, guarded by a lock and a manifest that records backend-confirmed
325
+ completion, so an unprocessed file is never mistaken for a finished video. Each playlist
326
+ entry has its own state; completed entries are skipped on a later run and unfinished ones
327
+ are preserved independently.
328
+ - **Labelled phases** in the terminal title and progress output: current item, source title,
329
+ video/audio/media stream, conversion or merge, and saving.
330
+ - **Workflow regression tests** and real-backend smoke coverage for URL lists, profiles,
331
+ retry, duplicate detection and playlist selection.
332
+
333
+ ### Changed
334
+
335
+ - Generated configuration comments, the example profiles (`music`, `archive`),
336
+ documentation and sample filenames are English throughout. Previously generated German
337
+ template comments are translated by the next `veo config edit`, preserving existing
338
+ settings, paths and custom profile names.
339
+ - `veo config edit` fills new or empty files with a commented template and gives existing
340
+ files a one-time commented reference guide, without changing stored settings. Config
341
+ files accept `//` line and `/* ... */` block comments.
342
+ - Ambiguous "resume folders" are replaced by the source/settings hash layout; only
343
+ backend-confirmed postprocessed media is reused.
344
+ - Other positive numeric resolutions, such as `-q 540p`, are accepted instead of only the
345
+ documented list.
346
+
347
+ ## 1.2.0
348
+
349
+ Everything below ships together: `1.1.0` was prepared but never published, so this
350
+ release is the first to contain these changes.
351
+
352
+ ### Changed
353
+
354
+ - **`--quality` is now an upper bound.** `-q 720p` downloads the best resolution at or
355
+ below 720p and never fetches 2160p instead. If a source offers nothing at or below the
356
+ request, veo stops before downloading and names the resolutions that do exist. The
357
+ historical "nearest available height" rule is still available as `--closest-quality`
358
+ and may pick a resolution above the request. Sources without resolution metadata fall
359
+ back to the best available stream, as before.
360
+ - A finished download is now linked into place instead of copied. Staging lives inside
361
+ the output directory, so a hard link is enough; filesystems without hard links still
362
+ fall back to a copy. This removes a full extra read and write per download, roughly
363
+ halves the peak disk usage, and makes saving cancellable.
364
+ - Fewer duplicated downloads in `veo update`: an explicitly installed backend release
365
+ is no longer pruned.
366
+ - Metadata and media tools are prepared before any network work, so an unusable local
367
+ setup fails before a backend download starts.
368
+
369
+ ### Added
370
+
371
+ - **Multiple URLs** in one invocation: `veo <url1> <url2> ...`. Downloads run
372
+ sequentially, a failure does not stop the remaining URLs, and the exit status is `1`
373
+ if any URL failed.
374
+ - **`--playlist`** to download every entry of a playlist or channel URL. Each entry keeps
375
+ its own title, and `--no-playlist` remains the default.
376
+ - **Subtitles**: `--subs`, `--sub-langs <langs>`, `--embed-subs`.
377
+ - **Metadata**: `--embed-metadata`, `--embed-thumbnail`, `--sponsorblock-remove <categories>`,
378
+ `--section <range>`, and `-N/--concurrent-fragments <n>` for faster fragmented downloads.
379
+ - **`--resume`** keeps partial data in `.veo-part-<video id>` and continues an interrupted
380
+ download, including one that was cancelled with Ctrl+C.
381
+ - **`--cookies <file>` and `--cookies-from-browser <browser[:profile]>`** for content you
382
+ are authorized to access. Cookie files are validated before any network work and a
383
+ world-readable file produces a warning.
384
+ - **`--dry-run`** reports the title, quality and destination path without downloading.
385
+ - **`--list-formats`** prints the backend's own format table.
386
+ - **`--json`** prints one JSON object per URL for scripting.
387
+ - **`veo doctor`** checks Node.js, the output directory, the backend cache, yt-dlp,
388
+ FFmpeg/FFprobe, the config file, leftover partial downloads and network reachability.
389
+ It downloads nothing and exits `1` when a check fails.
390
+ - **`veo backend update [--check]`** installs a newer yt-dlp release without waiting for a
391
+ new veo release, verified against that release's own `SHA2-256SUMS`. `veo backend reset`
392
+ returns to the release pinned and hash-verified at build time.
393
+ - **Config file** for defaults (output directory, quality, format, subtitle preferences,
394
+ and so on). Explicit command-line flags always win.
395
+ - **Windows on ARM** is no longer rejected: when the bundled static media tools are
396
+ unavailable, veo uses a system FFmpeg installation found on `PATH`.
397
+
398
+ ### Fixed
399
+
400
+ - `--rename` is applied again; it had stopped affecting the saved filename.
401
+
402
+ ## 1.0.2
403
+
404
+ - Initial published release.