update code

This commit is contained in:
ekAI-anhnln 2025-03-29 10:24:31 +07:00
parent e3ed1ab8ec
commit cc0b707732
24 changed files with 97 additions and 56 deletions

3
.gitignore vendored
View File

@ -11,7 +11,7 @@ models
*.mp4 *.mp4
*.db *.db
*.csv *.csv
frigate/version.py # frigate/version.py
web/build web/build
web/node_modules web/node_modules
web/coverage web/coverage
@ -19,3 +19,4 @@ core
!/web/**/*.ts !/web/**/*.ts
.idea/* .idea/*
.ipynb_checkpoints .ipynb_checkpoints
media/*

View File

@ -13,7 +13,7 @@ from frigate.object_detection import (
) )
my_frame = np.expand_dims(np.full((300, 300, 3), 1, np.uint8), axis=0) my_frame = np.expand_dims(np.full((300, 300, 3), 1, np.uint8), axis=0)
labels = load_labels("/labelmap.txt") labels = load_labels("./labelmap.txt")
###### ######
# Minimal same process runner # Minimal same process runner

BIN
cpu_model.tflite Normal file

Binary file not shown.

View File

@ -8,7 +8,7 @@
"node_modules", "node_modules",
"__pycache__", "__pycache__",
"dist", "dist",
"/audio-labelmap.txt" "./audio-labelmap.txt"
], ],
"language": "en", "language": "en",
"dictionaryDefinitions": [ "dictionaryDefinitions": [

View File

@ -15,7 +15,7 @@ sys.path.remove("/opt/frigate")
yaml = YAML() yaml = YAML()
config_file = os.environ.get("CONFIG_FILE", "/config/config.yml") config_file = os.environ.get("CONFIG_FILE", "./config/config.yml")
# Check if we can use .yaml instead of .yml # Check if we can use .yaml instead of .yml
config_file_yaml = config_file.replace(".yml", ".yaml") config_file_yaml = config_file.replace(".yml", ".yaml")

View File

@ -29,7 +29,7 @@ if os.path.isdir("/run/secrets"):
Path(os.path.join("/run/secrets", secret_file)).read_text().strip() Path(os.path.join("/run/secrets", secret_file)).read_text().strip()
) )
config_file = os.environ.get("CONFIG_FILE", "/config/config.yml") config_file = os.environ.get("CONFIG_FILE", "./config/config.yml")
# Check if we can use .yaml instead of .yml # Check if we can use .yaml instead of .yml
config_file_yaml = config_file.replace(".yml", ".yaml") config_file_yaml = config_file.replace(".yml", ".yaml")

View File

@ -1,8 +1,8 @@
daemon off; # daemon off;
user root; user root;
worker_processes auto; worker_processes auto;
error_log /dev/stdout warn; # error_log /dev/stdout warn;
pid /var/run/nginx.pid; pid /var/run/nginx.pid;
events { events {
@ -19,7 +19,7 @@ http {
'$status $body_bytes_sent "$http_referer" ' '$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'; '"$http_user_agent" "$http_x_forwarded_for"';
access_log /dev/stdout main; # access_log /dev/stdout main;
# send headers in one piece, it is better than sending them one by one # send headers in one piece, it is better than sending them one by one
tcp_nopush on; tcp_nopush on;

View File

@ -7,7 +7,7 @@ from ruamel.yaml import YAML
yaml = YAML() yaml = YAML()
config_file = os.environ.get("CONFIG_FILE", "/config/config.yml") config_file = os.environ.get("CONFIG_FILE", "./config/config.yml")
# Check if we can use .yaml instead of .yml # Check if we can use .yaml instead of .yml
config_file_yaml = config_file.replace(".yml", ".yaml") config_file_yaml = config_file.replace(".yml", ".yaml")

View File

@ -7,7 +7,8 @@ import shutil
from multiprocessing import Queue from multiprocessing import Queue
from multiprocessing.synchronize import Event as MpEvent from multiprocessing.synchronize import Event as MpEvent
from typing import Optional from typing import Optional
import subprocess
import sys
import psutil import psutil
import uvicorn import uvicorn
from peewee_migrate import Router from peewee_migrate import Router
@ -94,6 +95,37 @@ class FrigateApp:
self.region_grids: dict[str, list[list[dict[str, int]]]] = {} self.region_grids: dict[str, list[list[dict[str, int]]]] = {}
self.frame_manager = SharedMemoryFrameManager() self.frame_manager = SharedMemoryFrameManager()
self.config = config self.config = config
self.go2rtc_process = self.run_go2rtc()
# self.nginx_process = self.run_nginx()
def run_go2rtc(self, config_path="./config/cam.yaml"):
"""
Hàm chạy Frigate cùng với go2rtc trong một tiến trình nền.
Args:
config_path (str): Đường dẫn đến file cấu hình của go2rtc (mặc định: config/cam.yaml)
"""
# Khởi động go2rtc trong một tiến trình nền
go2rtc_process = subprocess.Popen(
["go2rtc", "-c", config_path],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True # Để dễ đọc output dưới dạng chuỗi
)
print(f"Đã khởi động go2rtc với PID: {go2rtc_process.pid}")
return go2rtc_process
def run_nginx(self):
nginx_path = shutil.which("nginx")
nginx_process = subprocess.Popen(
["sudo", nginx_path],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
print(f"Đã khởi động Nginx với PID: {nginx_process.pid}")
return nginx_process
def ensure_dirs(self) -> None: def ensure_dirs(self) -> None:
for d in [ for d in [
@ -583,7 +615,6 @@ class FrigateApp:
def start(self) -> None: def start(self) -> None:
logger.info(f"Starting Frigate ({VERSION})") logger.info(f"Starting Frigate ({VERSION})")
# Ensure global state. # Ensure global state.
self.ensure_dirs() self.ensure_dirs()
@ -643,6 +674,12 @@ class FrigateApp:
def stop(self) -> None: def stop(self) -> None:
logger.info("Stopping...") logger.info("Stopping...")
self.go2rtc_process.terminate()
logger.info("Exiting go2rtc...")
# self.nginx_process.terminate()
# logger.info("Exiting Nginx...")
self.stop_event.set() self.stop_event.set()
# set an end_time on entries without an end_time before exiting # set an end_time on entries without an end_time before exiting

View File

@ -67,27 +67,29 @@ class FfmpegConfig(FrigateBaseModel):
@property @property
def ffmpeg_path(self) -> str: def ffmpeg_path(self) -> str:
if self.path == "default": # if self.path == "default":
if shutil.which("ffmpeg") is None: # if shutil.which("ffmpeg") is None:
return f"/usr/lib/ffmpeg/{DEFAULT_FFMPEG_VERSION}/bin/ffmpeg" # return f"/usr/lib/ffmpeg/{DEFAULT_FFMPEG_VERSION}/bin/ffmpeg"
else: # else:
return "ffmpeg" # return "ffmpeg"
elif self.path in INCLUDED_FFMPEG_VERSIONS: # elif self.path in INCLUDED_FFMPEG_VERSIONS:
return f"/usr/lib/ffmpeg/{self.path}/bin/ffmpeg" # return f"/usr/lib/ffmpeg/{self.path}/bin/ffmpeg"
else: # else:
return f"{self.path}/bin/ffmpeg" # return f"{self.path}/bin/ffmpeg"
return shutil.which("ffmpeg")
@property @property
def ffprobe_path(self) -> str: def ffprobe_path(self) -> str:
if self.path == "default": # if self.path == "default":
if shutil.which("ffprobe") is None: # if shutil.which("ffprobe") is None:
return f"/usr/lib/ffmpeg/{DEFAULT_FFMPEG_VERSION}/bin/ffprobe" # return f"/usr/lib/ffmpeg/{DEFAULT_FFMPEG_VERSION}/bin/ffprobe"
else: # else:
return "ffprobe" # return "ffprobe"
elif self.path in INCLUDED_FFMPEG_VERSIONS: # elif self.path in INCLUDED_FFMPEG_VERSIONS:
return f"/usr/lib/ffmpeg/{self.path}/bin/ffprobe" # return f"/usr/lib/ffmpeg/{self.path}/bin/ffprobe"
else: # else:
return f"{self.path}/bin/ffprobe" # return f"{self.path}/bin/ffprobe"
return shutil.which("ffprobe")
class CameraRoleEnum(str, Enum): class CameraRoleEnum(str, Enum):

View File

@ -607,9 +607,9 @@ class FrigateConfig(FrigateBaseModel):
if "path" not in model_config: if "path" not in model_config:
if detector_config.type == "cpu": if detector_config.type == "cpu":
model_config["path"] = "/cpu_model.tflite" model_config["path"] = "./cpu_model.tflite"
elif detector_config.type == "edgetpu": elif detector_config.type == "edgetpu":
model_config["path"] = "/edgetpu_model.tflite" model_config["path"] = "./edgetpu_model.tflite"
model = ModelConfig.model_validate(model_config) model = ModelConfig.model_validate(model_config)
model.check_and_load_plus_model(self.plus_api, detector_config.type) model.check_and_load_plus_model(self.plus_api, detector_config.type)

View File

@ -1,9 +1,9 @@
import re import re
CONFIG_DIR = "/config" CONFIG_DIR = "./config"
DEFAULT_DB_PATH = f"{CONFIG_DIR}/frigate.db" DEFAULT_DB_PATH = f"{CONFIG_DIR}/frigate.db"
MODEL_CACHE_DIR = f"{CONFIG_DIR}/model_cache" MODEL_CACHE_DIR = f"{CONFIG_DIR}/model_cache"
BASE_DIR = "/media/frigate" BASE_DIR = "./media/frigate"
CLIPS_DIR = f"{BASE_DIR}/clips" CLIPS_DIR = f"{BASE_DIR}/clips"
RECORD_DIR = f"{BASE_DIR}/recordings" RECORD_DIR = f"{BASE_DIR}/recordings"
EXPORT_DIR = f"{BASE_DIR}/exports" EXPORT_DIR = f"{BASE_DIR}/exports"

View File

@ -94,7 +94,7 @@ class ModelConfig(BaseModel):
super().__init__(**config) super().__init__(**config)
self._merged_labelmap = { self._merged_labelmap = {
**load_labels(config.get("labelmap_path", "/labelmap.txt")), **load_labels(config.get("labelmap_path", "./labelmap.txt")),
**config.get("labelmap", {}), **config.get("labelmap", {}),
} }
self._colormap = {} self._colormap = {}
@ -117,7 +117,7 @@ class ModelConfig(BaseModel):
return return
model_id = self.path[7:] model_id = self.path[7:]
self.path = f"/config/model_cache/{model_id}" self.path = f"./config/model_cache/{model_id}"
model_info_path = f"{self.path}.json" model_info_path = f"{self.path}.json"
# download the model if it doesn't exist # download the model if it doesn't exist

View File

@ -57,7 +57,7 @@ class HailoDetector(DetectionApi):
self.h8l_tensor_format = detector_config.model.input_tensor self.h8l_tensor_format = detector_config.model.input_tensor
self.h8l_pixel_format = detector_config.model.input_pixel_format self.h8l_pixel_format = detector_config.model.input_pixel_format
self.model_url = "https://hailo-model-zoo.s3.eu-west-2.amazonaws.com/ModelZoo/Compiled/v2.11.0/hailo8l/ssd_mobilenet_v1.hef" self.model_url = "https://hailo-model-zoo.s3.eu-west-2.amazonaws.com/ModelZoo/Compiled/v2.11.0/hailo8l/ssd_mobilenet_v1.hef"
self.cache_dir = "/config/model_cache/h8l_cache" self.cache_dir = "./config/model_cache/h8l_cache"
self.expected_model_filename = "ssd_mobilenet_v1.hef" self.expected_model_filename = "ssd_mobilenet_v1.hef"
output_type = "FLOAT32" output_type = "FLOAT32"

View File

@ -35,8 +35,8 @@ class OvDetector(DetectionApi):
logger.error(f"OpenVino model file {detector_config.model.path} not found.") logger.error(f"OpenVino model file {detector_config.model.path} not found.")
raise FileNotFoundError raise FileNotFoundError
os.makedirs("/config/model_cache/openvino", exist_ok=True) os.makedirs("./config/model_cache/openvino", exist_ok=True)
self.ov_core.set_property({props.cache_dir: "/config/model_cache/openvino"}) self.ov_core.set_property({props.cache_dir: "./config/model_cache/openvino"})
self.interpreter = self.ov_core.compile_model( self.interpreter = self.ov_core.compile_model(
model=detector_config.model.path, device_name=detector_config.device model=detector_config.model.path, device_name=detector_config.device
) )

View File

@ -17,7 +17,7 @@ supported_socs = ["rk3562", "rk3566", "rk3568", "rk3576", "rk3588"]
supported_models = {ModelTypeEnum.yolonas: "^deci-fp16-yolonas_[sml]$"} supported_models = {ModelTypeEnum.yolonas: "^deci-fp16-yolonas_[sml]$"}
model_cache_dir = "/config/model_cache/rknn_cache/" model_cache_dir = "./config/model_cache/rknn_cache/"
class RknnDetectorConfig(BaseDetectorConfig): class RknnDetectorConfig(BaseDetectorConfig):

View File

@ -116,7 +116,7 @@ class ROCmDetector(DetectionApi):
logger.info(f"AMD/ROCm: saving parsed model into {mxr_path}") logger.info(f"AMD/ROCm: saving parsed model into {mxr_path}")
os.makedirs("/config/model_cache/rocm", exist_ok=True) os.makedirs("./config/model_cache/rocm", exist_ok=True)
migraphx.save(self.model, mxr_path) migraphx.save(self.model, mxr_path)
logger.info("AMD/ROCm: model loaded") logger.info("AMD/ROCm: model loaded")

View File

@ -309,7 +309,7 @@ class AudioTfl:
def __init__(self, stop_event: threading.Event, num_threads=2): def __init__(self, stop_event: threading.Event, num_threads=2):
self.stop_event = stop_event self.stop_event = stop_event
self.num_threads = num_threads self.num_threads = num_threads
self.labels = load_labels("/audio-labelmap.txt", prefill=521) self.labels = load_labels("./audio-labelmap.txt", prefill=521)
self.interpreter = Interpreter( self.interpreter = Interpreter(
model_path="/cpu_audio_model.tflite", model_path="/cpu_audio_model.tflite",
num_threads=self.num_threads, num_threads=self.num_threads,

View File

@ -75,11 +75,11 @@ class TestConfig(unittest.TestCase):
"detectors": { "detectors": {
"cpu": { "cpu": {
"type": "cpu", "type": "cpu",
"model_path": "/cpu_model.tflite", "model_path": "./cpu_model.tflite",
}, },
"edgetpu": { "edgetpu": {
"type": "edgetpu", "type": "edgetpu",
"model_path": "/edgetpu_model.tflite", "model_path": "./edgetpu_model.tflite",
}, },
"openvino": { "openvino": {
"type": "openvino", "type": "openvino",
@ -854,9 +854,9 @@ class TestConfig(unittest.TestCase):
assert frigate_config.model.merged_labelmap[0] == "person" assert frigate_config.model.merged_labelmap[0] == "person"
def test_plus_labelmap(self): def test_plus_labelmap(self):
with open("/config/model_cache/test", "w") as f: with open("./config/model_cache/test", "w") as f:
json.dump(self.plus_model_info, f) json.dump(self.plus_model_info, f)
with open("/config/model_cache/test.json", "w") as f: with open("./config/model_cache/test.json", "w") as f:
json.dump(self.plus_model_info, f) json.dump(self.plus_model_info, f)
config = { config = {

View File

@ -316,7 +316,7 @@ class TestHttp(unittest.TestCase):
) )
with TestClient(app) as client: with TestClient(app) as client:
config = client.get("/config").json() config = client.get("./config").json()
assert config assert config
assert config["cameras"]["front_door"] assert config["cameras"]["front_door"]

View File

@ -14,7 +14,7 @@ from frigate.util.services import get_video_properties
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
CURRENT_CONFIG_VERSION = "0.15-1" CURRENT_CONFIG_VERSION = "0.15-1"
DEFAULT_CONFIG_FILE = "/config/config.yml" DEFAULT_CONFIG_FILE = "./config/config.yml"
def find_config_file() -> str: def find_config_file() -> str:

View File

@ -46,7 +46,7 @@ def get_ort_providers(
# so it is not enabled by default # so it is not enabled by default
if device == "Tensorrt": if device == "Tensorrt":
os.makedirs( os.makedirs(
"/config/model_cache/tensorrt/ort/trt-engines", exist_ok=True "./config/model_cache/tensorrt/ort/trt-engines", exist_ok=True
) )
device_id = 0 if not device.isdigit() else int(device) device_id = 0 if not device.isdigit() else int(device)
providers.append(provider) providers.append(provider)
@ -57,19 +57,19 @@ def get_ort_providers(
and os.environ.get("USE_FP_16", "True") != "False", and os.environ.get("USE_FP_16", "True") != "False",
"trt_timing_cache_enable": True, "trt_timing_cache_enable": True,
"trt_engine_cache_enable": True, "trt_engine_cache_enable": True,
"trt_timing_cache_path": "/config/model_cache/tensorrt/ort", "trt_timing_cache_path": "./config/model_cache/tensorrt/ort",
"trt_engine_cache_path": "/config/model_cache/tensorrt/ort/trt-engines", "trt_engine_cache_path": "./config/model_cache/tensorrt/ort/trt-engines",
} }
) )
else: else:
continue continue
elif provider == "OpenVINOExecutionProvider": elif provider == "OpenVINOExecutionProvider":
os.makedirs("/config/model_cache/openvino/ort", exist_ok=True) os.makedirs("./config/model_cache/openvino/ort", exist_ok=True)
providers.append(provider) providers.append(provider)
options.append( options.append(
{ {
"arena_extend_strategy": "kSameAsRequested", "arena_extend_strategy": "kSameAsRequested",
"cache_dir": "/config/model_cache/openvino/ort", "cache_dir": "./config/model_cache/openvino/ort",
"device_type": device, "device_type": device,
} }
) )
@ -103,7 +103,7 @@ class ONNXModelRunner:
self.type = "ov" self.type = "ov"
self.ov = ov.Core() self.ov = ov.Core()
self.ov.set_property( self.ov.set_property(
{ov.properties.cache_dir: "/config/model_cache/openvino"} {ov.properties.cache_dir: "./config/model_cache/openvino"}
) )
self.interpreter = self.ov.compile_model( self.interpreter = self.ov.compile_model(
model=model_path, device_name=device model=model_path, device_name=device

1
frigate/version.py Normal file
View File

@ -0,0 +1 @@
VERSION = "0.15.0"

View File

@ -266,7 +266,7 @@ def process(path, label, output, debug_path):
}, },
} }
object_detector = LocalObjectDetector(labels="/labelmap.txt") object_detector = LocalObjectDetector(labels="./labelmap.txt")
results = [] results = []
for c in clips: for c in clips: