Fix Windows compatibility: pipe streamlink→ffmpeg manually
On Windows, asyncio subprocess stdin can't accept another process's StreamReader directly. Use a background task to forward data instead. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
26
capture.py
26
capture.py
@@ -1,8 +1,22 @@
|
||||
import asyncio
|
||||
import struct
|
||||
from collections.abc import AsyncIterator
|
||||
|
||||
|
||||
async def _pipe_stream(source: asyncio.StreamReader, dest: asyncio.StreamWriter):
|
||||
"""Forward data from streamlink stdout to ffmpeg stdin."""
|
||||
try:
|
||||
while True:
|
||||
chunk = await source.read(65536)
|
||||
if not chunk:
|
||||
break
|
||||
dest.write(chunk)
|
||||
await dest.drain()
|
||||
except (BrokenPipeError, ConnectionResetError):
|
||||
pass
|
||||
finally:
|
||||
dest.close()
|
||||
|
||||
|
||||
async def capture_frames(
|
||||
channel: str, quality: str, interval: int
|
||||
) -> AsyncIterator[bytes]:
|
||||
@@ -35,13 +49,15 @@ async def capture_frames(
|
||||
|
||||
ffmpeg_proc = await asyncio.create_subprocess_exec(
|
||||
*ffmpeg_cmd,
|
||||
stdin=streamlink_proc.stdout,
|
||||
stdin=asyncio.subprocess.PIPE,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.DEVNULL,
|
||||
)
|
||||
|
||||
# Release streamlink's stdout so ffmpeg owns the pipe
|
||||
streamlink_proc.stdout = None
|
||||
# Forward streamlink → ffmpeg in background
|
||||
pipe_task = asyncio.create_task(
|
||||
_pipe_stream(streamlink_proc.stdout, ffmpeg_proc.stdin)
|
||||
)
|
||||
|
||||
try:
|
||||
buf = b""
|
||||
@@ -59,13 +75,13 @@ async def capture_frames(
|
||||
break
|
||||
eoi = buf.find(b"\xff\xd9", soi + 2)
|
||||
if eoi == -1:
|
||||
# Keep from SOI onward, discard junk before
|
||||
buf = buf[soi:]
|
||||
break
|
||||
frame = buf[soi : eoi + 2]
|
||||
buf = buf[eoi + 2 :]
|
||||
yield frame
|
||||
finally:
|
||||
pipe_task.cancel()
|
||||
for proc in (ffmpeg_proc, streamlink_proc):
|
||||
try:
|
||||
proc.terminate()
|
||||
|
||||
Reference in New Issue
Block a user