Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
953ec628a0 | ||
|
|
e678c8c267 | ||
|
|
69d58f99e3 |
+18
-11
@@ -213,6 +213,13 @@ def _image_via_ffmpeg(path: Path, maxsize: int, quality: int) -> bytes:
|
|||||||
tmp_path = tmp_f.name
|
tmp_path = tmp_f.name
|
||||||
cmd = [
|
cmd = [
|
||||||
"ffmpeg",
|
"ffmpeg",
|
||||||
|
# Keep error messages, drop the banner/config/stream-mapping spam.
|
||||||
|
"-hide_banner",
|
||||||
|
"-loglevel",
|
||||||
|
"error",
|
||||||
|
"-nostats",
|
||||||
|
# No interactive keyboard prompts ("Press [q] to stop ...").
|
||||||
|
"-nostdin",
|
||||||
"-y",
|
"-y",
|
||||||
"-i",
|
"-i",
|
||||||
str(path),
|
str(path),
|
||||||
@@ -233,8 +240,9 @@ def _image_via_ffmpeg(path: Path, maxsize: int, quality: int) -> bytes:
|
|||||||
new_w = int(w * scale)
|
new_w = int(w * scale)
|
||||||
new_h = int(h * scale)
|
new_h = int(h * scale)
|
||||||
# insert -s <wxh> right after the input file
|
# insert -s <wxh> right after the input file
|
||||||
cmd.insert(4, "-s")
|
input_index = cmd.index(str(path)) + 1
|
||||||
cmd.insert(5, f"{new_w}x{new_h}")
|
cmd.insert(input_index, "-s")
|
||||||
|
cmd.insert(input_index + 1, f"{new_w}x{new_h}")
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
# stdin=DEVNULL is critical: ffmpeg must not inherit the worker's
|
# stdin=DEVNULL is critical: ffmpeg must not inherit the worker's
|
||||||
@@ -254,10 +262,10 @@ def _image_via_ffmpeg(path: Path, maxsize: int, quality: int) -> bytes:
|
|||||||
stderr = (e.stderr or b"").decode(errors="replace").strip()
|
stderr = (e.stderr or b"").decode(errors="replace").strip()
|
||||||
if stderr:
|
if stderr:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"ffmpeg failed (exit {e.returncode}): {shell_cmd}\n{stderr}"
|
f"ffmpeg failed (exit {e.returncode}):\n{shell_cmd}\n{stderr}"
|
||||||
) from e
|
) from e
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"ffmpeg failed (exit {e.returncode}): {shell_cmd}"
|
f"ffmpeg failed (exit {e.returncode}):\n{shell_cmd}"
|
||||||
) from e
|
) from e
|
||||||
with Path(tmp_path).open("rb") as f:
|
with Path(tmp_path).open("rb") as f:
|
||||||
return f.read()
|
return f.read()
|
||||||
@@ -285,9 +293,10 @@ def process_image_pyvips(path, *, maxsize, quality):
|
|||||||
height=height,
|
height=height,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Other image formats: pyvips first, ffmpeg fallback.
|
# Other image formats: pyvips only. ffmpeg is not a useful fallback
|
||||||
|
# here — when pyvips cannot decode a file, ffmpeg's image decoders
|
||||||
|
# cannot either, and their failure output is far noisier.
|
||||||
load_opts = {"access": "sequential"}
|
load_opts = {"access": "sequential"}
|
||||||
orig_w = orig_h = None
|
|
||||||
try:
|
try:
|
||||||
img = pyvips.Image.new_from_file(str(path), **load_opts)
|
img = pyvips.Image.new_from_file(str(path), **load_opts)
|
||||||
img = img.autorot()
|
img = img.autorot()
|
||||||
@@ -301,11 +310,9 @@ def process_image_pyvips(path, *, maxsize, quality):
|
|||||||
effort=AVIF_FAST_EFFORT,
|
effort=AVIF_FAST_EFFORT,
|
||||||
keep="none",
|
keep="none",
|
||||||
)
|
)
|
||||||
backend = "pyvips"
|
except pyvips.error.Error as e:
|
||||||
except pyvips.error.Error:
|
raise ValueError(f"cannot decode image: {e}") from e
|
||||||
orig_w, orig_h = None, None
|
backend = "pyvips"
|
||||||
ret = _image_via_ffmpeg(path, maxsize, quality)
|
|
||||||
backend = "ffmpeg"
|
|
||||||
t_end = perf_counter()
|
t_end = perf_counter()
|
||||||
|
|
||||||
return ret, PreviewResponse(
|
return ret, PreviewResponse(
|
||||||
|
|||||||
Reference in New Issue
Block a user