Live-stream recording, recent-additions feed, per-platform impersonate profiles
Three roadmap items together since they touch overlapping code: Live-stream recording - New `live: bool` argument on Downloader::start. When true, attaches `--live-from-start --wait-for-video 30`, suppresses `--break-on-existing` (every recording is a unique file), and prepends a UTC timestamp suffix to the output filename so re-recordings of the same broadcaster don't collide. - The job label gains a "🔴 LIVE" marker so a long-running record is obviously different from a VOD pull. - Both UIs gain a "🔴 Live stream" checkbox in the download panel, hidden when Music mode is selected. Works for Twitch *and* YouTube Live since yt-dlp recognizes both from the URL. - Web `POST /api/download` accepts a `live: bool` body field; all other callers (scheduled re-check, right-click "Check for new videos") pass false. Recent-additions feed - `library::Video` gains `mtime_unix: Option<u64>` — populated from the metadata we already read for `file_size`, so no extra fs hit. - New `SidebarView::Recent` (desktop) + `showRecent` (web) sort the whole library by mtime descending and cap at 100 entries. - Sidebar entry "🕒 Recent additions" appears only when the library has any dated content, so a fresh install doesn't show an empty view. Per-platform impersonation - New `Platform::impersonate_target()`: - Twitch → None (skip impersonation; their OAuth/Helix dislikes mismatched TLS fingerprints). - TikTok → "Chrome-Android-131" (mobile profile matches their first-party app surface). - Everything else → "Chrome-146:Macos-26". - `Downloader::apply_impersonation` now takes the platform and routes through the override; `repair()` (always YouTube-implicit) and `start_music()` (uses classify_url on the URL) wire through too. - `/api/preview` does the same classification before dispatching to yt-dlp. - 3 new tests confirm Twitch → None, TikTok → mobile, YouTube → desktop. 44 unit tests pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c0be4bb533
commit
b24ef4be67
5 changed files with 245 additions and 42 deletions
|
|
@ -72,6 +72,10 @@ pub struct Video {
|
|||
pub has_chapters: bool,
|
||||
/// Size of the video file on disk; `None` if the video file is missing.
|
||||
pub file_size: Option<u64>,
|
||||
/// Filesystem mtime of the video file as a UNIX timestamp (seconds).
|
||||
/// Used by the activity feed to surface recent additions. `None` if the
|
||||
/// video file is missing or the system clock returned an error.
|
||||
pub mtime_unix: Option<u64>,
|
||||
/// Upload date as `YYYYMMDD` (yt-dlp's native format from info.json).
|
||||
/// `None` if the info.json sidecar is missing or lacks the field.
|
||||
pub upload_date: Option<String>,
|
||||
|
|
@ -404,9 +408,14 @@ fn enrich(raws: Vec<RawVideo>) -> Vec<Video> {
|
|||
(dur, chap, date)
|
||||
})
|
||||
.unwrap_or((None, false, None));
|
||||
let file_size = raw.video_path.as_ref()
|
||||
.and_then(|p| std::fs::metadata(p).ok())
|
||||
.map(|m| m.len());
|
||||
let metadata = raw.video_path.as_ref()
|
||||
.and_then(|p| std::fs::metadata(p).ok());
|
||||
let file_size = metadata.as_ref().map(|m| m.len());
|
||||
let mtime_unix = metadata
|
||||
.as_ref()
|
||||
.and_then(|m| m.modified().ok())
|
||||
.and_then(|t| t.duration_since(std::time::UNIX_EPOCH).ok())
|
||||
.map(|d| d.as_secs());
|
||||
Video {
|
||||
id: raw.id,
|
||||
title: raw.title,
|
||||
|
|
@ -420,6 +429,7 @@ fn enrich(raws: Vec<RawVideo>) -> Vec<Video> {
|
|||
duration_secs,
|
||||
has_chapters,
|
||||
file_size,
|
||||
mtime_unix,
|
||||
upload_date,
|
||||
}
|
||||
}).collect();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue