mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-11 13:45:25 +03:00
formatted
This commit is contained in:
parent
11d77964c3
commit
f846d754ad
@ -68,14 +68,17 @@ def imagestream(detected_frames_processor, camera_name, fps, height, draw_option
|
|||||||
while True:
|
while True:
|
||||||
# max out at specified FPS
|
# max out at specified FPS
|
||||||
time.sleep(1 / fps)
|
time.sleep(1 / fps)
|
||||||
frame = detected_frames_processor.get_current_frame(camera_name, draw_options)
|
frame = detected_frames_processor.get_current_frame(
|
||||||
|
camera_name, draw_options)
|
||||||
if frame is None:
|
if frame is None:
|
||||||
frame = np.zeros((height, int(height * 16 / 9), 3), np.uint8)
|
frame = np.zeros((height, int(height * 16 / 9), 3), np.uint8)
|
||||||
|
|
||||||
width = int(height * frame.shape[1] / frame.shape[0])
|
width = int(height * frame.shape[1] / frame.shape[0])
|
||||||
frame = cv2.resize(frame, dsize=(width, height), interpolation=cv2.INTER_LINEAR)
|
frame = cv2.resize(frame, dsize=(width, height),
|
||||||
|
interpolation=cv2.INTER_LINEAR)
|
||||||
|
|
||||||
ret, jpg = cv2.imencode(".jpg", frame, [int(cv2.IMWRITE_JPEG_QUALITY), 70])
|
ret, jpg = cv2.imencode(
|
||||||
|
".jpg", frame, [int(cv2.IMWRITE_JPEG_QUALITY), 70])
|
||||||
yield (
|
yield (
|
||||||
b"--frame\r\n"
|
b"--frame\r\n"
|
||||||
b"Content-Type: image/jpeg\r\n\r\n" + jpg.tobytes() + b"\r\n\r\n"
|
b"Content-Type: image/jpeg\r\n\r\n" + jpg.tobytes() + b"\r\n\r\n"
|
||||||
@ -111,16 +114,19 @@ def latest_frame(camera_name):
|
|||||||
camera_name, draw_options
|
camera_name, draw_options
|
||||||
)
|
)
|
||||||
retry_interval = float(
|
retry_interval = float(
|
||||||
current_app.frigate_config.cameras.get(camera_name).ffmpeg.retry_interval
|
current_app.frigate_config.cameras.get(
|
||||||
|
camera_name).ffmpeg.retry_interval
|
||||||
or 10
|
or 10
|
||||||
)
|
)
|
||||||
|
|
||||||
if frame is None or datetime.now().timestamp() > (
|
if frame is None or datetime.now().timestamp() > (
|
||||||
current_app.detected_frames_processor.get_current_frame_time(camera_name)
|
current_app.detected_frames_processor.get_current_frame_time(
|
||||||
|
camera_name)
|
||||||
+ retry_interval
|
+ retry_interval
|
||||||
):
|
):
|
||||||
if current_app.camera_error_image is None:
|
if current_app.camera_error_image is None:
|
||||||
error_image = glob.glob("/opt/frigate/frigate/images/camera-error.jpg")
|
error_image = glob.glob(
|
||||||
|
"/opt/frigate/frigate/images/camera-error.jpg")
|
||||||
|
|
||||||
if len(error_image) > 0:
|
if len(error_image) > 0:
|
||||||
current_app.camera_error_image = cv2.imread(
|
current_app.camera_error_image = cv2.imread(
|
||||||
@ -140,11 +146,13 @@ def latest_frame(camera_name):
|
|||||||
|
|
||||||
if height < 1 or width < 1:
|
if height < 1 or width < 1:
|
||||||
return (
|
return (
|
||||||
"Invalid height / width requested :: {} / {}".format(height, width),
|
"Invalid height / width requested :: {} / {}".format(
|
||||||
|
height, width),
|
||||||
400,
|
400,
|
||||||
)
|
)
|
||||||
|
|
||||||
frame = cv2.resize(frame, dsize=(width, height), interpolation=cv2.INTER_AREA)
|
frame = cv2.resize(frame, dsize=(width, height),
|
||||||
|
interpolation=cv2.INTER_AREA)
|
||||||
|
|
||||||
ret, img = cv2.imencode(
|
ret, img = cv2.imencode(
|
||||||
".webp", frame, [int(cv2.IMWRITE_WEBP_QUALITY), resize_quality]
|
".webp", frame, [int(cv2.IMWRITE_WEBP_QUALITY), resize_quality]
|
||||||
@ -155,14 +163,16 @@ def latest_frame(camera_name):
|
|||||||
return response
|
return response
|
||||||
elif camera_name == "birdseye" and current_app.frigate_config.birdseye.restream:
|
elif camera_name == "birdseye" and current_app.frigate_config.birdseye.restream:
|
||||||
frame = cv2.cvtColor(
|
frame = cv2.cvtColor(
|
||||||
current_app.detected_frames_processor.get_current_frame(camera_name),
|
current_app.detected_frames_processor.get_current_frame(
|
||||||
|
camera_name),
|
||||||
cv2.COLOR_YUV2BGR_I420,
|
cv2.COLOR_YUV2BGR_I420,
|
||||||
)
|
)
|
||||||
|
|
||||||
height = int(request.args.get("h", str(frame.shape[0])))
|
height = int(request.args.get("h", str(frame.shape[0])))
|
||||||
width = int(height * frame.shape[1] / frame.shape[0])
|
width = int(height * frame.shape[1] / frame.shape[0])
|
||||||
|
|
||||||
frame = cv2.resize(frame, dsize=(width, height), interpolation=cv2.INTER_AREA)
|
frame = cv2.resize(frame, dsize=(width, height),
|
||||||
|
interpolation=cv2.INTER_AREA)
|
||||||
|
|
||||||
ret, img = cv2.imencode(
|
ret, img = cv2.imencode(
|
||||||
".webp", frame, [int(cv2.IMWRITE_WEBP_QUALITY), resize_quality]
|
".webp", frame, [int(cv2.IMWRITE_WEBP_QUALITY), resize_quality]
|
||||||
@ -275,7 +285,8 @@ def submit_recording_snapshot_to_plus(camera_name: str, frame_time: str):
|
|||||||
404,
|
404,
|
||||||
)
|
)
|
||||||
|
|
||||||
nd = cv2.imdecode(np.frombuffer(image_data, dtype=np.int8), cv2.IMREAD_COLOR)
|
nd = cv2.imdecode(np.frombuffer(
|
||||||
|
image_data, dtype=np.int8), cv2.IMREAD_COLOR)
|
||||||
current_app.plus_api.upload_image(nd, camera_name)
|
current_app.plus_api.upload_image(nd, camera_name)
|
||||||
|
|
||||||
return make_response(
|
return make_response(
|
||||||
@ -378,7 +389,8 @@ def recordings_summary(camera_name):
|
|||||||
"duration": round(recording_group.duration),
|
"duration": round(recording_group.duration),
|
||||||
}
|
}
|
||||||
if day not in days:
|
if day not in days:
|
||||||
days[day] = {"events": events_count, "hours": [hour_data], "day": day}
|
days[day] = {"events": events_count,
|
||||||
|
"hours": [hour_data], "day": day}
|
||||||
else:
|
else:
|
||||||
days[day]["events"] += events_count
|
days[day]["events"] += events_count
|
||||||
days[day]["hours"].append(hour_data)
|
days[day]["hours"].append(hour_data)
|
||||||
@ -392,7 +404,8 @@ def recordings(camera_name):
|
|||||||
after = request.args.get(
|
after = request.args.get(
|
||||||
"after", type=float, default=(datetime.now() - timedelta(hours=1)).timestamp()
|
"after", type=float, default=(datetime.now() - timedelta(hours=1)).timestamp()
|
||||||
)
|
)
|
||||||
before = request.args.get("before", type=float, default=datetime.now().timestamp())
|
before = request.args.get("before", type=float,
|
||||||
|
default=datetime.now().timestamp())
|
||||||
|
|
||||||
recordings = (
|
recordings = (
|
||||||
Recordings.select(
|
Recordings.select(
|
||||||
@ -511,7 +524,8 @@ def recording_clip(camera_name, start_ts, end_ts):
|
|||||||
response.headers["Content-Disposition"] = "attachment; filename=%s" % file_name
|
response.headers["Content-Disposition"] = "attachment; filename=%s" % file_name
|
||||||
response.headers["Content-Length"] = os.path.getsize(path)
|
response.headers["Content-Length"] = os.path.getsize(path)
|
||||||
response.headers["X-Accel-Redirect"] = (
|
response.headers["X-Accel-Redirect"] = (
|
||||||
f"/cache/{file_name}" # nginx: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers
|
# nginx: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers
|
||||||
|
f"/cache/{file_name}"
|
||||||
)
|
)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
@ -521,7 +535,8 @@ def recording_clip(camera_name, start_ts, end_ts):
|
|||||||
@MediaBp.route("/vod/<camera_name>/start/<float:start_ts>/end/<float:end_ts>")
|
@MediaBp.route("/vod/<camera_name>/start/<float:start_ts>/end/<float:end_ts>")
|
||||||
def vod_ts(camera_name, start_ts, end_ts):
|
def vod_ts(camera_name, start_ts, end_ts):
|
||||||
recordings = (
|
recordings = (
|
||||||
Recordings.select(Recordings.path, Recordings.duration, Recordings.end_time)
|
Recordings.select(
|
||||||
|
Recordings.path, Recordings.duration, Recordings.end_time)
|
||||||
.where(
|
.where(
|
||||||
Recordings.start_time.between(start_ts, end_ts)
|
Recordings.start_time.between(start_ts, end_ts)
|
||||||
| Recordings.end_time.between(start_ts, end_ts)
|
| Recordings.end_time.between(start_ts, end_ts)
|
||||||
@ -550,7 +565,8 @@ def vod_ts(camera_name, start_ts, end_ts):
|
|||||||
clips.append(clip)
|
clips.append(clip)
|
||||||
durations.append(duration)
|
durations.append(duration)
|
||||||
else:
|
else:
|
||||||
logger.warning(f"Recording clip is missing or empty: {recording.path}")
|
logger.warning(
|
||||||
|
f"Recording clip is missing or empty: {recording.path}")
|
||||||
|
|
||||||
if not clips:
|
if not clips:
|
||||||
logger.error("No recordings found for the requested time range")
|
logger.error("No recordings found for the requested time range")
|
||||||
@ -588,7 +604,8 @@ def vod_hour_no_timezone(year_month, day, hour, camera_name):
|
|||||||
def vod_hour(year_month, day, hour, camera_name, tz_name):
|
def vod_hour(year_month, day, hour, camera_name, tz_name):
|
||||||
parts = year_month.split("-")
|
parts = year_month.split("-")
|
||||||
start_date = (
|
start_date = (
|
||||||
datetime(int(parts[0]), int(parts[1]), int(day), int(hour), tzinfo=timezone.utc)
|
datetime(int(parts[0]), int(parts[1]), int(
|
||||||
|
day), int(hour), tzinfo=timezone.utc)
|
||||||
- datetime.now(pytz.timezone(tz_name.replace(",", "/"))).utcoffset()
|
- datetime.now(pytz.timezone(tz_name.replace(",", "/"))).utcoffset()
|
||||||
)
|
)
|
||||||
end_date = start_date + timedelta(hours=1) - timedelta(milliseconds=1)
|
end_date = start_date + timedelta(hours=1) - timedelta(milliseconds=1)
|
||||||
@ -678,7 +695,8 @@ def label_snapshot(camera_name, label):
|
|||||||
return event_snapshot(event.id)
|
return event_snapshot(event.id)
|
||||||
except DoesNotExist:
|
except DoesNotExist:
|
||||||
frame = np.zeros((720, 1280, 3), np.uint8)
|
frame = np.zeros((720, 1280, 3), np.uint8)
|
||||||
ret, jpg = cv2.imencode(".jpg", frame, [int(cv2.IMWRITE_JPEG_QUALITY), 70])
|
ret, jpg = cv2.imencode(
|
||||||
|
".jpg", frame, [int(cv2.IMWRITE_JPEG_QUALITY), 70])
|
||||||
|
|
||||||
response = make_response(jpg.tobytes())
|
response = make_response(jpg.tobytes())
|
||||||
response.headers["Content-Type"] = "image/jpeg"
|
response.headers["Content-Type"] = "image/jpeg"
|
||||||
@ -689,7 +707,8 @@ def label_snapshot(camera_name, label):
|
|||||||
@MediaBp.route("/<camera_name>/<label>/thumbnail.jpg")
|
@MediaBp.route("/<camera_name>/<label>/thumbnail.jpg")
|
||||||
def label_thumbnail(camera_name, label):
|
def label_thumbnail(camera_name, label):
|
||||||
label = unquote(label)
|
label = unquote(label)
|
||||||
event_query = Event.select(fn.MAX(Event.id)).where(Event.camera == camera_name)
|
event_query = Event.select(fn.MAX(Event.id)).where(
|
||||||
|
Event.camera == camera_name)
|
||||||
if label != "any":
|
if label != "any":
|
||||||
event_query = event_query.where(Event.label == label)
|
event_query = event_query.where(Event.label == label)
|
||||||
|
|
||||||
@ -699,7 +718,8 @@ def label_thumbnail(camera_name, label):
|
|||||||
return event_thumbnail(event, 60)
|
return event_thumbnail(event, 60)
|
||||||
except DoesNotExist:
|
except DoesNotExist:
|
||||||
frame = np.zeros((175, 175, 3), np.uint8)
|
frame = np.zeros((175, 175, 3), np.uint8)
|
||||||
ret, jpg = cv2.imencode(".jpg", frame, [int(cv2.IMWRITE_JPEG_QUALITY), 70])
|
ret, jpg = cv2.imencode(
|
||||||
|
".jpg", frame, [int(cv2.IMWRITE_JPEG_QUALITY), 70])
|
||||||
|
|
||||||
response = make_response(jpg.tobytes())
|
response = make_response(jpg.tobytes())
|
||||||
response.headers["Content-Type"] = "image/jpeg"
|
response.headers["Content-Type"] = "image/jpeg"
|
||||||
@ -725,6 +745,7 @@ def label_clip(camera_name, label):
|
|||||||
jsonify({"success": False, "message": "Event not found"}), 404
|
jsonify({"success": False, "message": "Event not found"}), 404
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@MediaBp.route("/<camera_name>/<label>/preview.gif")
|
@MediaBp.route("/<camera_name>/<label>/preview.gif")
|
||||||
def label_preview(camera_name, label):
|
def label_preview(camera_name, label):
|
||||||
label = unquote(label)
|
label = unquote(label)
|
||||||
@ -737,14 +758,14 @@ def label_preview(camera_name, label):
|
|||||||
try:
|
try:
|
||||||
event = event_query.get()
|
event = event_query.get()
|
||||||
|
|
||||||
|
|
||||||
except DoesNotExist:
|
except DoesNotExist:
|
||||||
return make_response(
|
return make_response(
|
||||||
jsonify({"success": False, "message": "Event not found"}), 404
|
jsonify({"success": False, "message": "Event not found"}), 404
|
||||||
)
|
)
|
||||||
|
|
||||||
start_ts = event.start_time
|
start_ts = event.start_time
|
||||||
end_ts = start_ts + (min(event.end_time - event.start_time, 20) if event.end_time else 20)
|
end_ts = start_ts + \
|
||||||
|
(min(event.end_time - event.start_time, 20) if event.end_time else 20)
|
||||||
return preview_gif(event.camera, start_ts, end_ts)
|
return preview_gif(event.camera, start_ts, end_ts)
|
||||||
|
|
||||||
|
|
||||||
@ -754,14 +775,17 @@ def grid_snapshot(camera_name):
|
|||||||
|
|
||||||
if camera_name in current_app.frigate_config.cameras:
|
if camera_name in current_app.frigate_config.cameras:
|
||||||
detect = current_app.frigate_config.cameras[camera_name].detect
|
detect = current_app.frigate_config.cameras[camera_name].detect
|
||||||
frame = current_app.detected_frames_processor.get_current_frame(camera_name, {})
|
frame = current_app.detected_frames_processor.get_current_frame(
|
||||||
|
camera_name, {})
|
||||||
retry_interval = float(
|
retry_interval = float(
|
||||||
current_app.frigate_config.cameras.get(camera_name).ffmpeg.retry_interval
|
current_app.frigate_config.cameras.get(
|
||||||
|
camera_name).ffmpeg.retry_interval
|
||||||
or 10
|
or 10
|
||||||
)
|
)
|
||||||
|
|
||||||
if frame is None or datetime.now().timestamp() > (
|
if frame is None or datetime.now().timestamp() > (
|
||||||
current_app.detected_frames_processor.get_current_frame_time(camera_name)
|
current_app.detected_frames_processor.get_current_frame_time(
|
||||||
|
camera_name)
|
||||||
+ retry_interval
|
+ retry_interval
|
||||||
):
|
):
|
||||||
return make_response(
|
return make_response(
|
||||||
@ -783,7 +807,8 @@ def grid_snapshot(camera_name):
|
|||||||
)
|
)
|
||||||
|
|
||||||
color_arg = request.args.get("color", default="", type=str).lower()
|
color_arg = request.args.get("color", default="", type=str).lower()
|
||||||
draw_font_scale = request.args.get("font_scale", default=0.5, type=float)
|
draw_font_scale = request.args.get(
|
||||||
|
"font_scale", default=0.5, type=float)
|
||||||
|
|
||||||
if color_arg == "red":
|
if color_arg == "red":
|
||||||
draw_color = (0, 0, 255)
|
draw_color = (0, 0, 255)
|
||||||
@ -856,7 +881,8 @@ def grid_snapshot(camera_name):
|
|||||||
thickness=2,
|
thickness=2,
|
||||||
)
|
)
|
||||||
|
|
||||||
ret, jpg = cv2.imencode(".jpg", frame, [int(cv2.IMWRITE_JPEG_QUALITY), 70])
|
ret, jpg = cv2.imencode(
|
||||||
|
".jpg", frame, [int(cv2.IMWRITE_JPEG_QUALITY), 70])
|
||||||
response = make_response(jpg.tobytes())
|
response = make_response(jpg.tobytes())
|
||||||
response.headers["Content-Type"] = "image/jpeg"
|
response.headers["Content-Type"] = "image/jpeg"
|
||||||
response.headers["Cache-Control"] = "no-store"
|
response.headers["Cache-Control"] = "no-store"
|
||||||
@ -903,7 +929,8 @@ def event_snapshot_clean(id):
|
|||||||
)
|
)
|
||||||
elif not event.has_snapshot:
|
elif not event.has_snapshot:
|
||||||
return make_response(
|
return make_response(
|
||||||
jsonify({"success": False, "message": "Snapshot not available"}), 404
|
jsonify(
|
||||||
|
{"success": False, "message": "Snapshot not available"}), 404
|
||||||
)
|
)
|
||||||
except DoesNotExist:
|
except DoesNotExist:
|
||||||
return make_response(
|
return make_response(
|
||||||
@ -922,7 +949,8 @@ def event_snapshot_clean(id):
|
|||||||
404,
|
404,
|
||||||
)
|
)
|
||||||
with open(
|
with open(
|
||||||
os.path.join(CLIPS_DIR, f"{event.camera}-{event.id}-clean.png"), "rb"
|
os.path.join(
|
||||||
|
CLIPS_DIR, f"{event.camera}-{event.id}-clean.png"), "rb"
|
||||||
) as image_file:
|
) as image_file:
|
||||||
png_bytes = image_file.read()
|
png_bytes = image_file.read()
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -953,7 +981,8 @@ def event_snapshot(id):
|
|||||||
event_complete = True
|
event_complete = True
|
||||||
if not event.has_snapshot:
|
if not event.has_snapshot:
|
||||||
return make_response(
|
return make_response(
|
||||||
jsonify({"success": False, "message": "Snapshot not available"}), 404
|
jsonify(
|
||||||
|
{"success": False, "message": "Snapshot not available"}), 404
|
||||||
)
|
)
|
||||||
# read snapshot from disk
|
# read snapshot from disk
|
||||||
with open(
|
with open(
|
||||||
@ -973,7 +1002,8 @@ def event_snapshot(id):
|
|||||||
bounding_box=request.args.get("bbox", type=int),
|
bounding_box=request.args.get("bbox", type=int),
|
||||||
crop=request.args.get("crop", type=int),
|
crop=request.args.get("crop", type=int),
|
||||||
height=request.args.get("h", type=int),
|
height=request.args.get("h", type=int),
|
||||||
quality=request.args.get("quality", default=70, type=int),
|
quality=request.args.get(
|
||||||
|
"quality", default=70, type=int),
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
return make_response(
|
return make_response(
|
||||||
@ -1035,7 +1065,8 @@ def event_clip(id):
|
|||||||
response.headers["Content-Disposition"] = "attachment; filename=%s" % file_name
|
response.headers["Content-Disposition"] = "attachment; filename=%s" % file_name
|
||||||
response.headers["Content-Length"] = os.path.getsize(clip_path)
|
response.headers["Content-Length"] = os.path.getsize(clip_path)
|
||||||
response.headers["X-Accel-Redirect"] = (
|
response.headers["X-Accel-Redirect"] = (
|
||||||
f"/clips/{file_name}" # nginx: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers
|
# nginx: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers
|
||||||
|
f"/clips/{file_name}"
|
||||||
)
|
)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
@ -1083,7 +1114,8 @@ def event_thumbnail(id, max_cache_age=2592000):
|
|||||||
cv2.BORDER_CONSTANT,
|
cv2.BORDER_CONSTANT,
|
||||||
(0, 0, 0),
|
(0, 0, 0),
|
||||||
)
|
)
|
||||||
ret, jpg = cv2.imencode(".jpg", thumbnail, [int(cv2.IMWRITE_JPEG_QUALITY), 70])
|
ret, jpg = cv2.imencode(
|
||||||
|
".jpg", thumbnail, [int(cv2.IMWRITE_JPEG_QUALITY), 70])
|
||||||
thumbnail_bytes = jpg.tobytes()
|
thumbnail_bytes = jpg.tobytes()
|
||||||
|
|
||||||
response = make_response(thumbnail_bytes)
|
response = make_response(thumbnail_bytes)
|
||||||
@ -1174,7 +1206,8 @@ def preview_gif(camera_name: str, start_ts, end_ts, max_cache_age=2592000):
|
|||||||
if process.returncode != 0:
|
if process.returncode != 0:
|
||||||
logger.error(process.stderr)
|
logger.error(process.stderr)
|
||||||
return make_response(
|
return make_response(
|
||||||
jsonify({"success": False, "message": "Unable to create preview gif"}),
|
jsonify(
|
||||||
|
{"success": False, "message": "Unable to create preview gif"}),
|
||||||
500,
|
500,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1197,7 +1230,8 @@ def preview_gif(camera_name: str, start_ts, end_ts, max_cache_age=2592000):
|
|||||||
if file > end_file:
|
if file > end_file:
|
||||||
break
|
break
|
||||||
|
|
||||||
selected_previews.append(f"file '{os.path.join(preview_dir, file)}'")
|
selected_previews.append(
|
||||||
|
f"file '{os.path.join(preview_dir, file)}'")
|
||||||
selected_previews.append("duration 0.12")
|
selected_previews.append("duration 0.12")
|
||||||
|
|
||||||
if not selected_previews:
|
if not selected_previews:
|
||||||
@ -1240,7 +1274,8 @@ def preview_gif(camera_name: str, start_ts, end_ts, max_cache_age=2592000):
|
|||||||
if process.returncode != 0:
|
if process.returncode != 0:
|
||||||
logger.error(process.stderr)
|
logger.error(process.stderr)
|
||||||
return make_response(
|
return make_response(
|
||||||
jsonify({"success": False, "message": "Unable to create preview gif"}),
|
jsonify(
|
||||||
|
{"success": False, "message": "Unable to create preview gif"}),
|
||||||
500,
|
500,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1333,7 +1368,8 @@ def preview_mp4(camera_name: str, start_ts, end_ts):
|
|||||||
if process.returncode != 0:
|
if process.returncode != 0:
|
||||||
logger.error(process.stderr)
|
logger.error(process.stderr)
|
||||||
return make_response(
|
return make_response(
|
||||||
jsonify({"success": False, "message": "Unable to create preview gif"}),
|
jsonify(
|
||||||
|
{"success": False, "message": "Unable to create preview gif"}),
|
||||||
500,
|
500,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1355,7 +1391,8 @@ def preview_mp4(camera_name: str, start_ts, end_ts):
|
|||||||
if file > end_file:
|
if file > end_file:
|
||||||
break
|
break
|
||||||
|
|
||||||
selected_previews.append(f"file '{os.path.join(preview_dir, file)}'")
|
selected_previews.append(
|
||||||
|
f"file '{os.path.join(preview_dir, file)}'")
|
||||||
selected_previews.append("duration 0.12")
|
selected_previews.append("duration 0.12")
|
||||||
|
|
||||||
if not selected_previews:
|
if not selected_previews:
|
||||||
@ -1396,7 +1433,8 @@ def preview_mp4(camera_name: str, start_ts, end_ts):
|
|||||||
if process.returncode != 0:
|
if process.returncode != 0:
|
||||||
logger.error(process.stderr)
|
logger.error(process.stderr)
|
||||||
return make_response(
|
return make_response(
|
||||||
jsonify({"success": False, "message": "Unable to create preview gif"}),
|
jsonify(
|
||||||
|
{"success": False, "message": "Unable to create preview gif"}),
|
||||||
500,
|
500,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1406,7 +1444,8 @@ def preview_mp4(camera_name: str, start_ts, end_ts):
|
|||||||
response.headers["Content-Type"] = "video/mp4"
|
response.headers["Content-Type"] = "video/mp4"
|
||||||
response.headers["Content-Length"] = os.path.getsize(path)
|
response.headers["Content-Length"] = os.path.getsize(path)
|
||||||
response.headers["X-Accel-Redirect"] = (
|
response.headers["X-Accel-Redirect"] = (
|
||||||
f"/cache/{file_name}" # nginx: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers
|
# nginx: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers
|
||||||
|
f"/cache/{file_name}"
|
||||||
)
|
)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user