mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-01-22 20:18:30 +03:00
Compare commits
11 Commits
62e45e1682
...
08366bb9db
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08366bb9db | ||
|
|
87376d9875 | ||
|
|
d743ee7435 | ||
|
|
3f165b971d | ||
|
|
fa77625d45 | ||
|
|
ce2500a45a | ||
|
|
5313bb9a42 | ||
|
|
2c0b3684c9 | ||
|
|
22f9056264 | ||
|
|
30d7a79987 | ||
|
|
9c2f3b9ce6 |
@ -97,7 +97,6 @@ class RecordingMaintainer(threading.Thread):
|
||||
self.object_recordings_info: dict[str, list] = defaultdict(list)
|
||||
self.audio_recordings_info: dict[str, list] = defaultdict(list)
|
||||
self.end_time_cache: dict[str, Tuple[datetime.datetime, float]] = {}
|
||||
self.unexpected_cache_files_logged: bool = False
|
||||
|
||||
async def move_files(self) -> None:
|
||||
cache_files = [
|
||||
@ -113,14 +112,7 @@ class RecordingMaintainer(threading.Thread):
|
||||
for cache in cache_files:
|
||||
cache_path = os.path.join(CACHE_DIR, cache)
|
||||
basename = os.path.splitext(cache)[0]
|
||||
try:
|
||||
camera, date = basename.rsplit("@", maxsplit=1)
|
||||
except ValueError:
|
||||
if not self.unexpected_cache_files_logged:
|
||||
logger.warning("Skipping unexpected files in cache")
|
||||
self.unexpected_cache_files_logged = True
|
||||
continue
|
||||
|
||||
camera, date = basename.rsplit("@", maxsplit=1)
|
||||
start_time = datetime.datetime.strptime(
|
||||
date, CACHE_SEGMENT_FORMAT
|
||||
).astimezone(datetime.timezone.utc)
|
||||
@ -172,13 +164,7 @@ class RecordingMaintainer(threading.Thread):
|
||||
|
||||
cache_path = os.path.join(CACHE_DIR, cache)
|
||||
basename = os.path.splitext(cache)[0]
|
||||
try:
|
||||
camera, date = basename.rsplit("@", maxsplit=1)
|
||||
except ValueError:
|
||||
if not self.unexpected_cache_files_logged:
|
||||
logger.warning("Skipping unexpected files in cache")
|
||||
self.unexpected_cache_files_logged = True
|
||||
continue
|
||||
camera, date = basename.rsplit("@", maxsplit=1)
|
||||
|
||||
# important that start_time is utc because recordings are stored and compared in utc
|
||||
start_time = datetime.datetime.strptime(
|
||||
|
||||
@ -1,66 +0,0 @@
|
||||
import sys
|
||||
import unittest
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
# Mock complex imports before importing maintainer
|
||||
sys.modules["frigate.comms.inter_process"] = MagicMock()
|
||||
sys.modules["frigate.comms.detections_updater"] = MagicMock()
|
||||
sys.modules["frigate.comms.recordings_updater"] = MagicMock()
|
||||
sys.modules["frigate.config.camera.updater"] = MagicMock()
|
||||
|
||||
# Now import the class under test
|
||||
from frigate.config import FrigateConfig # noqa: E402
|
||||
from frigate.record.maintainer import RecordingMaintainer # noqa: E402
|
||||
|
||||
|
||||
class TestMaintainer(unittest.IsolatedAsyncioTestCase):
|
||||
async def test_move_files_survives_bad_filename(self):
|
||||
config = MagicMock(spec=FrigateConfig)
|
||||
config.cameras = {}
|
||||
stop_event = MagicMock()
|
||||
|
||||
maintainer = RecordingMaintainer(config, stop_event)
|
||||
|
||||
# We need to mock end_time_cache to avoid key errors if logic proceeds
|
||||
maintainer.end_time_cache = {}
|
||||
|
||||
# Mock filesystem
|
||||
# One bad file, one good file
|
||||
files = ["bad_filename.mp4", "camera@20210101000000+0000.mp4"]
|
||||
|
||||
with patch("os.listdir", return_value=files):
|
||||
with patch("os.path.isfile", return_value=True):
|
||||
with patch(
|
||||
"frigate.record.maintainer.psutil.process_iter", return_value=[]
|
||||
):
|
||||
with patch("frigate.record.maintainer.logger.warning") as warn:
|
||||
# Mock validate_and_move_segment to avoid further logic
|
||||
maintainer.validate_and_move_segment = MagicMock()
|
||||
|
||||
try:
|
||||
await maintainer.move_files()
|
||||
except ValueError as e:
|
||||
if "not enough values to unpack" in str(e):
|
||||
self.fail("move_files() crashed on bad filename!")
|
||||
raise e
|
||||
except Exception:
|
||||
# Ignore other errors (like DB connection) as we only care about the unpack crash
|
||||
pass
|
||||
|
||||
# The bad filename is encountered in multiple loops, but should only warn once.
|
||||
matching = [
|
||||
c
|
||||
for c in warn.call_args_list
|
||||
if c.args
|
||||
and isinstance(c.args[0], str)
|
||||
and "Skipping unexpected files in cache" in c.args[0]
|
||||
]
|
||||
self.assertEqual(
|
||||
1,
|
||||
len(matching),
|
||||
f"Expected a single warning for unexpected files, got {len(matching)}",
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@ -1,11 +1 @@
|
||||
{
|
||||
"documentTitle": "Luokittelumallit - Frigate",
|
||||
"details": {
|
||||
"scoreInfo": "Pistemäärä edustaa tämän objektin kaikkien havaintojen keskimääräistä luokitteluvarmuutta.",
|
||||
"none": "Ei mitään"
|
||||
},
|
||||
"button": {
|
||||
"deleteImages": "Poista kuvat",
|
||||
"trainModel": "Kouluta malli"
|
||||
}
|
||||
}
|
||||
{}
|
||||
|
||||
@ -13,8 +13,5 @@
|
||||
"title": "Nimeä uudelleen",
|
||||
"desc": "Anna uusi nimi viedylle kohteelle.",
|
||||
"saveExport": "Tallenna vienti"
|
||||
},
|
||||
"tooltip": {
|
||||
"editName": "Muokkaa nimeä"
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,8 +10,7 @@
|
||||
"object": "Virheenjäljitys - Frigate",
|
||||
"authentication": "Autentikointiuasetukset - Frigate",
|
||||
"notifications": "Ilmoitusasetukset - Frigate",
|
||||
"enrichments": "Laajennusasetukset – Frigate",
|
||||
"cameraManagement": "Hallitse Kameroita - Frigate"
|
||||
"enrichments": "Laajennusasetukset – Frigate"
|
||||
},
|
||||
"menu": {
|
||||
"ui": "Käyttöliittymä",
|
||||
|
||||
@ -41,14 +41,5 @@
|
||||
"snort": "Шмркање",
|
||||
"cough": "Кашаљ",
|
||||
"throat_clearing": "Прочишћавање грла",
|
||||
"sneeze": "Кијање",
|
||||
"sniff": "Њушкање",
|
||||
"run": "Трчање",
|
||||
"shuffle": "Насумично",
|
||||
"footsteps": "Корачање",
|
||||
"chewing": "Жвакање",
|
||||
"biting": "Угриз",
|
||||
"gargling": "Гргорење",
|
||||
"stomach_rumble": "Крчање стомака",
|
||||
"camera": "Камера"
|
||||
"sneeze": "Кијање"
|
||||
}
|
||||
|
||||
@ -38,14 +38,7 @@
|
||||
"hour_one": "{{time}} сат",
|
||||
"hour_few": "{{time}} сата",
|
||||
"hour_other": "{{time}} сати",
|
||||
"m": "{{time}}m",
|
||||
"minute_one": "{{time}} минут",
|
||||
"minute_few": "{{time}} минута",
|
||||
"minute_other": "{{time}} минута",
|
||||
"s": "{{time}}s",
|
||||
"second_one": "{{time}} секунда",
|
||||
"second_few": "{{time}} секунде",
|
||||
"second_other": "{{time}} секунди"
|
||||
"m": "{{time}}m"
|
||||
},
|
||||
"readTheDocumentation": "Прочитајте документацију"
|
||||
}
|
||||
|
||||
@ -52,28 +52,10 @@
|
||||
"smartStreaming": {
|
||||
"label": "Паметан стриминг (препоручено)",
|
||||
"desc": "Паметан стриминг ће ажурирати слике камере једном у минуту, када нема детектоване активности, да би се уштедело на мрежном саобраћају и ресурсима. Када је детектована активност, слика ће аутоматски прећи на стриминг уживо."
|
||||
},
|
||||
"continuousStreaming": {
|
||||
"label": "Непрекидно стримовање",
|
||||
"desc": {
|
||||
"title": "Слика камере ће увек бити стрим уживо када је видљива на контролној табли, чак и када активност није детектована.",
|
||||
"warning": "Непрекидно стримовање може проузроковати високу употребу мрежу и проблеме са перформансама. Користити опрезно."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"compatibilityMode": {
|
||||
"label": "Режим компатибилности",
|
||||
"desc": "Омогућите ову опцију само ако репродукција стрима уживо на камери приказује обојене артифекте и има дијагоналну линију на десној страни слице."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"options": {
|
||||
"label": "Подешавања",
|
||||
"title": "Опције",
|
||||
"showOptions": "Приказ опција"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,25 +65,5 @@
|
||||
"saveExport": "Чување извоза",
|
||||
"previewExport": "Преглед извоза"
|
||||
}
|
||||
},
|
||||
"streaming": {
|
||||
"label": "Стрим",
|
||||
"restreaming": {
|
||||
"disabled": "Поновни стриминг није омогућен за ову камеру.",
|
||||
"desc": {
|
||||
"title": "Подесите go2rtc за додатне опције репродукције слике и звука уживо за ову камеру."
|
||||
}
|
||||
},
|
||||
"showStats": {
|
||||
"label": "Приказ статистике стримовања",
|
||||
"desc": "Омогућите ову опцију за приказ статистике стримовања као надслој на преноса са камере."
|
||||
},
|
||||
"debugView": "Приказ за дебаговање"
|
||||
},
|
||||
"search": {
|
||||
"saveSearch": {
|
||||
"label": "Сачувати претрагу",
|
||||
"desc": "Обезбедите назив за ову сачувану претрагу."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,12 +29,5 @@
|
||||
"shoe": "Ципела",
|
||||
"eye_glasses": "Наочаре",
|
||||
"handbag": "Ручна торба",
|
||||
"tie": "Кравата",
|
||||
"suitcase": "Актовка",
|
||||
"frisbee": "Фризби",
|
||||
"skis": "Скије",
|
||||
"snowboard": "Сноуборд",
|
||||
"sports_ball": "Спортска лопта",
|
||||
"baseball_bat": "Палица за бејзбол",
|
||||
"baseball_glove": "Рукавица за бејзбол"
|
||||
"tie": "Кравата"
|
||||
}
|
||||
|
||||
@ -40,22 +40,10 @@
|
||||
"deleteModelFailed": "Неуспешно брисање модела: {{errorMessage}}",
|
||||
"categorizeFailed": "Неуспешна категоризација слике: {{errorMessage}}",
|
||||
"trainingFailed": "Неуспешно тренирање модела. Проверите Фригејт логове за детаље.",
|
||||
"trainingFailedToStart": "Неуспешан почетак тренирања модела: {{errorMessage}}",
|
||||
"updateModelFailed": "Неуспешно ажурирање модела: {{errorMessage}}",
|
||||
"renameCategoryFailed": "Неуспешно преименовање класе: {{errorMessage}}"
|
||||
"trainingFailedToStart": "Неуспешан почетак тренирања модела: {{errorMessage}}"
|
||||
}
|
||||
},
|
||||
"train": {
|
||||
"titleShort": "Скорашње"
|
||||
},
|
||||
"deleteCategory": {
|
||||
"title": "Брисање класе",
|
||||
"desc": "Да ли сте сигурни да желите да обришете класу {{name}}? Тиме ће трајно бити обрисане и све придружене слике и биће потребно поновно тренирање модела.",
|
||||
"minClassesTitle": "Није могуће обрисати класу",
|
||||
"minClassesDesc": "Класификациони модел мора имати најмање две класе. Додајте нову класу пре него што избришете ову."
|
||||
},
|
||||
"deleteModel": {
|
||||
"title": "Брисање класификационог модела",
|
||||
"single": "Да ли сте сигурни да желите да обришете {{name}}? Ово ће трајно обрисати све повезане податке, укључујући слике и податке за тренирање. Ова акција се не може накнадно опозвати."
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,15 +47,5 @@
|
||||
},
|
||||
"calendarFilter": {
|
||||
"last24Hours": "Последња 24 часа"
|
||||
},
|
||||
"markAsReviewed": "Означавање да је прегледано",
|
||||
"markTheseItemsAsReviewed": "Означи ове ставке као прегледане",
|
||||
"newReviewItems": {
|
||||
"label": "Приказ нових ставки за прегледање",
|
||||
"button": "Нове ставке за преглед"
|
||||
},
|
||||
"selected_one": "{{count}} изабрано",
|
||||
"selected_other": "{{count}} изабрано",
|
||||
"select_all": "Све",
|
||||
"camera": "Камера"
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,18 +46,6 @@
|
||||
"createObjectMask": "Креирање маске објекта",
|
||||
"adjustAnnotationSettings": "Прилагођавање подешавања анотације",
|
||||
"scrollViewTips": "Кликните да видите значајне моменте у животном циклусу овог објекта.",
|
||||
"autoTrackingTips": "Позиције оквира неће бити тачне за камере са аутоматским праћењем.",
|
||||
"count": "{{first}} од {{second}}",
|
||||
"trackedPoint": "Праћена тачка",
|
||||
"lifecycleItemDesc": {
|
||||
"visible": "{{label}} детектован",
|
||||
"entered_zone": "{{label}} је ушао у {{zones}}",
|
||||
"active": "{{label}} се активирао",
|
||||
"stationary": "{{label}} је постао стационаран",
|
||||
"attribute": {
|
||||
"faceOrLicense_plate": "{{attribute}} детектован за {{label}}",
|
||||
"other": "{{label}} је препознат као {{attribute}}"
|
||||
}
|
||||
}
|
||||
"autoTrackingTips": "Позиције оквира неће бити тачне за камере са аутоматским праћењем."
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,18 +56,6 @@
|
||||
"addFace": "Додавање лица",
|
||||
"renameFace": "Преименовање лица",
|
||||
"deleteFace": "Брисање лица",
|
||||
"uploadImage": "Отпремање слике",
|
||||
"reprocessFace": "Поново обради лице"
|
||||
},
|
||||
"imageEntry": {
|
||||
"validation": {
|
||||
"selectImage": "Изаберите фајл са сликом."
|
||||
},
|
||||
"dropActive": "Превуците слику овде…",
|
||||
"dropInstructions": "Превуците или пејстујте слику овде, или кликните за избор",
|
||||
"maxSize": "Максимална величина: {{size}}MB"
|
||||
},
|
||||
"nofaces": "Нема доступних лица",
|
||||
"trainFaceAs": "Тренирање лица као:",
|
||||
"trainFace": "Тренирање лица"
|
||||
"uploadImage": "Отпремање слике"
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,22 +72,5 @@
|
||||
"snapshots": {
|
||||
"enable": "Укључивање снепшотова",
|
||||
"disable": "Онемогућивање снепшотова"
|
||||
},
|
||||
"snapshot": {
|
||||
"takeSnapshot": "Преузимање тренутног снимка",
|
||||
"noVideoSource": "Нема доступних извора за снепшот.",
|
||||
"captureFailed": "Неуспешно прављење снепшота.",
|
||||
"downloadStarted": "Преузимање снепшота је започето."
|
||||
},
|
||||
"audioDetect": {
|
||||
"enable": "Омогућавање детектовања звука",
|
||||
"disable": "Онемогућавање детекције звука"
|
||||
},
|
||||
"transcription": {
|
||||
"enable": "Омогућавање транскрибовања звука уживо",
|
||||
"disable": "Искључивање транскрибовања звука уживо"
|
||||
},
|
||||
"autotracking": {
|
||||
"enable": "Омогућавање аутоматског праћења"
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,19 +38,7 @@
|
||||
"beforeDateBeLaterAfter": "Датум 'пре' мора бити након датума 'после'.",
|
||||
"afterDatebeEarlierBefore": "Датум 'после' мора бити пре датума 'пре'.",
|
||||
"minScoreMustBeLessOrEqualMaxScore": "'min_score' мора бити нижи или један 'max_score'.",
|
||||
"maxScoreMustBeGreaterOrEqualMinScore": "'max_score' мора бити већи или једнак од 'min_score'.",
|
||||
"minSpeedMustBeLessOrEqualMaxSpeed": "'min_speed' мора бити мања или једнака 'max_speed'.",
|
||||
"maxSpeedMustBeGreaterOrEqualMinSpeed": "'max_speed' мора бити већа или једнака 'min_speed'."
|
||||
}
|
||||
},
|
||||
"tips": {
|
||||
"title": "Како да се користе филтери за текст",
|
||||
"desc": {
|
||||
"text": "Филтери Вам помажу да сузите резултате претраге. Ево како да их користите у пољима за унос:",
|
||||
"step1": "Откуцајте назив кључа филтера а затим две тачке (нпр. \"cameras:\").",
|
||||
"step2": "Изаберите предложену или сопствену вредност.",
|
||||
"step3": "Примените више филтера тако што ћете их додати један за другим са размаком између.",
|
||||
"step4": "Филтери за датум (пре: и касније:) користе {{DateFormat}} формат."
|
||||
"maxScoreMustBeGreaterOrEqualMinScore": "'max_score' мора бити већи или једнак од 'min_score'."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,21 +44,7 @@
|
||||
"automaticLiveView": {
|
||||
"label": "Аутоматси преглед уживо",
|
||||
"desc": "Аутоматско пребацивање на преглед камере уживо када је активност детектована. Онемогућавање ове опције доводи до тога да се слике камере на контролној тапли ажурирају једном у минуту."
|
||||
},
|
||||
"playAlertVideos": {
|
||||
"label": "Репродукуј видео за узбуну",
|
||||
"desc": "Скорашњa упозорења се на контролној табли подразумевано репродукују као мали видеи који се понављају. Онемогућите ову опцију за приказивање само статичке слике скорашњих упозорења (на овом уређају/браузеру)."
|
||||
},
|
||||
"displayCameraNames": {
|
||||
"label": "Увек приказивати називе камера",
|
||||
"desc": "Увек приказивати називе камера у чипу у репродукцији уживо више камера на контролној табли."
|
||||
},
|
||||
"liveFallbackTimeout": {
|
||||
"desc": "Када стрим високог квалитета није доступан за камеру, спусти се на режим споре мреже након оволико секунди. Подразумевано 3."
|
||||
}
|
||||
},
|
||||
"storedLayouts": {
|
||||
"title": "Сачувани распореди"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,21 +48,7 @@
|
||||
"hardwareInfo": {
|
||||
"title": "Информације о хардверу",
|
||||
"gpuUsage": "Употреба GPU",
|
||||
"gpuMemory": "GPU меморија",
|
||||
"gpuEncoder": "GPU енкодер",
|
||||
"gpuDecoder": "GPU декодер",
|
||||
"gpuInfo": {
|
||||
"vainfoOutput": {
|
||||
"title": "Vainfo Output",
|
||||
"returnCode": "Повратни код: {{code}}",
|
||||
"processOutput": "Обрада излаза:",
|
||||
"processError": "Грешка у обради:"
|
||||
},
|
||||
"nvidiaSMIOutput": {
|
||||
"title": "Nvidia SMI излаз",
|
||||
"name": "Назив: {{name}}"
|
||||
}
|
||||
}
|
||||
"gpuMemory": "GPU меморија"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user