mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-10-02 21:06:52 +03:00
Fix 500 when an event thumbnail file is empty (#24110)
* fix 500 when an event thumbnail file is empty * fix test
This commit is contained in:
@@ -1060,7 +1060,7 @@ async def event_thumbnail(
|
|||||||
except DoesNotExist:
|
except DoesNotExist:
|
||||||
thumbnail_bytes = None
|
thumbnail_bytes = None
|
||||||
|
|
||||||
if thumbnail_bytes is None:
|
if not thumbnail_bytes:
|
||||||
# see if the object is currently being tracked
|
# see if the object is currently being tracked
|
||||||
try:
|
try:
|
||||||
camera_states = request.app.detected_frames_processor.get_camera_states()
|
camera_states = request.app.detected_frames_processor.get_camera_states()
|
||||||
@@ -1076,7 +1076,7 @@ async def event_thumbnail(
|
|||||||
status_code=404,
|
status_code=404,
|
||||||
)
|
)
|
||||||
|
|
||||||
if thumbnail_bytes is None:
|
if not thumbnail_bytes:
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
content={"success": False, "message": "Event not found"},
|
content={"success": False, "message": "Event not found"},
|
||||||
status_code=404,
|
status_code=404,
|
||||||
@@ -1085,6 +1085,13 @@ async def event_thumbnail(
|
|||||||
img_as_np = np.frombuffer(thumbnail_bytes, dtype=np.uint8)
|
img_as_np = np.frombuffer(thumbnail_bytes, dtype=np.uint8)
|
||||||
img = cv2.imdecode(img_as_np, flags=1)
|
img = cv2.imdecode(img_as_np, flags=1)
|
||||||
|
|
||||||
|
if img is None:
|
||||||
|
# thumbnail on disk is truncated or corrupt
|
||||||
|
return JSONResponse(
|
||||||
|
content={"success": False, "message": "Event not found"},
|
||||||
|
status_code=404,
|
||||||
|
)
|
||||||
|
|
||||||
# android notifications prefer a 2:1 ratio
|
# android notifications prefer a 2:1 ratio
|
||||||
if format == "android":
|
if format == "android":
|
||||||
img = cv2.copyMakeBorder(
|
img = cv2.copyMakeBorder(
|
||||||
|
|||||||
@@ -70,3 +70,19 @@ class TestFileUtils(TestCase):
|
|||||||
assert rendered_image is not None
|
assert rendered_image is not None
|
||||||
assert rendered_image.shape[0] == 40
|
assert rendered_image.shape[0] == 40
|
||||||
assert rendered_image.max() > 0
|
assert rendered_image.max() > 0
|
||||||
|
|
||||||
|
def test_get_event_thumbnail_bytes_ignores_empty_file(self):
|
||||||
|
"""Verify empty thumbnail files are treated as missing."""
|
||||||
|
event = SimpleNamespace(id="empty-thumb", camera="front_door", thumbnail=None)
|
||||||
|
|
||||||
|
with (
|
||||||
|
tempfile.TemporaryDirectory() as thumb_dir,
|
||||||
|
patch.object(file_util, "THUMB_DIR", thumb_dir),
|
||||||
|
):
|
||||||
|
camera_dir = os.path.join(thumb_dir, event.camera)
|
||||||
|
os.makedirs(camera_dir)
|
||||||
|
|
||||||
|
with open(os.path.join(camera_dir, f"{event.id}.webp"), "wb"):
|
||||||
|
pass
|
||||||
|
|
||||||
|
assert file_util.get_event_thumbnail_bytes(event) is None
|
||||||
|
|||||||
@@ -20,14 +20,15 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
def get_event_thumbnail_bytes(event: Event) -> bytes | None:
|
def get_event_thumbnail_bytes(event: Event) -> bytes | None:
|
||||||
|
# callers treat empty bytes as a valid image, so normalize them to None
|
||||||
if event.thumbnail:
|
if event.thumbnail:
|
||||||
return base64.b64decode(event.thumbnail)
|
return base64.b64decode(event.thumbnail) or None
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
with open(
|
with open(
|
||||||
os.path.join(THUMB_DIR, event.camera, f"{event.id}.webp"), "rb"
|
os.path.join(THUMB_DIR, event.camera, f"{event.id}.webp"), "rb"
|
||||||
) as f:
|
) as f:
|
||||||
return f.read()
|
return f.read() or None
|
||||||
except Exception:
|
except Exception:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user