fix: a failed subtitle no longer destroys the download
Two faults behind the 429 in the report. The subtitle languages were a wildcard: 'en.*' also matches every machine-translated variant YouTube offers — en-en-US and dozens more — so each download fired a burst of subtitle requests and earned an HTTP 429. Languages are now named exactly, as '<lang>,<lang>-orig'. Turning subtitles off now really does request none; it previously still asked for English. Worse, yt-dlp exits non-zero if anything at all failed, and a caption it could not fetch was enough to mark a fully downloaded video as failed and leave the file orphaned. yt-dlp now runs with --ignore-errors, and success is judged by whether the media file actually landed rather than by the exit code. 429 also gets its own message pointing at the sign-in setting, which raises the limit.
This commit is contained in:
@@ -121,6 +121,11 @@ fn explain_yt_dlp_error(stderr: &str, signed_in: bool) -> String {
|
||||
.into()
|
||||
};
|
||||
}
|
||||
if stderr.contains("429") || stderr.contains("Too Many Requests") {
|
||||
return "YouTube is rate-limiting this machine. Wait a few minutes, or sign in \
|
||||
under Settings → Sign in to YouTube, which raises the limit."
|
||||
.into();
|
||||
}
|
||||
if stderr.contains("Operation not permitted") && stderr.contains("Safari") {
|
||||
return "macOS blocked access to Safari's cookies. Give FlightTube Full Disk Access in System Settings → Privacy & Security, or pick a different browser."
|
||||
.into();
|
||||
@@ -1038,15 +1043,15 @@ pub async fn download_video(
|
||||
let stderr_lines = stderr_task.await.unwrap_or_default();
|
||||
drop(permit);
|
||||
|
||||
if status.success() {
|
||||
// yt-dlp normally reports the path via `--print after_move:`; if that
|
||||
// line went missing, find the file it wrote by its embedded video id.
|
||||
let path = match final_path {
|
||||
Some(p) => p,
|
||||
None => find_by_video_id(&library, &video_id)
|
||||
.await
|
||||
.ok_or("Download finished but the file could not be located.")?,
|
||||
};
|
||||
// yt-dlp exits non-zero if *anything* failed, including a subtitle it could
|
||||
// not fetch. If the video itself landed, the download succeeded — throwing
|
||||
// away a finished file over a missing caption would be absurd.
|
||||
let landed = match final_path {
|
||||
Some(p) if tokio::fs::metadata(&p).await.is_ok() => Some(p),
|
||||
_ => find_by_video_id(&library, &video_id).await,
|
||||
};
|
||||
|
||||
if let Some(path) = landed {
|
||||
// YouTube's captions arrive pinned to the left edge and full of
|
||||
// karaoke timing tags; clean them before they reach the player.
|
||||
tidy_subtitles(&library, &video_id).await;
|
||||
|
||||
Reference in New Issue
Block a user