mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-05-09 15:05:26 +03:00
Compare commits
5 Commits
361cb13cb6
...
3bcca216e1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3bcca216e1 | ||
|
|
fb3bb380fd | ||
|
|
ec1d794655 | ||
|
|
b12552571e | ||
|
|
7c2f4b5d1e |
@ -19,6 +19,11 @@ from frigate.util.object import calculate_region
|
|||||||
from ..types import DataProcessorMetrics
|
from ..types import DataProcessorMetrics
|
||||||
from .api import RealTimeProcessorApi
|
from .api import RealTimeProcessorApi
|
||||||
|
|
||||||
|
try:
|
||||||
|
from tflite_runtime.interpreter import Interpreter
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
from tensorflow.lite.python.interpreter import Interpreter
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -30,7 +35,7 @@ class BirdRealTimeProcessor(RealTimeProcessorApi):
|
|||||||
metrics: DataProcessorMetrics,
|
metrics: DataProcessorMetrics,
|
||||||
):
|
):
|
||||||
super().__init__(config, metrics)
|
super().__init__(config, metrics)
|
||||||
self.interpreter: Any | None = None
|
self.interpreter: Interpreter = None
|
||||||
self.sub_label_publisher = sub_label_publisher
|
self.sub_label_publisher = sub_label_publisher
|
||||||
self.tensor_input_details: dict[str, Any] = None
|
self.tensor_input_details: dict[str, Any] = None
|
||||||
self.tensor_output_details: dict[str, Any] = None
|
self.tensor_output_details: dict[str, Any] = None
|
||||||
@ -77,11 +82,6 @@ class BirdRealTimeProcessor(RealTimeProcessorApi):
|
|||||||
|
|
||||||
@redirect_output_to_logger(logger, logging.DEBUG)
|
@redirect_output_to_logger(logger, logging.DEBUG)
|
||||||
def __build_detector(self) -> None:
|
def __build_detector(self) -> None:
|
||||||
try:
|
|
||||||
from tflite_runtime.interpreter import Interpreter
|
|
||||||
except ModuleNotFoundError:
|
|
||||||
from tensorflow.lite.python.interpreter import Interpreter
|
|
||||||
|
|
||||||
self.interpreter = Interpreter(
|
self.interpreter = Interpreter(
|
||||||
model_path=os.path.join(MODEL_CACHE_DIR, "bird/bird.tflite"),
|
model_path=os.path.join(MODEL_CACHE_DIR, "bird/bird.tflite"),
|
||||||
num_threads=2,
|
num_threads=2,
|
||||||
|
|||||||
@ -29,6 +29,11 @@ from frigate.util.object import box_overlaps, calculate_region
|
|||||||
from ..types import DataProcessorMetrics
|
from ..types import DataProcessorMetrics
|
||||||
from .api import RealTimeProcessorApi
|
from .api import RealTimeProcessorApi
|
||||||
|
|
||||||
|
try:
|
||||||
|
from tflite_runtime.interpreter import Interpreter
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
from tensorflow.lite.python.interpreter import Interpreter
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
MAX_OBJECT_CLASSIFICATIONS = 16
|
MAX_OBJECT_CLASSIFICATIONS = 16
|
||||||
@ -47,7 +52,7 @@ class CustomStateClassificationProcessor(RealTimeProcessorApi):
|
|||||||
self.requestor = requestor
|
self.requestor = requestor
|
||||||
self.model_dir = os.path.join(MODEL_CACHE_DIR, self.model_config.name)
|
self.model_dir = os.path.join(MODEL_CACHE_DIR, self.model_config.name)
|
||||||
self.train_dir = os.path.join(CLIPS_DIR, self.model_config.name, "train")
|
self.train_dir = os.path.join(CLIPS_DIR, self.model_config.name, "train")
|
||||||
self.interpreter: Any | None = None
|
self.interpreter: Interpreter = None
|
||||||
self.tensor_input_details: dict[str, Any] | None = None
|
self.tensor_input_details: dict[str, Any] | None = None
|
||||||
self.tensor_output_details: dict[str, Any] | None = None
|
self.tensor_output_details: dict[str, Any] | None = None
|
||||||
self.labelmap: dict[int, str] = {}
|
self.labelmap: dict[int, str] = {}
|
||||||
@ -345,7 +350,7 @@ class CustomObjectClassificationProcessor(RealTimeProcessorApi):
|
|||||||
self.model_config = model_config
|
self.model_config = model_config
|
||||||
self.model_dir = os.path.join(MODEL_CACHE_DIR, self.model_config.name)
|
self.model_dir = os.path.join(MODEL_CACHE_DIR, self.model_config.name)
|
||||||
self.train_dir = os.path.join(CLIPS_DIR, self.model_config.name, "train")
|
self.train_dir = os.path.join(CLIPS_DIR, self.model_config.name, "train")
|
||||||
self.interpreter: Any | None = None
|
self.interpreter: Interpreter = None
|
||||||
self.sub_label_publisher = sub_label_publisher
|
self.sub_label_publisher = sub_label_publisher
|
||||||
self.requestor = requestor
|
self.requestor = requestor
|
||||||
self.tensor_input_details: dict[str, Any] | None = None
|
self.tensor_input_details: dict[str, Any] | None = None
|
||||||
@ -368,11 +373,6 @@ class CustomObjectClassificationProcessor(RealTimeProcessorApi):
|
|||||||
|
|
||||||
@redirect_output_to_logger(logger, logging.DEBUG)
|
@redirect_output_to_logger(logger, logging.DEBUG)
|
||||||
def __build_detector(self) -> None:
|
def __build_detector(self) -> None:
|
||||||
try:
|
|
||||||
from tflite_runtime.interpreter import Interpreter
|
|
||||||
except ModuleNotFoundError:
|
|
||||||
from tensorflow.lite.python.interpreter import Interpreter
|
|
||||||
|
|
||||||
model_path = os.path.join(self.model_dir, "model.tflite")
|
model_path = os.path.join(self.model_dir, "model.tflite")
|
||||||
labelmap_path = os.path.join(self.model_dir, "labelmap.txt")
|
labelmap_path = os.path.join(self.model_dir, "labelmap.txt")
|
||||||
|
|
||||||
|
|||||||
@ -146,29 +146,6 @@ class EmbeddingMaintainer(threading.Thread):
|
|||||||
self.detected_license_plates: dict[str, dict[str, Any]] = {}
|
self.detected_license_plates: dict[str, dict[str, Any]] = {}
|
||||||
self.genai_client = get_genai_client(config)
|
self.genai_client = get_genai_client(config)
|
||||||
|
|
||||||
# Pre-import TensorFlow/tflite on main thread to avoid atexit registration issues
|
|
||||||
# when importing from worker threads later (e.g., during dynamic config updates)
|
|
||||||
if (
|
|
||||||
self.config.classification.bird.enabled
|
|
||||||
or len(self.config.classification.custom) > 0
|
|
||||||
):
|
|
||||||
try:
|
|
||||||
from tflite_runtime.interpreter import Interpreter # noqa: F401
|
|
||||||
except ModuleNotFoundError:
|
|
||||||
try:
|
|
||||||
from tensorflow.lite.python.interpreter import ( # noqa: F401
|
|
||||||
Interpreter,
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.debug(
|
|
||||||
"Pre-imported TensorFlow Interpreter on main thread for classification models"
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(
|
|
||||||
f"Failed to pre-import TensorFlow Interpreter: {e}. "
|
|
||||||
"Classification models may fail to load if added dynamically."
|
|
||||||
)
|
|
||||||
|
|
||||||
# model runners to share between realtime and post processors
|
# model runners to share between realtime and post processors
|
||||||
if self.config.lpr.enabled:
|
if self.config.lpr.enabled:
|
||||||
lpr_model_runner = LicensePlateModelRunner(
|
lpr_model_runner = LicensePlateModelRunner(
|
||||||
|
|||||||
@ -186,6 +186,9 @@ class JinaV1ImageEmbedding(BaseEmbedding):
|
|||||||
download_func=self._download_model,
|
download_func=self._download_model,
|
||||||
)
|
)
|
||||||
self.downloader.ensure_model_files()
|
self.downloader.ensure_model_files()
|
||||||
|
# Avoid lazy loading in worker threads: block until downloads complete
|
||||||
|
# and load the model on the main thread during initialization.
|
||||||
|
self._load_model_and_utils()
|
||||||
else:
|
else:
|
||||||
self.downloader = None
|
self.downloader = None
|
||||||
ModelDownloader.mark_files_state(
|
ModelDownloader.mark_files_state(
|
||||||
|
|||||||
@ -65,6 +65,9 @@ class JinaV2Embedding(BaseEmbedding):
|
|||||||
download_func=self._download_model,
|
download_func=self._download_model,
|
||||||
)
|
)
|
||||||
self.downloader.ensure_model_files()
|
self.downloader.ensure_model_files()
|
||||||
|
# Avoid lazy loading in worker threads: block until downloads complete
|
||||||
|
# and load the model on the main thread during initialization.
|
||||||
|
self._load_model_and_utils()
|
||||||
else:
|
else:
|
||||||
self.downloader = None
|
self.downloader = None
|
||||||
ModelDownloader.mark_files_state(
|
ModelDownloader.mark_files_state(
|
||||||
|
|||||||
@ -54,7 +54,7 @@ export default function useCameraLiveMode(
|
|||||||
}>({});
|
}>({});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!cameras) return;
|
if (!cameras || cameras.length === 0) return;
|
||||||
|
|
||||||
const mseSupported =
|
const mseSupported =
|
||||||
"MediaSource" in window || "ManagedMediaSource" in window;
|
"MediaSource" in window || "ManagedMediaSource" in window;
|
||||||
|
|||||||
@ -147,10 +147,11 @@ export default function LiveCameraView({
|
|||||||
|
|
||||||
// supported features
|
// supported features
|
||||||
|
|
||||||
const [streamName, setStreamName] = useUserPersistence<string>(
|
const [streamName, setStreamName, streamNameLoaded] =
|
||||||
`${camera.name}-stream`,
|
useUserPersistence<string>(
|
||||||
Object.values(camera.live.streams)[0],
|
`${camera.name}-stream`,
|
||||||
);
|
Object.values(camera.live.streams)[0],
|
||||||
|
);
|
||||||
|
|
||||||
const isRestreamed = useMemo(
|
const isRestreamed = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@ -159,6 +160,19 @@ export default function LiveCameraView({
|
|||||||
[config, streamName],
|
[config, streamName],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// validate stored stream name and reset if now invalid
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!streamNameLoaded) return;
|
||||||
|
|
||||||
|
const available = Object.values(camera.live.streams || {});
|
||||||
|
if (available.length === 0) return;
|
||||||
|
|
||||||
|
if (streamName != null && !available.includes(streamName)) {
|
||||||
|
setStreamName(available[0]);
|
||||||
|
}
|
||||||
|
}, [streamNameLoaded, camera.live.streams, streamName, setStreamName]);
|
||||||
|
|
||||||
const { data: cameraMetadata } = useSWR<LiveStreamMetadata>(
|
const { data: cameraMetadata } = useSWR<LiveStreamMetadata>(
|
||||||
isRestreamed ? `go2rtc/streams/${streamName}` : null,
|
isRestreamed ? `go2rtc/streams/${streamName}` : null,
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user