fix(ffmpeg): give the CF-bypass stream the same retry/resume as aiohttp (#169) - #172
Merged
Conversation
…tp (#169) `_stream_url_to_ffmpeg` has two transports. The aiohttp path retried up to 5 times and resumed from `bytes_downloaded` with a `Range` header; the curl_cffi path (Cloudflare-protected sources, e.g. MyInstants) did a single request with no retry, so a transient network blip killed playback outright on exactly the clips that are hardest to fetch. The worker thread now mirrors the aiohttp path: - up to 5 attempts, `time.sleep(0.5)` backoff between them; - `bytes_downloaded` is tracked across attempts and a retry sends `Range: bytes=<n>-`, so a drop resumes mid-clip instead of restarting from zero and repeating audio; - if a ranged retry is answered with a plain `200` (server ignored `Range`), the already-fed prefix is skipped from the new stream; - the response is now closed on every path. The queue hand-off helper (`enqueue_chunk`) is factored out of the inline `while` loop and cancels the pending `queue.put` future on a 0.5s timeout rather than leaving it to maybe fire later and double-feed a chunk. Verified the retry/resume/skip state machine against clean, mid-stream-drop (206 resume), ignored-Range (200 + skip) and connection-failure scenarios; all reconstruct the byte stream exactly. Not verified end to end: this needs a live voice server and a real Cloudflare-protected source, and the 200+skip branch assumes the restarted body is byte-identical. Bumps VERSION to 1.8.24. Closes #169 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
4 tasks
Dolly132
added a commit
to Dolly132/torchlight
that referenced
this pull request
Sep 6, 2026
Dolly132
approved these changes
Sep 6, 2026
Dolly132
left a comment
Collaborator
There was a problem hiding this comment.
Tested and works fine as expected. no errors
LGTM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Split out of #150.
_stream_url_to_ffmpeghas two transports and they gave different reliability guarantees by accident of structure:needs_cf_bypass)Range: bytes=N-sleep(0.5)So a transient blip killed playback outright on a Cloudflare-protected clip (MyInstants) while the same blip silently recovered on a normal URL.
Changes
The curl_cffi worker thread now mirrors the aiohttp path:
time.sleep(0.5)backoff;bytes_downloadedtracked across attempts; a retry sendsRange: bytes=<n>-so a drop resumes mid-clip instead of restarting from zero and repeating audio;200(server ignoredRange), the already-fed prefix is skipped from the restarted body;curl_cffiresponse is nowclose()d on every path.The queue hand-off is factored into
enqueue_chunk(), which now cancels the pendingqueue.putfuture on its 0.5s timeout instead of leaving it to maybe fire later and double-feed a chunk (the busy-poll flagged in the issue).What is and isn't verified
206resume), ignored-Range(200+ skip) and connection-failure scenarios — all reconstruct the byte stream exactly.ruff/mypyclean.200+skip branch assumes the restarted body is byte-identical to the original.The two transports are still deliberately separate (curl_cffi exists for TLS impersonation aiohttp can't do).
Merge order
Batch with #164, #169, #55; sequential
VERSIONpatch bumps (this one ->1.8.24). Needs a one-lineVERSIONrebase if it doesn't merge second.Closes #169
🤖 Generated with Claude Code