Skip to content

refactor(ffmpeg): share the ffmpeg stdin write and cleanup between fetch paths - #170

Merged
Rushaway merged 2 commits into
masterfrom
refactor/150-unify-ffmpeg-fetch-paths
Sep 6, 2026
Merged

refactor(ffmpeg): share the ffmpeg stdin write and cleanup between fetch paths#170
Rushaway merged 2 commits into
masterfrom
refactor/150-unify-ffmpeg-fetch-paths

Conversation

@Rushaway

@Rushaway Rushaway commented Sep 5, 2026

Copy link
Copy Markdown
Member

Summary

  • The curl_cffi and aiohttp streaming paths each inlined their own chunk write to ffmpeg stdin, and carried a byte-identical stdin close()/wait_closed() cleanup block (three duplicated blocks in total).
  • Extracted _write_to_ffmpeg() and _close_ffmpeg_stdin() and used them from both paths.
  • Small hardening: the aiohttp path now also skips writes while stdin is closing, a guard the curl_cffi path already had.

What I deliberately did not do, and why

The issue asked to "unify into one fetch abstraction with a pluggable transport wrapped by a single shared retry policy." I don't think that's the right change to ship blind, and here's the reasoning:

The two transports aren't gratuitous duplication. curl_cffi is there for impersonate="chrome120" — TLS fingerprint impersonation, which is precisely what gets past Cloudflare and which aiohttp fundamentally cannot do. aiohttp gives async-native streaming plus retry/Range resume and SOCKS support. They're different capabilities that happen to both end in "write bytes to ffmpeg" — and that ending is exactly the part I extracted.

The retry inconsistency is real, but fixing it properly is its own job. Naive retry on the curl_cffi path would restart the stream from byte 0 mid-playback (audible repetition); doing it right needs Range resume tracking across a thread boundary. And none of it is verifiable here — no live voice server, no real Cloudflare-protected source. This is the audio hot path; an unverified rewrite of it fails in production rather than in review. Tracked in #169 with the specifics, for someone who can test it end to end.

Happy to go further if you'd rather, but I didn't want to hand you a large, untested rewrite of streaming under a "refactor" label.

Closes #150

Test plan

Exercised both extracted helpers with stubs:

  • Writes forwarded to stdin in order.
  • Write skipped when stdin is_closing().
  • No crash when ffmpeg_process is None (both helpers).
  • _close_ffmpeg_stdin() closes stdin; no crash with no process.
  • All modules compile.

Note: #167 and #168 also touch FFmpegAudioPlayer, so whichever lands later needs a rebase.

🤖 Generated with Claude Code

…tch paths

The curl_cffi and aiohttp streaming paths each inlined their own chunk
write to ffmpeg stdin and carried a byte-identical stdin close/wait_closed
cleanup block. Extracted _write_to_ffmpeg() and _close_ffmpeg_stdin() and
used them from both, removing the three duplicated blocks.

The aiohttp path now also skips writes while stdin is closing, a guard the
curl_cffi path already had.

The two transports themselves are deliberately left separate: curl_cffi
exists for TLS impersonation to get past Cloudflare, which aiohttp cannot
do, so they are different capabilities rather than duplicated logic.
Retry parity between them is tracked in #169, since doing it correctly
needs Range-resume in the curl_cffi path and cannot be verified without a
live voice server and a real Cloudflare-protected source.

Bumps VERSION to 1.8.22.

Closes #150

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Dolly132 <109222243+Dolly132@users.noreply.github.com>
@Rushaway
Rushaway requested a review from Dolly132 September 5, 2026 13:26

@Rushaway Rushaway left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Self-review: this is the PR where I deliberately did less than the issue asked. The full transport abstraction would be a big rewrite of the audio hot path that I cannot test here (no live voice server, no real Cloudflare source), and the retry parity needs Range-resume across a thread boundary to avoid restarting playback from byte 0. I extracted the part that is genuinely duplicated and verifiable, and split the rest to #169 with the reasoning written down. Push back if you would rather I attempt the full unification.

@Dolly132 Dolly132 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't say no to reusable code, so LGTM

@Rushaway
Rushaway merged commit 24b5980 into master Sep 6, 2026
2 checks passed
@Rushaway
Rushaway deleted the refactor/150-unify-ffmpeg-fetch-paths branch September 6, 2026 10:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FFmpegAudioPlayer has two duplicate network-fetch implementations with inconsistent retry behavior

2 participants