feat: subtitles, delete-all, auto refresh, and menu cleanup
Subtitles: a language preference in Settings drives what is shown and what is downloaded. yt-dlp saves WebVTT sidecars next to each download, including YouTube's auto-generated track, and the player attaches them as <track> elements so they work offline. Sidecars are removed with their video, and by Delete all. WebVTT rather than muxed subtitle streams because WebKit reads a <track> reliably and largely ignores subtitle tracks inside an MP4. Downloads in progress now appear under the downloaded-only filter, so a download you just started does not vanish from the list you are watching it in. That view also gains a Delete all, behind a confirmation naming what goes. The feed refreshes on launch and whenever the player closes, so the Refresh button is only for staleness. Player: Delete moved to the footer and shortened, Open on YouTube is now an external-link icon. Removes the Edit and Help menus. Cut/Copy/Paste move to the app menu, without which their shortcuts would stop working in the search field. The webview context menu is suppressed outside text fields — its Reload and Back items act on a page the app does not present as one. Settings now warns that 4K AV1 plays back with artefacts: the files decode cleanly in ffmpeg, so it is the built-in decoder, not the download.
This commit is contained in:
@@ -79,7 +79,12 @@ pub fn parse_progress_line(line: &str) -> Option<Progress> {
|
||||
|
||||
/// Arguments for downloading one video. Kept separate from process spawning so
|
||||
/// the argument construction is assertable in tests.
|
||||
pub fn build_args(video_id: &str, out_template: &str, quality: &str) -> Vec<String> {
|
||||
pub fn build_args(
|
||||
video_id: &str,
|
||||
out_template: &str,
|
||||
quality: &str,
|
||||
sub_langs: &str,
|
||||
) -> Vec<String> {
|
||||
vec![
|
||||
"-f".into(),
|
||||
format_selector(quality),
|
||||
@@ -94,6 +99,18 @@ pub fn build_args(video_id: &str, out_template: &str, quality: &str) -> Vec<Stri
|
||||
"180".into(),
|
||||
"--progress-template".into(),
|
||||
PROGRESS_TEMPLATE.into(),
|
||||
// Subtitles come along for offline use, including YouTube's
|
||||
// auto-generated ones. They are written beside the video as WebVTT
|
||||
// rather than muxed in: WebKit reads a <track> reliably, whereas
|
||||
// subtitle streams inside an MP4 it largely ignores.
|
||||
"--write-subs".into(),
|
||||
"--write-auto-subs".into(),
|
||||
"--sub-format".into(),
|
||||
"vtt".into(),
|
||||
"--convert-subs".into(),
|
||||
"vtt".into(),
|
||||
"--sub-langs".into(),
|
||||
sub_langs.into(),
|
||||
"--print".into(),
|
||||
"after_move:FTPATH %(filepath)s".into(),
|
||||
"-o".into(),
|
||||
@@ -175,9 +192,20 @@ mod tests {
|
||||
assert_eq!(p.pct(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn subtitles_are_requested_including_auto_generated() {
|
||||
let args = build_args("abc", "/tmp/o.%(ext)s", "best", "en.*,nl.*");
|
||||
assert!(args.contains(&"--write-subs".to_string()));
|
||||
// The auto-generated track is the only one many videos have.
|
||||
assert!(args.contains(&"--write-auto-subs".to_string()));
|
||||
assert!(args.contains(&"en.*,nl.*".to_string()));
|
||||
// WebVTT, because that is what a <track> element can load.
|
||||
assert!(args.contains(&"vtt".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn best_quality_takes_the_highest_available() {
|
||||
let args = build_args("abc123", "/tmp/out.%(ext)s", "best");
|
||||
let args = build_args("abc123", "/tmp/out.%(ext)s", "best", "en.*");
|
||||
assert!(args.contains(&FORMAT_BEST.to_string()));
|
||||
assert!(args.contains(&"mp4".to_string()));
|
||||
assert!(args.contains(&"https://www.youtube.com/watch?v=abc123".to_string()));
|
||||
@@ -197,7 +225,7 @@ mod tests {
|
||||
let sel = format_selector("1080");
|
||||
assert!(sel.contains("height<=1080"));
|
||||
assert!(!sel.contains("height<=2160"));
|
||||
assert!(build_args("x", "o", "1080").contains(&sel));
|
||||
assert!(build_args("x", "o", "1080", "en.*").contains(&sel));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user