From 326a46b31bbf319c525770b5f685e390cd0c9337 Mon Sep 17 00:00:00 2001 From: SeydX Date: Sun, 16 Jan 2022 06:27:52 +0100 Subject: [PATCH] v1.0.8 --- CHANGELOG.md | 16 +- LICENSE | 2 +- package-lock.json | 156 +++++------------- package.json | 8 +- src/api/database.js | 18 +- src/common/ffmpeg.js | 28 +++- src/common/telegram.js | 3 +- .../camera/services/media.service.js | 2 +- .../camera/services/prebuffer.service.js | 7 +- .../camera/services/stream.service.js | 7 +- .../camera/services/videoanalysis.service.js | 46 ++++-- src/controller/event/event.controller.js | 6 +- src/controller/motion/motion.controller.js | 23 ++- ui/package-lock.json | 14 +- ui/package.json | 2 +- ui/src/i18n/locale/de.json | 2 + ui/src/i18n/locale/en.json | 2 + ui/src/i18n/locale/nl.json | 2 + ui/src/views/Settings/subpages/cameras.vue | 8 + 19 files changed, 179 insertions(+), 173 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c6a3519..4388df19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,18 @@ # Changelog All notable changes to this project will be documented in this file. +# v1.0.8 - 2022-01-16 + +## Other Changes +- Videoanalysis: Using a default zone if none was created +- Videoanalysis: Increases default sensitivity +- Telegram: Stop Telegram bot after message is send +- Added new Translations +- Bump dependencies + +## Bugfixes +- Minor bugfixes + # v1.0.7 - 2022-01-15 ## Other Changes @@ -16,7 +28,7 @@ All notable changes to this project will be documented in this file. - Fixed an isue where crashing FFmpeg did not display an error message in the log - Fixed an issue where the dwell time could start before the motion handler was initialized - Fixed an issue where the restart timer for prebuffering and videoanalysis were calculated wrong -- Minor Bugfixes +- Minor bugfixes # v1.0.6 - 2022-01-14 @@ -44,7 +56,7 @@ All notable changes to this project will be documented in this file. - Fixed an issue where resetting motion via MQTT didnt work - Fixed an issue where the video analysis sensitivity does not work as desired - Fixed an issue where mapping video/audio stream didnt work (ffmpeg) -- Minor Bugfixes +- Minor bugfixes # [1.0.4] - 2022-01-11 diff --git a/LICENSE b/LICENSE index 31b16781..4f955fcd 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020-2022 seydx +Copyright (c) 2020-2022 seydx Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/package-lock.json b/package-lock.json index de28ee81..84eda387 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "camera.ui", - "version": "1.0.7", + "version": "1.0.8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "camera.ui", - "version": "1.0.7", + "version": "1.0.8", "funding": [ { "type": "paypal", @@ -60,7 +60,7 @@ "swagger-ui-express": "4.1.6", "systeminformation": "^5.10.0", "tar": "^6.1.11", - "telegraf": "^4.5.2", + "telegraf": "^4.6.0", "web-push": "^3.4.5" }, "bin": { @@ -71,10 +71,10 @@ "@babel/eslint-parser": "7.16.5", "@babel/eslint-plugin": "7.16.5", "concurrently": "6.5.1", - "eslint": "^8.6.0", + "eslint": "^8.7.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-import": "^2.25.4", - "eslint-plugin-jest": "^25.3.4", + "eslint-plugin-jest": "^25.7.0", "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-unicorn": "^40.0.0", "jest": "^27.4.7", @@ -2554,15 +2554,6 @@ "string-width": "^4.1.0" } }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -4078,18 +4069,6 @@ } } }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, "node_modules/entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", @@ -4286,9 +4265,9 @@ } }, "node_modules/eslint": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.6.0.tgz", - "integrity": "sha512-UvxdOJ7mXFlw7iuHZA4jmzPaUqIw54mZrv+XPYKNbKdLR0et4rf60lIZUU9kiNtnzzMzGWxMV+tQ7uG7JG8DPw==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.7.0.tgz", + "integrity": "sha512-ifHYzkBGrzS2iDU7KjhCAVMGCvF6M3Xfs8X8b37cgrUlDt6bWRTpRh6T/gtSXv1HJ/BUGgmjvNvOEGu85Iif7w==", "dev": true, "dependencies": { "@eslint/eslintrc": "^1.0.5", @@ -4298,11 +4277,10 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", - "enquirer": "^2.3.5", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.1.0", "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.1.0", + "eslint-visitor-keys": "^3.2.0", "espree": "^9.3.0", "esquery": "^1.4.0", "esutils": "^2.0.2", @@ -4311,7 +4289,7 @@ "functional-red-black-tree": "^1.0.1", "glob-parent": "^6.0.1", "globals": "^13.6.0", - "ignore": "^4.0.6", + "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", @@ -4322,9 +4300,7 @@ "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "progress": "^2.0.0", "regexpp": "^3.2.0", - "semver": "^7.2.1", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0", @@ -4448,9 +4424,9 @@ "dev": true }, "node_modules/eslint-plugin-jest": { - "version": "25.3.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.3.4.tgz", - "integrity": "sha512-CCnwG71wvabmwq/qkz0HWIqBHQxw6pXB1uqt24dxqJ9WB34pVg49bL1sjXphlJHgTMWGhBjN1PicdyxDxrfP5A==", + "version": "25.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz", + "integrity": "sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==", "dev": true, "dependencies": { "@typescript-eslint/experimental-utils": "^5.0.0" @@ -4601,9 +4577,9 @@ } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", - "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz", + "integrity": "sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -4633,19 +4609,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "node_modules/eslint/node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, "engines": { - "node": ">=10" + "node": ">= 4" } }, "node_modules/eslint/node_modules/type-fest": { @@ -8744,15 +8714,6 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -10103,9 +10064,9 @@ } }, "node_modules/telegraf": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/telegraf/-/telegraf-4.5.2.tgz", - "integrity": "sha512-OG68wQqYQQq2ldzAMv6JJUkh9XU+4mWRgHinMeJ8FoRA5ZZuA4WauqRFi8aY/OQiwJM2gTT2XWCfopN2dZWDNw==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/telegraf/-/telegraf-4.6.0.tgz", + "integrity": "sha512-77JqMIyEd8jN5meTp6F50ILVsqxMaVplbDZtGNfJhVr75ZsnClLYt+z3p61cOcACaPIlgOtqzQwN0wtjVjdiCg==", "dependencies": { "abort-controller": "^3.0.0", "debug": "^4.3.3", @@ -10115,7 +10076,7 @@ "p-timeout": "^4.1.0", "safe-compare": "^1.1.4", "sandwich-stream": "^2.0.2", - "typegram": "^3.6.1" + "typegram": "^3.7.0" }, "bin": { "telegraf": "bin/telegraf" @@ -12900,12 +12861,6 @@ "string-width": "^4.1.0" } }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, "ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -14053,15 +14008,6 @@ "base64-arraybuffer": "~1.0.1" } }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - } - }, "entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", @@ -14206,9 +14152,9 @@ } }, "eslint": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.6.0.tgz", - "integrity": "sha512-UvxdOJ7mXFlw7iuHZA4jmzPaUqIw54mZrv+XPYKNbKdLR0et4rf60lIZUU9kiNtnzzMzGWxMV+tQ7uG7JG8DPw==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.7.0.tgz", + "integrity": "sha512-ifHYzkBGrzS2iDU7KjhCAVMGCvF6M3Xfs8X8b37cgrUlDt6bWRTpRh6T/gtSXv1HJ/BUGgmjvNvOEGu85Iif7w==", "dev": true, "requires": { "@eslint/eslintrc": "^1.0.5", @@ -14218,11 +14164,10 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", - "enquirer": "^2.3.5", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.1.0", "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.1.0", + "eslint-visitor-keys": "^3.2.0", "espree": "^9.3.0", "esquery": "^1.4.0", "esutils": "^2.0.2", @@ -14231,7 +14176,7 @@ "functional-red-black-tree": "^1.0.1", "glob-parent": "^6.0.1", "globals": "^13.6.0", - "ignore": "^4.0.6", + "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", @@ -14242,9 +14187,7 @@ "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "progress": "^2.0.0", "regexpp": "^3.2.0", - "semver": "^7.2.1", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0", @@ -14262,9 +14205,9 @@ } }, "eslint-visitor-keys": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", - "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz", + "integrity": "sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==", "dev": true }, "estraverse": { @@ -14282,14 +14225,11 @@ "type-fest": "^0.20.2" } }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true }, "type-fest": { "version": "0.20.2", @@ -14396,9 +14336,9 @@ } }, "eslint-plugin-jest": { - "version": "25.3.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.3.4.tgz", - "integrity": "sha512-CCnwG71wvabmwq/qkz0HWIqBHQxw6pXB1uqt24dxqJ9WB34pVg49bL1sjXphlJHgTMWGhBjN1PicdyxDxrfP5A==", + "version": "25.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz", + "integrity": "sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==", "dev": true, "requires": { "@typescript-eslint/experimental-utils": "^5.0.0" @@ -17561,12 +17501,6 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, "prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -18588,9 +18522,9 @@ } }, "telegraf": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/telegraf/-/telegraf-4.5.2.tgz", - "integrity": "sha512-OG68wQqYQQq2ldzAMv6JJUkh9XU+4mWRgHinMeJ8FoRA5ZZuA4WauqRFi8aY/OQiwJM2gTT2XWCfopN2dZWDNw==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/telegraf/-/telegraf-4.6.0.tgz", + "integrity": "sha512-77JqMIyEd8jN5meTp6F50ILVsqxMaVplbDZtGNfJhVr75ZsnClLYt+z3p61cOcACaPIlgOtqzQwN0wtjVjdiCg==", "requires": { "abort-controller": "^3.0.0", "debug": "^4.3.3", @@ -18600,7 +18534,7 @@ "p-timeout": "^4.1.0", "safe-compare": "^1.1.4", "sandwich-stream": "^2.0.2", - "typegram": "^3.6.1" + "typegram": "^3.7.0" } }, "terminal-link": { diff --git a/package.json b/package.json index 1a971bf8..2ba9b323 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "camera.ui", - "version": "1.0.7", + "version": "1.0.8", "description": "User Interface for RTSP capable cameras.", "author": "SeydX (https://github.com/SeydX/camera.ui)", "scripts": { @@ -53,7 +53,7 @@ "swagger-jsdoc": "^6.1.0", "swagger-ui-express": "4.1.6", "tar": "^6.1.11", - "telegraf": "^4.5.2", + "telegraf": "^4.6.0", "web-push": "^3.4.5" }, "devDependencies": { @@ -61,10 +61,10 @@ "@babel/eslint-parser": "7.16.5", "@babel/eslint-plugin": "7.16.5", "concurrently": "6.5.1", - "eslint": "^8.6.0", + "eslint": "^8.7.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-import": "^2.25.4", - "eslint-plugin-jest": "^25.3.4", + "eslint-plugin-jest": "^25.7.0", "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-unicorn": "^40.0.0", "jest": "^27.4.7", diff --git a/src/api/database.js b/src/api/database.js index cbff3551..f0d964b3 100644 --- a/src/api/database.js +++ b/src/api/database.js @@ -138,9 +138,19 @@ const defaultCameraSettingsEntry = { labels: [], }, videoanalysis: { - sensitivity: 25, - difference: 9, - regions: [], + sensitivity: 75, + difference: 5, + regions: [ + { + finished: true, + coords: [ + [0, 100], + [0, 0], + [100, 0], + [100, 100], + ], + }, + ], }, }; @@ -518,7 +528,7 @@ class Database { settings.videoanalysis.sensitivity = defaultCameraSettingsEntry.videoanalysis.sensitivity; } - if (!Array.isArray(settings.videoanalysis.regions)) { + if (!Array.isArray(settings.videoanalysis.regions) || !settings.videoanalysis.regions?.length) { settings.videoanalysis.regions = defaultCameraSettingsEntry.videoanalysis.regions; } diff --git a/src/common/ffmpeg.js b/src/common/ffmpeg.js index 5d9d9700..8623b25f 100644 --- a/src/common/ffmpeg.js +++ b/src/common/ffmpeg.js @@ -77,9 +77,12 @@ const storeFrameFromVideoBuffer = function (camera, fileBuffer, outputPath) { const ffmpeg = spawn(videoProcessor, ffmpegArguments, { env: process.env }); - const errors = []; + let errors = []; - ffmpeg.stderr.on('data', (data) => errors.push(data.toString().replace(/(\r\n|\n|\r)/gm, ''))); + ffmpeg.stderr.on('data', (data) => { + errors = errors.slice(-5); + errors.push(data.toString().replace(/(\r\n|\n|\r)/gm, '')); + }); ffmpeg.on('error', (error) => reject(error)); @@ -181,9 +184,12 @@ exports.getAndStoreSnapshot = function (camera, recordingPath, fileName, label, const ffmpeg = spawn(videoProcessor, ffmpegArguments, { env: process.env }); - const errors = []; + let errors = []; - ffmpeg.stderr.on('data', (data) => errors.push(data.toString().replace(/(\r\n|\n|\r)/gm, ''))); + ffmpeg.stderr.on('data', (data) => { + errors = errors.slice(-5); + errors.push(data.toString().replace(/(\r\n|\n|\r)/gm, '')); + }); let imageBuffer = Buffer.alloc(0); @@ -247,9 +253,12 @@ exports.storeSnapshotFromVideo = async function (camera, recordingPath, fileName const ffmpeg = spawn(videoProcessor, ffmpegArguments, { env: process.env }); - const errors = []; + let errors = []; - ffmpeg.stderr.on('data', (data) => errors.push(data.toString().replace(/(\r\n|\n|\r)/gm, ''))); + ffmpeg.stderr.on('data', (data) => { + errors = errors.slice(-5); + errors.push(data.toString().replace(/(\r\n|\n|\r)/gm, '')); + }); ffmpeg.on('error', (error) => reject(error)); @@ -331,9 +340,12 @@ exports.storeVideo = function (camera, recordingPath, fileName, recordingTimer) const ffmpeg = spawn(videoProcessor, ffmpegArguments, { env: process.env }); - const errors = []; + let errors = []; - ffmpeg.stderr.on('data', (data) => errors.push(data.toString().replace(/(\r\n|\n|\r)/gm, ''))); + ffmpeg.stderr.on('data', (data) => { + errors = errors.slice(-5); + errors.push(data.toString().replace(/(\r\n|\n|\r)/gm, '')); + }); ffmpeg.on('error', (error) => reject(error)); diff --git a/src/common/telegram.js b/src/common/telegram.js index 56527c66..db7cd8c6 100644 --- a/src/common/telegram.js +++ b/src/common/telegram.js @@ -7,7 +7,7 @@ const { LoggerService } = require('../services/logger/logger.service'); const { log } = LoggerService; class Telegram { - static bot; + static bot = null; constructor() {} @@ -43,6 +43,7 @@ class Telegram { if (Telegram.bot) { log.debug('Stopping Telegram...'); await Telegram.bot.stop(); + Telegram.bot = null; } } diff --git a/src/controller/camera/services/media.service.js b/src/controller/camera/services/media.service.js index b2003ce9..8db48ca2 100644 --- a/src/controller/camera/services/media.service.js +++ b/src/controller/camera/services/media.service.js @@ -96,7 +96,7 @@ class MediaService { this.codecs.timedout = true; cp.kill('SIGKILL'); } - }, 8000); + }, 5000); }); } } diff --git a/src/controller/camera/services/prebuffer.service.js b/src/controller/camera/services/prebuffer.service.js index b70c689b..af2f01e1 100644 --- a/src/controller/camera/services/prebuffer.service.js +++ b/src/controller/camera/services/prebuffer.service.js @@ -550,13 +550,16 @@ class PrebufferService { this.cameraName ); - const errors = []; + let errors = []; const cp = spawn(ConfigService.ui.options.videoProcessor, arguments_, { env: process.env, }); - cp.stderr.on('data', (data) => errors.push(data.toString().replace(/(\r\n|\n|\r)/gm, ''))); + cp.stderr.on('data', (data) => { + errors = errors.slice(-5); + errors.push(data.toString().replace(/(\r\n|\n|\r)/gm, '')); + }); cp.on('exit', (code, signal) => { if (code === 1 || (!this.killed && errors.length > 0)) { diff --git a/src/controller/camera/services/stream.service.js b/src/controller/camera/services/stream.service.js index efb1dca6..125680a9 100644 --- a/src/controller/camera/services/stream.service.js +++ b/src/controller/camera/services/stream.service.js @@ -148,13 +148,16 @@ class StreamService { env: process.env, }); - const errors = []; + let errors = []; this.streamSession.stdout.on('data', (data) => { this.#socket.to(`stream/${this.cameraName}`).emit(this.cameraName, data); }); - this.streamSession.stderr.on('data', (data) => errors.push(data.toString().replace(/(\r\n|\n|\r)/gm, ''))); + this.streamSession.stderr.on('data', (data) => { + errors = errors.slice(-5); + errors.push(data.toString().replace(/(\r\n|\n|\r)/gm, '')); + }); this.streamSession.on('exit', (code, signal) => { if (code === 1) { diff --git a/src/controller/camera/services/videoanalysis.service.js b/src/controller/camera/services/videoanalysis.service.js index 2cf8af5e..2af4c648 100644 --- a/src/controller/camera/services/videoanalysis.service.js +++ b/src/controller/camera/services/videoanalysis.service.js @@ -23,10 +23,21 @@ const isUINT = (value) => Number.isInteger(value) && value >= 0; const FFMPEG_MODE = 'rgb24'; // gray, rgba, rgb24 const FFMPEG_RESOLUTION = '640:360'; const FFMPEG_FPS = '2'; -const DEFAULT_DIFFERENCE = 9; // 1 - 255 -const DEFAULT_SENSITIVITY = 25; // 0 - 100 + const DWELL_TIME = 60 * 1000; +const DEFAULT_DIFFERENCE = 5; // 1 - 255 +const DEFAULT_SENSITIVITY = 75; // 0 - 100 +const DEFAULT_ZONE = { + finished: true, + coords: [ + [0, 100], + [0, 0], + [100, 0], + [100, 100], + ], +}; + class VideoAnalysisService { #camera; #controller; @@ -151,7 +162,7 @@ class VideoAnalysisService { } if (this.motionEventTimeout || this.forceCloseTimeout) { - this.#triggerMotion(false); + this.#triggerMotion(false, 'killed'); } if (this.restartTimer) { @@ -221,7 +232,7 @@ class VideoAnalysisService { this.cameraName ); - const errors = []; + let errors = []; const settings = await Database.interfaceDB.get('settings').get('cameras').find({ name: this.cameraName }).value(); @@ -268,24 +279,23 @@ class VideoAnalysisService { } if (!this.motionEventTimeout) { - log.debug(`Motion detected via Videoanalysis: ${JSON.stringify(data.trigger)}`, this.cameraName); - this.#triggerMotion(true); + this.#triggerMotion(true, 'pixelDifference'); // forceClose after 3min this.forceCloseTimeout = setTimeout(() => { - this.#triggerMotion(false); + this.#triggerMotion(false, 'forceClose'); }, 3 * 60 * 1000); } if (this.motionEventTimeout) { - log.debug('Resetted the dwell time because new movement detected, resetting motion in 60s..', this.cameraName); + log.debug('Dwell time resetted because new motion detected, resetting motion in 60s..', this.cameraName); clearTimeout(this.motionEventTimeout); this.motionEventTimeout = null; } this.motionEventTimeout = setTimeout(async () => { - this.#triggerMotion(false); + this.#triggerMotion(false, 'dwellTime'); }, DWELL_TIME); }); @@ -293,7 +303,10 @@ class VideoAnalysisService { env: process.env, }); - cp.stderr.on('data', (data) => errors.push(data.toString().replace(/(\r\n|\n|\r)/gm, ''))); + cp.stderr.on('data', (data) => { + errors = errors.slice(-5); + errors.push(data.toString().replace(/(\r\n|\n|\r)/gm, '')); + }); cp.on('exit', (code, signal) => { isActive = false; @@ -339,8 +352,11 @@ class VideoAnalysisService { }; } - async #triggerMotion(state) { - await MotionController.handleMotion('motion', this.cameraName, state, 'videoanalysis'); + async #triggerMotion(state, reason) { + log.debug( + `New message: Motion: ${state ? 'detected' : 'resetted'} - Reason: ${reason} - Camera: ${this.cameraName}`, + 'VIDEOANALYSIS' + ); if (!state) { if (this.forceCloseTimeout) { @@ -353,6 +369,8 @@ class VideoAnalysisService { this.motionEventTimeout = null; } } + + await MotionController.handleMotion('motion', this.cameraName, state, 'videoanalysis'); } #millisUntilTime(end = '04:00') { @@ -384,6 +402,10 @@ class VideoAnalysisService { const sens = sensitivity >= 0 && sensitivity <= 100 ? sensitivity : DEFAULT_SENSITIVITY; const percent = 100 - sens; + if (!zones?.length) { + zones = DEFAULT_ZONE; + } + const regions = zones ?.map((zone, index) => { if (zone.coords?.length > 2) { diff --git a/src/controller/event/event.controller.js b/src/controller/event/event.controller.js index 1f49fa50..b2d572a3 100644 --- a/src/controller/event/event.controller.js +++ b/src/controller/event/event.controller.js @@ -13,8 +13,6 @@ const { Telegram } = require('../../common/telegram'); const { LoggerService } = require('../../services/logger/logger.service'); -//const { CameraController } = require('../camera/camera.controller'); - const CamerasModel = require('../../api/components/cameras/cameras.model'); const NotificationsModel = require('../../api/components/notifications/notifications.model'); const RecordingsModel = require('../../api/components/recordings/recordings.model'); @@ -43,8 +41,6 @@ class EventController { // eslint-disable-next-line no-unused-vars static async handle(trigger, cameraName, active, fileBuffer, type) { if (active) { - //const controller = CameraController.cameras.get(cameraName); - try { let Camera, CameraSettings; @@ -546,6 +542,8 @@ class EventController { } catch (error) { log.info('An error occured during sending telegram notification', cameraName, 'events'); log.error(error, cameraName, 'events'); + } finally { + await Telegram.stop(); } } diff --git a/src/controller/motion/motion.controller.js b/src/controller/motion/motion.controller.js index 9f73b8c6..d8c3c25f 100644 --- a/src/controller/motion/motion.controller.js +++ b/src/controller/motion/motion.controller.js @@ -145,7 +145,7 @@ class MotionController { message: `Malformed URL ${request.url}`, }; - log.debug(request.url, 'HTTP'); + log.debug(`New message: URL: ${request.url}`, 'HTTP'); let cameraName; @@ -217,7 +217,7 @@ class MotionController { }); MotionController.mqttClient.on('message', async (topic, data) => { - log.debug(`${data.toString()} (${topic})`, 'MQTT'); + log.debug(`New message: Topic: ${topic} - Data: ${data.toString()}`, 'MQTT'); let cameraName; @@ -370,7 +370,7 @@ class MotionController { for (const rcptTo of session.envelope.rcptTo) { const name = rcptTo.address.split('@')[0].replace(regex, ' '); - log.debug(`Email received (${name}).`, 'SMTP'); + log.debug(`New message: Email Address: ${name}`, 'SMTP'); await MotionController.handleMotion('motion', name, true, 'smtp'); } @@ -493,7 +493,7 @@ class MotionController { if (pathSplit.length > 0) { const name = pathSplit[0]; - log.debug(`Receiving file. (${name}).`, 'FTP'); + log.debug(`New message: File Path: ${name}`, 'FTP'); await MotionController.handleMotion('motion', name, true, 'ftp'); } else { @@ -641,13 +641,10 @@ class MotionController { const recTimer = recordingSettings.timer || 10; const timeout = MotionController.#motionTimers.get(cameraName); - const timeoutConfig = recActive - ? camera.motionTimeout < recTimer - ? recTimer + 5 - : camera.motionTimeout - : camera.motionTimeout > 0 - ? camera.motionTimeout - : 1; + let timeoutConfig = + (recActive && camera.motionTimeout < recTimer) || camera.useInterfaceTimer + ? recTimer + : camera.motionTimeout; if (timeout) { if (state) { @@ -664,11 +661,11 @@ class MotionController { }); } } else { - if (state && timeoutConfig > 0) { + if (state) { const timer = setTimeout(() => { log.debug('Motion handler timeout. (ui)', cameraName); MotionController.#motionTimers.delete(cameraName); - }, timeoutConfig * 1000); + }, (timeoutConfig || 1) * 1000); MotionController.#motionTimers.set(cameraName, timer); } diff --git a/ui/package-lock.json b/ui/package-lock.json index c98f13b8..1f48ece4 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -47,7 +47,7 @@ "@vue/eslint-config-prettier": "6.0.0", "autoprefixer": "9.8.8", "babel-eslint": "^10.1.0", - "core-js": "^3.20.2", + "core-js": "^3.20.3", "eslint": "6.7.2", "eslint-plugin-prettier": "3.3.1", "eslint-plugin-vue": "6.2.2", @@ -5045,9 +5045,9 @@ } }, "node_modules/core-js": { - "version": "3.20.2", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.20.2.tgz", - "integrity": "sha512-nuqhq11DcOAbFBV4zCbKeGbKQsUDRqTX0oqx7AttUBuqe3h20ixsE039QHelbL6P4h+9kytVqyEtyZ6gsiwEYw==", + "version": "3.20.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.20.3.tgz", + "integrity": "sha512-vVl8j8ph6tRS3B8qir40H7yw7voy17xL0piAjlbBUsH7WIfzoedL/ZOr1OV9FyZQLWXsayOJyV4tnRyXR85/ag==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -21910,9 +21910,9 @@ } }, "core-js": { - "version": "3.20.2", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.20.2.tgz", - "integrity": "sha512-nuqhq11DcOAbFBV4zCbKeGbKQsUDRqTX0oqx7AttUBuqe3h20ixsE039QHelbL6P4h+9kytVqyEtyZ6gsiwEYw==" + "version": "3.20.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.20.3.tgz", + "integrity": "sha512-vVl8j8ph6tRS3B8qir40H7yw7voy17xL0piAjlbBUsH7WIfzoedL/ZOr1OV9FyZQLWXsayOJyV4tnRyXR85/ag==" }, "core-js-compat": { "version": "3.19.3", diff --git a/ui/package.json b/ui/package.json index 5a2173a9..e7a40f9a 100644 --- a/ui/package.json +++ b/ui/package.json @@ -47,7 +47,7 @@ "@vue/eslint-config-prettier": "6.0.0", "autoprefixer": "9.8.8", "babel-eslint": "^10.1.0", - "core-js": "^3.20.2", + "core-js": "^3.20.3", "eslint": "6.7.2", "eslint-plugin-prettier": "3.3.1", "eslint-plugin-vue": "6.2.2", diff --git a/ui/src/i18n/locale/de.json b/ui/src/i18n/locale/de.json index 4bc21e60..f5e10888 100644 --- a/ui/src/i18n/locale/de.json +++ b/ui/src/i18n/locale/de.json @@ -431,6 +431,8 @@ "update_or_downgrade": "Updaten/Downgraden", "upload_backup_archive": "Backup Archiv hochladen", "uptime": "Betriebszeit", + "use_interface_timer": "Interface Recording Timer", + "use_interface_timer_info": "If enabled, the recording timer from camera.ui will be used for \"motionTimeout\".", "user": "Benutzer", "user_list": "Benutzerliste", "username": "Benutzername", diff --git a/ui/src/i18n/locale/en.json b/ui/src/i18n/locale/en.json index d99954f8..276e3147 100644 --- a/ui/src/i18n/locale/en.json +++ b/ui/src/i18n/locale/en.json @@ -429,6 +429,8 @@ "update_or_downgrade": "Update/Downgrade", "upload_backup_archive": "Upload Backup Archive", "uptime": "Uptime", + "use_interface_timer": "Interface Recording Timer", + "use_interface_timer_info": "If enabled, the recording timer from camera.ui will be used for \"motionTimeout\".", "user": "User", "user_list": "User List", "username": "Username", diff --git a/ui/src/i18n/locale/nl.json b/ui/src/i18n/locale/nl.json index 249dcd9b..f51e4a16 100644 --- a/ui/src/i18n/locale/nl.json +++ b/ui/src/i18n/locale/nl.json @@ -429,6 +429,8 @@ "update_or_downgrade": "Bijwerken/Downgraden", "upload_backup_archive": "Back-up archief uploaden", "uptime": "Uptime", + "use_interface_timer": "Interface Recording Timer", + "use_interface_timer_info": "If enabled, the recording timer from camera.ui will be used for \"motionTimeout\".", "user": "Gebruiker", "user_list": "Gebruikerslijst", "username": "Gebruikersnaam", diff --git a/ui/src/views/Settings/subpages/cameras.vue b/ui/src/views/Settings/subpages/cameras.vue index 0c9655e9..7f972f22 100644 --- a/ui/src/views/Settings/subpages/cameras.vue +++ b/ui/src/views/Settings/subpages/cameras.vue @@ -310,6 +310,14 @@ v-icon.text-muted.tw-mr-1(small) {{ icons['mdiInformationOutline'] }} .input-info.tw-italic {{ $t('excludeSwitch_info') }} v-switch(color="var(--cui-primary)" v-model="cam.excludeSwitch") + + .tw-flex.tw-justify-between.tw-items-center + .tw-block.tw-w-full.tw-pr-2 + label.form-input-label Interface Recording Timer + .tw-flex.tw-flex-row.tw-items-center.tw-break-normal + v-icon.text-muted.tw-mr-1(small) {{ icons['mdiInformationOutline'] }} + .input-info.tw-italic {{ $t('use_interface_timer_info') }} + v-switch(color="var(--cui-primary)" v-model="cam.useInterfaceTimer") label.form-input-label *Manufacturer v-text-field(v-model="cam.manufacturer" :hint="$t('manufacturer_info')" persistent-hint prepend-inner-icon="mdi-alphabetical" background-color="var(--cui-bg-card)" color="var(--cui-text-default)" solo)