Update ROADMAP: Phase 1 (Tartube parity) complete
Reconcile with what shipped since 2026-06-01: format conversion (1.7), filter presets (1.3+), hang watchdog + poison-recover locks (2.5), desktop UI scale. - State table: format conversion + filter UI → Tied; stability row expanded (crash log + disk-full + watchdog + lock recovery); added desktop UI scale row. Score 14 ahead / 1 behind / 13 tied — the lone "behind" is edge-case maturity, not a feature. - Phase 1 marked COMPLETE; the two last parity items recorded. - Phase 2: 2.5 done; only 2.1 (integration tests) + 2.2 (docs) remain. - Phase 3: unblocked 3.1 (packaging shipped) and reframed it around the real blocker (Linux-only tray/file-dialog); expanded 3.7 dedup with the perceptual-hash design. - Refreshed intro + footer to "at parity, now surpassing." Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
ffa864c470
commit
39850059cb
1 changed files with 61 additions and 45 deletions
106
ROADMAP.md
106
ROADMAP.md
|
|
@ -5,17 +5,17 @@
|
||||||
**Surpass [Tartube](https://github.com/axcore/tartube) in every dimension.**
|
**Surpass [Tartube](https://github.com/axcore/tartube) in every dimension.**
|
||||||
|
|
||||||
A structured analysis of Tartube's codebase, data model, operations, and
|
A structured analysis of Tartube's codebase, data model, operations, and
|
||||||
configuration surface lives at [`docs/tartube-spec.md`](docs/tartube-spec.md).
|
configuration surface lives at [`docs/tartube-spec.md`](docs/tartube-spec.md);
|
||||||
It enumerates the exact features we need to match — every Phase 1 item
|
it's what the Phase 1 parity work traced back to.
|
||||||
below traces back to a specific Tartube subsystem.
|
|
||||||
|
|
||||||
Tartube is the mature open-source yt-dlp GUI and the obvious benchmark for a
|
Tartube is the mature open-source yt-dlp GUI and the obvious benchmark for a
|
||||||
project in this space. yt-offline has architectural advantages Tartube can't
|
project in this space. yt-offline has architectural advantages Tartube can't
|
||||||
catch up on quickly (Rust + axum + a real web UI + bundled toolchain + a
|
catch up on quickly (Rust + axum + a real web UI + bundled toolchain + a
|
||||||
modern security model) but trails on feature breadth and years-of-edge-cases
|
modern security model). **As of 2026-06 we're at feature parity** — every
|
||||||
maturity. The plan below closes those gaps first, then pushes past.
|
Tartube subsystem is matched or led; the remaining gap is years-of-edge-
|
||||||
|
cases maturity. The plan below is now mostly "surpass" work.
|
||||||
|
|
||||||
## Current state vs Tartube (2026-06-01)
|
## Current state vs Tartube (2026-06-07)
|
||||||
|
|
||||||
| Area | Us | Tartube | Verdict |
|
| Area | Us | Tartube | Verdict |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
|
|
@ -37,47 +37,45 @@ maturity. The plan below closes those gaps first, then pushes past.
|
||||||
| Per-channel custom download options | ✅ JSON-blob overrides | ✅ deep | Tied |
|
| Per-channel custom download options | ✅ JSON-blob overrides | ✅ deep | Tied |
|
||||||
| Subtitle controls (auto / embed / convert) | ✅ global + per-channel | ✅ | Tied |
|
| Subtitle controls (auto / embed / convert) | ✅ global + per-channel | ✅ | Tied |
|
||||||
| Folder/group hierarchy | ✅ N-level nesting | ✅ N-level | Tied |
|
| Folder/group hierarchy | ✅ N-level nesting | ✅ N-level | Tied |
|
||||||
| Filter UI (date / size / watched) | ✅ chip-style | ✅ rich + presets | Tartube leads (presets only) |
|
| Filter UI (date / size / watched + presets) | ✅ chip-style + named presets | ✅ rich + presets | Tied |
|
||||||
|
| Format conversion / re-encode | ✅ remux / H.264 / audio post-pass | ✅ ffmpeg pipeline | Tied |
|
||||||
| Comments capture | ✅ `--write-comments` + viewer | ✅ raw JSON | We lead |
|
| Comments capture | ✅ `--write-comments` + viewer | ✅ raw JSON | We lead |
|
||||||
| System tray | ✅ ksni (Linux SNI) | ✅ GTK | Tied |
|
| System tray | ✅ ksni (Linux SNI) | ✅ GTK | Tied |
|
||||||
| Library backup + restore | ✅ DB snapshot + idempotent import | ✅ | Tied |
|
| Library backup + restore | ✅ DB snapshot + idempotent import | ✅ | Tied |
|
||||||
| Per-channel notes / annotations | ✅ searchable | ✅ | Tied |
|
| Per-channel notes / annotations | ✅ searchable | ✅ | Tied |
|
||||||
| Error classification + suggested fixes | ✅ 9-class + hints | ✅ rescue recipes | Tied |
|
| Error classification + suggested fixes | ✅ 9-class + hints | ✅ rescue recipes | Tied |
|
||||||
| Crash log + disk-full preflight | ✅ | partial | We lead |
|
| Stability hardening | ✅ crash log + disk-full preflight + hang watchdog + poison-recover locks | partial | We lead |
|
||||||
| Format conversion / re-encode | ❌ remux only | ✅ ffmpeg pipeline | **Tartube leads** |
|
| Desktop UI scale | ✅ global egui zoom, persisted | ✅ GTK native | Tied |
|
||||||
| Maturity / edge cases | ~months | ~years | **Tartube leads** |
|
| Maturity / edge cases | ~months | ~years | **Tartube leads** |
|
||||||
|
|
||||||
Score: 16 ahead, 2 behind, 11 tied. The big remaining gap is **format
|
Score: 14 ahead, 1 behind, 13 tied. **Phase 1 (Tartube parity) is
|
||||||
conversion (1.7)**; everything else is polish or stretch.
|
complete** — the only thing Tartube still leads on is years-of-edge-cases
|
||||||
|
maturity, which is time, not a feature. Everything below is "surpass"
|
||||||
|
territory plus test/doc investment.
|
||||||
|
|
||||||
## Phase 1 — Remaining Tartube parity items
|
## Phase 1 — COMPLETE
|
||||||
|
|
||||||
### 1.7 Format conversion pipeline — the one real parity gap left
|
All Tartube parity items shipped. For the record, the last to land:
|
||||||
|
|
||||||
Post-download re-encode option: H.264/AAC mp4 at a configurable CRF, or
|
- **1.7 Format conversion** — post-download ffmpeg pass with three modes
|
||||||
audio extraction at a target bitrate. Useful for shrinking large 4K files.
|
(remux→mp4, re-encode→H.264/AAC at a CRF, audio extraction), global
|
||||||
|
`[convert]` config + per-channel override, keep-original toggle,
|
||||||
|
surfaced as a distinct transcode job.
|
||||||
|
- **1.3+ Filter presets** — name a chip-filter set and re-apply it from
|
||||||
|
the filter row; persisted in localStorage.
|
||||||
|
|
||||||
- New `post_process` config field per quality preset.
|
See **Recently shipped** for the full list.
|
||||||
- ffmpeg job runs after the download completes, replaces the source file
|
|
||||||
(or keeps both with an `.original.mkv` suffix).
|
|
||||||
- Visible in the job log as a separate "transcoding" phase.
|
|
||||||
|
|
||||||
### 1.3+ Filter presets (extension of completed 1.3)
|
|
||||||
|
|
||||||
The chip filters ship, but Tartube also lets you *name* a filter set and
|
|
||||||
restore it later. Small UI layer on top of what's already implemented.
|
|
||||||
|
|
||||||
- "Save current filters as…" button next to the clear-filters link.
|
|
||||||
- Presets stored in localStorage (web) / SQLite (desktop).
|
|
||||||
- Dropdown chip to apply a saved preset.
|
|
||||||
|
|
||||||
## Phase 2 — Polish where Tartube is mature
|
## Phase 2 — Polish where Tartube is mature
|
||||||
|
|
||||||
Things we win on architecturally but lose on real-world ruggedness.
|
Things we win on architecturally but lose on real-world ruggedness.
|
||||||
|
|
||||||
|
The two genuinely-open items are **2.1 integration tests** and **2.2 docs
|
||||||
|
site** — both investment rather than features. 2.3 / 2.4 / 2.5 are done.
|
||||||
|
|
||||||
### 2.1 Integration test coverage
|
### 2.1 Integration test coverage
|
||||||
|
|
||||||
91 unit tests are good for parsers/helpers/resolvers, but don't cover
|
98 unit tests are good for parsers/helpers/resolvers, but don't cover
|
||||||
end-to-end correctness. We need real-yt-dlp integration tests against a
|
end-to-end correctness. We need real-yt-dlp integration tests against a
|
||||||
recorded fixture corpus.
|
recorded fixture corpus.
|
||||||
|
|
||||||
|
|
@ -108,14 +106,13 @@ surface new patterns.
|
||||||
`POST /api/restore/db` + file pickers in both UIs do an idempotent merge
|
`POST /api/restore/db` + file pickers in both UIs do an idempotent merge
|
||||||
(watched / positions / flags / folders / notes), schema-validated.
|
(watched / positions / flags / folders / notes), schema-validated.
|
||||||
|
|
||||||
### 2.5 Stability hardening — mostly DONE
|
### 2.5 Stability hardening — DONE
|
||||||
|
|
||||||
Done: crash.log panic hook, disk-full preflight (synthetic DiskFull job),
|
crash.log panic hook · disk-full preflight (synthetic DiskFull job) ·
|
||||||
auto-retry + adaptive throttle on transient failures. Remaining:
|
auto-retry + adaptive throttle on transient failures · hang watchdog
|
||||||
|
(SIGKILL a job silent for 5 min, classified retryable so it re-queues) ·
|
||||||
- Replace remaining `.lock().unwrap()` with poisoning-aware accessors.
|
`util::LockExt::lock_recover()` recovers poisoned `WebState` mutexes
|
||||||
- Hang watchdog: if a yt-dlp job stalls past `--socket-timeout * retries`,
|
instead of cascading one handler's panic into a dead server.
|
||||||
kill and re-queue.
|
|
||||||
|
|
||||||
## Phase 3 — Surpass
|
## Phase 3 — Surpass
|
||||||
|
|
||||||
|
|
@ -123,7 +120,11 @@ Once we're at parity, we push past Tartube on its own ground.
|
||||||
|
|
||||||
### 3.1 Cross-compile macOS + Windows binaries
|
### 3.1 Cross-compile macOS + Windows binaries
|
||||||
|
|
||||||
The current "later" roadmap item, blocked behind 1.8.
|
The Linux packaging (1.8) is done; this is the natural next reach. Blocked
|
||||||
|
on abstracting the Linux-only bits behind a per-OS backend — the `ksni`
|
||||||
|
tray and the `rfd` xdg-portal file dialog have no Windows/macOS path yet.
|
||||||
|
Once the tray is a trait with per-OS impls, the rest of the stack
|
||||||
|
(eframe/wgpu, axum, rusqlite-bundled) already cross-compiles.
|
||||||
|
|
||||||
### 3.2 Android client
|
### 3.2 Android client
|
||||||
|
|
||||||
|
|
@ -155,9 +156,14 @@ The comments capture (1.4) already ships a viewer. Surpass Tartube
|
||||||
|
|
||||||
### 3.7 Library-wide deduplication
|
### 3.7 Library-wide deduplication
|
||||||
|
|
||||||
Right now `maintenance` finds duplicates by yt-dlp video ID. Surpass by
|
Right now `maintenance` finds duplicates only by yt-dlp video ID — it
|
||||||
fingerprinting media bytes (`ffmpeg`-derived perceptual hashes) so the
|
catches "you downloaded this exact video twice," but not the same content
|
||||||
same video re-uploaded under a different ID gets flagged.
|
re-uploaded under a *different* ID (a reupload, a cross-platform mirror, a
|
||||||
|
re-encode). Surpass by perceptual-hashing sampled frames (ffmpeg → dHash)
|
||||||
|
and grouping videos whose fingerprints match within a Hamming threshold,
|
||||||
|
even across IDs/resolutions/encodings. A new `video_fingerprint` cache
|
||||||
|
table (keyed by path+mtime like `info_cache`) makes it a one-time cost per
|
||||||
|
video; bucket by duration first to keep the comparison sub-quadratic.
|
||||||
|
|
||||||
### 3.8 Plugin / scripting hook
|
### 3.8 Plugin / scripting hook
|
||||||
|
|
||||||
|
|
@ -179,6 +185,15 @@ Probably never, or much later.
|
||||||
|
|
||||||
Roughly reverse-chronological. Items that closed out a roadmap line.
|
Roughly reverse-chronological. Items that closed out a roadmap line.
|
||||||
|
|
||||||
|
- **Hang watchdog + poison-recover locks** (2.5) — SIGKILL a yt-dlp/ffmpeg
|
||||||
|
job silent for 5 min (classified retryable so it re-queues); recover
|
||||||
|
poisoned `WebState` mutexes instead of cascading a panic into a dead
|
||||||
|
server.
|
||||||
|
- **Filter presets** (1.3+) — save/apply/delete named chip-filter sets.
|
||||||
|
- **Desktop UI scale** — global egui zoom (whole UI, not just cards),
|
||||||
|
Settings slider + Ctrl +/-/0, persisted.
|
||||||
|
- **Format conversion** (1.7) — post-download ffmpeg remux / H.264 /
|
||||||
|
audio pass, global + per-channel, keep-original toggle.
|
||||||
- **Anti-bot stack** — POT token provider (bgutil-pot, version-matched
|
- **Anti-bot stack** — POT token provider (bgutil-pot, version-matched
|
||||||
plugin), nightly yt-dlp for working curl_cffi impersonation, dropped
|
plugin), nightly yt-dlp for working curl_cffi impersonation, dropped
|
||||||
the captcha-prone forced `player_client=web`, auto-retry + adaptive
|
the captcha-prone forced `player_client=web`, auto-retry + adaptive
|
||||||
|
|
@ -222,11 +237,12 @@ Roughly reverse-chronological. Items that closed out a roadmap line.
|
||||||
|
|
||||||
## How to read this
|
## How to read this
|
||||||
|
|
||||||
- **Phase 1** is the remaining parity work — four bounded items.
|
- **Phase 1** (Tartube parity) is **complete** — kept above for the record.
|
||||||
- **Phase 2** is concurrent polish — pick up between Phase 1 items.
|
- **Phase 2** is down to test coverage (2.1) and a docs site (2.2).
|
||||||
- **Phase 3** is the year-1 ambition once we're at parity.
|
- **Phase 3** is the "surpass" work now that we're at parity.
|
||||||
- **Phase 4** items might be valuable, but commit to nothing.
|
- **Phase 4** items might be valuable, but commit to nothing.
|
||||||
|
|
||||||
Items inside a phase are loosely ordered by user-visible impact, not strict
|
Items inside a phase are loosely ordered by user-visible impact, not strict
|
||||||
prerequisite. **1.8 (per-distro packaging)** is the biggest multiplier
|
prerequisite. With parity reached, the highest-leverage next moves are
|
||||||
for new users; **1.5 (notes)** is the biggest workflow gap.
|
**3.1 (Windows/macOS binaries)** for reach and **3.7 (perceptual-hash
|
||||||
|
dedup)** / **3.6 (comment-viewer)** for features Tartube can't match.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue