mirror of
https://github.com/wiltodelta/remove-ai-watermarks.git
synced 2026-08-10 08:00:32 +02:00
Prevent ffmpeg stderr backpressure
This commit is contained in:
+6
-24
@@ -1950,30 +1950,6 @@ class TestVideoVisibleScan:
|
||||
|
||||
|
||||
class TestVideoVisibleEncoding:
|
||||
@pytest.mark.parametrize("suffix", [".mp4", ".webm"])
|
||||
def test_encoder_bounds_codec_threads(
|
||||
self,
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
suffix: str,
|
||||
):
|
||||
from remove_ai_watermarks import video_encoding
|
||||
|
||||
monkeypatch.setattr(video_encoding.shutil, "which", lambda _name: "/usr/bin/ffmpeg")
|
||||
command = video_encoding.raw_video_command(
|
||||
tmp_path / "source.mp4",
|
||||
tmp_path / f"clean{suffix}",
|
||||
width=12,
|
||||
height=8,
|
||||
fps=24.0,
|
||||
strip_metadata=True,
|
||||
crf=14,
|
||||
profile=video_encoding.VideoEncodeProfile(),
|
||||
)
|
||||
|
||||
assert command[1:3] == ["-filter_threads", "1"]
|
||||
assert command[command.index("-threads:v") + 1] == "2"
|
||||
|
||||
@staticmethod
|
||||
def _patch_single_frame_encode(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
@@ -2008,6 +1984,12 @@ class TestVideoVisibleEncoding:
|
||||
def poll(self) -> int:
|
||||
return 1
|
||||
|
||||
def wait(self) -> int:
|
||||
return 1
|
||||
|
||||
def discard_stderr(self) -> None:
|
||||
pass
|
||||
|
||||
targets: list[Path] = []
|
||||
|
||||
def fake_command(_source: Path, target: Path, **_kwargs: object) -> list[str]:
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
import threading
|
||||
from types import SimpleNamespace
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
@@ -14,6 +16,55 @@ if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def test_encoder_redirects_large_stderr_while_frames_are_streaming(
|
||||
tmp_path: Path,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
diagnostic = "synthetic ffmpeg diagnostic"
|
||||
tail_diagnostic = "synthetic ffmpeg diagnostic tail"
|
||||
caplog.set_level("INFO", logger=video_encoding.__name__)
|
||||
command = [
|
||||
sys.executable,
|
||||
"-c",
|
||||
(
|
||||
"import sys; "
|
||||
f"sys.stderr.buffer.write({diagnostic.encode()!r} + b'x' * 262144 + {tail_diagnostic.encode()!r}); "
|
||||
"sys.stderr.buffer.flush(); "
|
||||
"sys.stdin.buffer.read(); "
|
||||
"raise SystemExit(7)"
|
||||
),
|
||||
]
|
||||
encoder = video_encoding.start_raw_video_encoder(command)
|
||||
write_finished = threading.Event()
|
||||
write_errors: list[Exception] = []
|
||||
|
||||
def write_frames() -> None:
|
||||
try:
|
||||
encoder.stdin.write(b"f" * 262144)
|
||||
encoder.stdin.flush()
|
||||
except Exception as exc: # pragma: no cover - mutation cleanup path
|
||||
write_errors.append(exc)
|
||||
finally:
|
||||
write_finished.set()
|
||||
|
||||
writer = threading.Thread(target=write_frames)
|
||||
writer.start()
|
||||
try:
|
||||
assert write_finished.wait(5), "stderr backpressure blocked the frame producer"
|
||||
assert write_errors == []
|
||||
with pytest.raises(RuntimeError, match=diagnostic):
|
||||
video_encoding.finish_raw_video_encoder(
|
||||
encoder,
|
||||
tmp_path / "unused.mp4",
|
||||
operation="synthetic encode",
|
||||
)
|
||||
assert "ffmpeg stderr truncated" in caplog.text
|
||||
assert tail_diagnostic in caplog.text
|
||||
finally:
|
||||
video_encoding.abort_raw_video_encoder(encoder)
|
||||
writer.join(timeout=5)
|
||||
|
||||
|
||||
def test_availability_requires_both_optional_packages(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.setattr(
|
||||
video_invisible,
|
||||
|
||||
Reference in New Issue
Block a user