From 644d48b49c98959d432dddd7d38861649eac5008 Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Mon, 24 Jul 2023 22:17:05 -0700 Subject: [PATCH 01/20] PTZ using cover #921 --- app/wyzebridge/mqtt.py | 13 +++++++++++++ app/wyzecam/tutk/tutk_protocol.py | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/wyzebridge/mqtt.py b/app/wyzebridge/mqtt.py index a2ad5030..094f2bc4 100644 --- a/app/wyzebridge/mqtt.py +++ b/app/wyzebridge/mqtt.py @@ -350,6 +350,19 @@ def get_entities(base_topic: str, pan_cam: bool = False, rtsp: bool = False) -> "entity_category": "diagnostic", }, }, + "pan_tilt": { + "type": "cover", + "payload": { + "command_topic": f"{base_topic}rotary_degree/set", + "tilt_command_topic": f"{base_topic}rotary_degree/set", + "payload_open": "up", + "payload_close": "down", + "payload_stop": None, + "tilt_opened_value": 90, + "tilt_closed_value": -90, + "icon": "mdi:rotate-orbit", + }, + }, } if pan_cam: entities |= { diff --git a/app/wyzecam/tutk/tutk_protocol.py b/app/wyzecam/tutk/tutk_protocol.py index 6d4cd46a..7a1fe767 100644 --- a/app/wyzecam/tutk/tutk_protocol.py +++ b/app/wyzecam/tutk/tutk_protocol.py @@ -888,7 +888,7 @@ class K11000SetRotaryByDegree(TutkWyzeProtocolMessage): """ - def __init__(self, horizontal: int, vertical: int, speed: int = 5): + def __init__(self, horizontal: int, vertical: int = 0, speed: int = 5): super().__init__(11000) self.horizontal = horizontal self.vertical = vertical From b002d87efcb0bc3818e60b86bbedbd7ace34915d Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Mon, 24 Jul 2023 22:31:03 -0700 Subject: [PATCH 02/20] set min max for rotate button? #921 --- app/wyzebridge/mqtt.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/wyzebridge/mqtt.py b/app/wyzebridge/mqtt.py index 094f2bc4..524cfc35 100644 --- a/app/wyzebridge/mqtt.py +++ b/app/wyzebridge/mqtt.py @@ -360,6 +360,8 @@ def get_entities(base_topic: str, pan_cam: bool = False, rtsp: bool = False) -> "payload_stop": None, "tilt_opened_value": 90, "tilt_closed_value": -90, + "tilt_min": -90, + "tilt_max": 90, "icon": "mdi:rotate-orbit", }, }, From 90a47b814076ca9dc570a490f5f5aa0164328ce0 Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Mon, 24 Jul 2023 22:35:03 -0700 Subject: [PATCH 03/20] only show pan_tilt for pan_cam --- app/wyzebridge/mqtt.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/app/wyzebridge/mqtt.py b/app/wyzebridge/mqtt.py index 524cfc35..64e1fa8a 100644 --- a/app/wyzebridge/mqtt.py +++ b/app/wyzebridge/mqtt.py @@ -54,7 +54,7 @@ def publish_discovery(cam_uri: str, cam: WyzeCamera, stopped: bool = True) -> No } # Clear out old/renamed entities - REMOVE = {"alarm": "switch"} + REMOVE = {"alarm": "switch", "pan_tilt": "cover"} for entity, type in REMOVE.items(): msgs.append((f"{MQTT_DISCOVERY}/{type}/{cam.mac}/{entity}/config", None)) @@ -350,21 +350,6 @@ def get_entities(base_topic: str, pan_cam: bool = False, rtsp: bool = False) -> "entity_category": "diagnostic", }, }, - "pan_tilt": { - "type": "cover", - "payload": { - "command_topic": f"{base_topic}rotary_degree/set", - "tilt_command_topic": f"{base_topic}rotary_degree/set", - "payload_open": "up", - "payload_close": "down", - "payload_stop": None, - "tilt_opened_value": 90, - "tilt_closed_value": -90, - "tilt_min": -90, - "tilt_max": 90, - "icon": "mdi:rotate-orbit", - }, - }, } if pan_cam: entities |= { @@ -405,6 +390,21 @@ def get_entities(base_topic: str, pan_cam: bool = False, rtsp: bool = False) -> "icon": "mdi:map-marker-multiple", }, }, + "pan_tilt": { + "type": "cover", + "payload": { + "command_topic": f"{base_topic}rotary_degree/set", + "tilt_command_topic": f"{base_topic}rotary_degree/set", + "payload_open": "up", + "payload_close": "down", + "payload_stop": None, + "tilt_opened_value": 90, + "tilt_closed_value": -90, + "tilt_min": -90, + "tilt_max": 90, + "icon": "mdi:rotate-orbit", + }, + }, } if rtsp: entities |= { From 59fd72d045ce628189fd1030d15d0497b8303087 Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Thu, 27 Jul 2023 19:21:41 -0700 Subject: [PATCH 04/20] Add extra intel packages #736 --- app/Dockerfile.qsv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Dockerfile.qsv b/app/Dockerfile.qsv index d7098f60..920b736e 100644 --- a/app/Dockerfile.qsv +++ b/app/Dockerfile.qsv @@ -7,7 +7,7 @@ ARG QSV RUN if [ -n "$QSV" ]; then echo 'deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware' >/etc/apt/sources.list.d/debian-testing.list; fi \ && apt-get update \ && apt-get install -y curl tar xz-utils \ - ${QSV:+i965-va-driver-shaders intel-media-va-driver-non-free intel-opencl-icd libmfx1 libva-drm2 libx11-6} \ + ${QSV:+i965-va-driver intel-gpu-tools intel-media-va-driver-non-free intel-opencl-icd libmfx1 libva-drm2 libx11-6 vainfo && apt-get install i965-va-driver-shaders} \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* COPY . /build/app/ From d7de34cf522dba43650128cf781676e686e5cfdb Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Thu, 27 Jul 2023 19:28:19 -0700 Subject: [PATCH 05/20] Update Dockerfile.hwaccel --- app/Dockerfile.hwaccel | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Dockerfile.hwaccel b/app/Dockerfile.hwaccel index 43a368b5..94cdd771 100644 --- a/app/Dockerfile.hwaccel +++ b/app/Dockerfile.hwaccel @@ -8,7 +8,8 @@ ARG QSV RUN if [ -n "$QSV" ]; then echo 'deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware' >/etc/apt/sources.list.d/debian-testing.list; fi \ && apt-get update \ && apt-get install -y curl tar xz-utils \ - ${QSV:+i965-va-driver intel-media-va-driver-non-free libmfx1 libva-drm2 libx11-6 && apt-get install i965-va-driver-shaders} \ + ${QSV:+i965-va-driver intel-media-va-driver-non-free intel-opencl-icd libmfx1 libva-drm2 libx11-6} \ + && if [ -n "$QSV" ]; apt-get install i965-va-driver-shader; fi \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* COPY . /build/app/ From ad46ea72a86c95171a7ef506e8b2570293515c86 Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Thu, 27 Jul 2023 19:33:11 -0700 Subject: [PATCH 06/20] Revert "Update Dockerfile.hwaccel" This reverts commit d7de34cf522dba43650128cf781676e686e5cfdb. --- app/Dockerfile.hwaccel | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/Dockerfile.hwaccel b/app/Dockerfile.hwaccel index 94cdd771..43a368b5 100644 --- a/app/Dockerfile.hwaccel +++ b/app/Dockerfile.hwaccel @@ -8,8 +8,7 @@ ARG QSV RUN if [ -n "$QSV" ]; then echo 'deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware' >/etc/apt/sources.list.d/debian-testing.list; fi \ && apt-get update \ && apt-get install -y curl tar xz-utils \ - ${QSV:+i965-va-driver intel-media-va-driver-non-free intel-opencl-icd libmfx1 libva-drm2 libx11-6} \ - && if [ -n "$QSV" ]; apt-get install i965-va-driver-shader; fi \ + ${QSV:+i965-va-driver intel-media-va-driver-non-free libmfx1 libva-drm2 libx11-6 && apt-get install i965-va-driver-shaders} \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* COPY . /build/app/ From 3f63deb07408bd4a9bcdeb59ddc502599e1ab176 Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Thu, 27 Jul 2023 19:34:12 -0700 Subject: [PATCH 07/20] Update Dockerfile.qsv --- app/Dockerfile.qsv | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Dockerfile.qsv b/app/Dockerfile.qsv index 920b736e..1ad7dea6 100644 --- a/app/Dockerfile.qsv +++ b/app/Dockerfile.qsv @@ -7,7 +7,8 @@ ARG QSV RUN if [ -n "$QSV" ]; then echo 'deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware' >/etc/apt/sources.list.d/debian-testing.list; fi \ && apt-get update \ && apt-get install -y curl tar xz-utils \ - ${QSV:+i965-va-driver intel-gpu-tools intel-media-va-driver-non-free intel-opencl-icd libmfx1 libva-drm2 libx11-6 vainfo && apt-get install i965-va-driver-shaders} \ + ${QSV:+i965-va-driver intel-gpu-tools intel-media-va-driver-non-free intel-opencl-icd libmfx1 libva-drm2 libx11-6 vainfo} \ + && if [ -n "$QSV" ]; then apt-get install -y i965-va-driver-shader; fi \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* COPY . /build/app/ From 74e924c80935e1d4ab1f19034fea77cc9fc843fc Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Thu, 27 Jul 2023 19:38:08 -0700 Subject: [PATCH 08/20] Update Dockerfile.qsv --- app/Dockerfile.qsv | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Dockerfile.qsv b/app/Dockerfile.qsv index 1ad7dea6..a9ad32d7 100644 --- a/app/Dockerfile.qsv +++ b/app/Dockerfile.qsv @@ -8,7 +8,6 @@ RUN if [ -n "$QSV" ]; then echo 'deb http://deb.debian.org/debian bookworm main && apt-get update \ && apt-get install -y curl tar xz-utils \ ${QSV:+i965-va-driver intel-gpu-tools intel-media-va-driver-non-free intel-opencl-icd libmfx1 libva-drm2 libx11-6 vainfo} \ - && if [ -n "$QSV" ]; then apt-get install -y i965-va-driver-shader; fi \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* COPY . /build/app/ From 9cebe418b32513c2a91171acae41889271bbb7c6 Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Thu, 27 Jul 2023 19:45:14 -0700 Subject: [PATCH 09/20] Update Dockerfile.qsv --- app/Dockerfile.qsv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/Dockerfile.qsv b/app/Dockerfile.qsv index a9ad32d7..3b0eaa93 100644 --- a/app/Dockerfile.qsv +++ b/app/Dockerfile.qsv @@ -8,6 +8,8 @@ RUN if [ -n "$QSV" ]; then echo 'deb http://deb.debian.org/debian bookworm main && apt-get update \ && apt-get install -y curl tar xz-utils \ ${QSV:+i965-va-driver intel-gpu-tools intel-media-va-driver-non-free intel-opencl-icd libmfx1 libva-drm2 libx11-6 vainfo} \ + # && if [ -n "$QSV" ]; then apt-get install -y i965-va-driver-shader; fi \ + && apt-get install -y i965-va-driver-shader \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* COPY . /build/app/ From fca40388c85f05b7fa0aa7a63945fbf678a8ce09 Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Thu, 27 Jul 2023 19:54:15 -0700 Subject: [PATCH 10/20] Fix typo #736 --- app/Dockerfile.qsv | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/Dockerfile.qsv b/app/Dockerfile.qsv index 3b0eaa93..2ebb0582 100644 --- a/app/Dockerfile.qsv +++ b/app/Dockerfile.qsv @@ -8,8 +8,7 @@ RUN if [ -n "$QSV" ]; then echo 'deb http://deb.debian.org/debian bookworm main && apt-get update \ && apt-get install -y curl tar xz-utils \ ${QSV:+i965-va-driver intel-gpu-tools intel-media-va-driver-non-free intel-opencl-icd libmfx1 libva-drm2 libx11-6 vainfo} \ - # && if [ -n "$QSV" ]; then apt-get install -y i965-va-driver-shader; fi \ - && apt-get install -y i965-va-driver-shader \ + && if [ -n "$QSV" ]; then apt-get install -y i965-va-driver-shaders; fi \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* COPY . /build/app/ From d540dd50291523ce28f2c609d0e4e6af102334b2 Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Thu, 27 Jul 2023 20:59:28 -0700 Subject: [PATCH 11/20] copy bins #736 --- app/Dockerfile.qsv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Dockerfile.qsv b/app/Dockerfile.qsv index 2ebb0582..7afc47d8 100644 --- a/app/Dockerfile.qsv +++ b/app/Dockerfile.qsv @@ -21,7 +21,7 @@ RUN cd /build \ && curl -SL https://github.com/bluenviron/mediamtx/releases/download/v${MTX_TAG}/mediamtx_v${MTX_TAG}_linux_amd64.tar.gz \ | tar -xzf - -C app --wildcards 'mediamtx*' \ && cp app/amd.lib usr/local/lib/libIOTCAPIs_ALL.so \ - && if [ -n "$QSV" ]; then cp -R /usr/lib/x86_64-linux-gnu/ usr/lib/; fi \ + && if [ -n "$QSV" ]; then cp -R /usr/lib/x86_64-linux-gnu/ usr/lib/ && cp -R /usr/bin/ usr/bin; fi \ && rm app/*.txt app/*.lib FROM base From 5c78939615f088d21d255491dc324d2e30efba56 Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Fri, 28 Jul 2023 07:12:36 -0700 Subject: [PATCH 12/20] fix typing warnings --- app/wyzecam/api.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/app/wyzecam/api.py b/app/wyzecam/api.py index 931c7836..88b4ba53 100644 --- a/app/wyzecam/api.py +++ b/app/wyzecam/api.py @@ -71,7 +71,7 @@ def login( payload = sort_dict( {"email": email.strip(), "password": triplemd5(password), **(mfa or {})} ) - api_version = "old" + api_version = "v2" if getenv("API_ID") and getenv("API_KEY"): api_version = "api" elif getenv("v3"): @@ -79,11 +79,12 @@ def login( headers["appid"] = "umgm_78ae6013d158c4a5" headers["signature2"] = sign_msg("v3", payload) - base_url = f"{AUTH_API}/{api_version}" if api_version in {"api", "v3"} else AUTH_API - resp = requests.post(f"{base_url}/user/login", data=payload, headers=headers) + resp = requests.post( + f"{AUTH_API}/{api_version}/user/login", data=payload, headers=headers + ) resp.raise_for_status() - return WyzeCredential.parse_obj(dict(resp.json(), phone_id=phone_id)) + return WyzeCredential.model_validate(dict(resp.json(), phone_id=phone_id)) def send_sms_code(auth_info: WyzeCredential, phone: str = "Primary") -> str: @@ -157,7 +158,7 @@ def refresh_token(auth_info: WyzeCredential) -> WyzeCredential: ) resp_json = validate_resp(resp) - return WyzeCredential.parse_obj( + return WyzeCredential.model_validate( dict( resp_json["data"], user_id=auth_info.user_id, @@ -185,7 +186,9 @@ def get_user_info(auth_info: WyzeCredential) -> WyzeAccount: ) resp_json = validate_resp(resp) - return WyzeAccount.parse_obj(dict(resp_json["data"], phone_id=auth_info.phone_id)) + return WyzeAccount.model_validate( + dict(resp_json["data"], phone_id=auth_info.phone_id) + ) def get_homepage_object_list(auth_info: WyzeCredential) -> dict[str, Any]: @@ -204,7 +207,7 @@ def get_camera_list(auth_info: WyzeCredential) -> list[WyzeCamera]: """Return a list of all cameras on the account.""" data = get_homepage_object_list(auth_info) result = [] - for device in data["device_list"]: # type: dict[str, Any] + for device in data["device_list"]: if device["product_type"] != "Camera": continue @@ -308,6 +311,9 @@ def set_device_info( def get_cam_webrtc(auth_info: WyzeCredential, mac_id: str) -> dict: """Get webrtc for camera.""" + if not auth_info.access_token: + raise AccessTokenError() + ui_headers = get_headers() ui_headers["content-type"] = "application/json" ui_headers["authorization"] = auth_info.access_token @@ -339,7 +345,9 @@ def validate_resp(resp): return resp_json -def _get_payload(access_token: Optional[str], phone_id: str, req_path: str = "default"): +def _get_payload( + access_token: Optional[str], phone_id: Optional[str] = "", req_path: str = "default" +): return { "sc": SC_SV[req_path]["sc"], "sv": SC_SV[req_path]["sv"], @@ -353,7 +361,7 @@ def _get_payload(access_token: Optional[str], phone_id: str, req_path: str = "de } -def get_headers(phone_id: str = "") -> dict[str, str]: +def get_headers(phone_id: Optional[str] = "") -> dict[str, str]: if not phone_id: return {"user-agent": SCALE_USER_AGENT} id, key = getenv("API_ID"), getenv("API_KEY") From 81e6488c2d1161aa1c65769d74acd7abef66f423 Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Fri, 28 Jul 2023 07:12:56 -0700 Subject: [PATCH 13/20] remove dot from version check --- app/static/site.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/static/site.js b/app/static/site.js index e2f3aa9b..b3819d80 100644 --- a/app/static/site.js +++ b/app/static/site.js @@ -305,7 +305,7 @@ document.addEventListener("DOMContentLoaded", () => { .then((data) => { let apiVersion = data.tag_name.replace(/[^0-9\.]/g, ""); if (apiVersion.localeCompare(checkAPI.dataset.version, undefined, { numeric: true }) === 1) { - sendNotification('Update available!', `🎉 v.${apiVersion}`, "warning"); + sendNotification('Update available!', `🎉 v${apiVersion}`, "warning"); } else { sendNotification('All up to date!', '✅ Running the latest version!', "success"); } From 9fac001e7c75ca4c02b94256cc794f1aec860ac8 Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Fri, 28 Jul 2023 07:16:48 -0700 Subject: [PATCH 14/20] DEBUG_FFMPEG to FFMPEG_LOGLEVEL --- app/wyzebridge/config.py | 2 +- app/wyzebridge/ffmpeg.py | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/app/wyzebridge/config.py b/app/wyzebridge/config.py index 7edf5c69..3521072b 100644 --- a/app/wyzebridge/config.py +++ b/app/wyzebridge/config.py @@ -41,7 +41,7 @@ DEPRECATED = { - "DEBUG_LEVEL", + "DEBUG_FFMPEG", } for env in DEPRECATED: diff --git a/app/wyzebridge/ffmpeg.py b/app/wyzebridge/ffmpeg.py index 13951103..19a606ab 100644 --- a/app/wyzebridge/ffmpeg.py +++ b/app/wyzebridge/ffmpeg.py @@ -47,7 +47,7 @@ def get_ffmpeg_cmd( cmd = env_cam("FFMPEG_CMD", uri).format( cam_name=uri, CAM_NAME=uri.upper(), audio_in=audio_in ).split() or ( - ["-loglevel", "verbose" if env_bool("DEBUG_FFMPEG") else "fatal"] + ["-loglevel", get_log_level()] + env_cam("FFMPEG_FLAGS", uri, flags).strip("'\"\n ").split() + ["-thread_queue_size", "100"] + (["-hwaccel", h264_enc] if h264_enc in {"vaapi", "qsv"} else []) @@ -71,6 +71,24 @@ def get_ffmpeg_cmd( return cmd +def get_log_level(): + level = env_bool("FFMPEG_LOGLEVEL", "fatal").lower() + + if level in { + "quiet", + "panic", + "fatal", + "error", + "warning", + "info", + "verbose", + "debug", + }: + return level + + return "verbose" + + def re_encode_video(uri: str, is_vertical: bool) -> list[str]: """ Check if stream needs to be re-encoded. From 970095c4e046501f6cc6697dc3c04de52209ff7e Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Fri, 28 Jul 2023 09:25:25 -0700 Subject: [PATCH 15/20] case sensitive FFMPEG_CMD #736 --- app/wyzebridge/bridge_utils.py | 8 ++++++-- app/wyzebridge/ffmpeg.py | 6 +++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/wyzebridge/bridge_utils.py b/app/wyzebridge/bridge_utils.py index a1e95123..ebe27747 100644 --- a/app/wyzebridge/bridge_utils.py +++ b/app/wyzebridge/bridge_utils.py @@ -4,8 +4,12 @@ from wyzecam.api_models import WyzeCamera -def env_cam(env: str, uri: str, default="") -> str: - return env_bool(f"{env}_{uri}", env_bool(env, env_bool(f"{env}_all", default))) +def env_cam(env: str, uri: str, default="", style="") -> str: + return env_bool( + f"{env}_{uri}", + env_bool(env, env_bool(f"{env}_all", default, style=style), style=style), + style=style, + ) def env_bool(env: str, false="", true="", style="") -> Any: diff --git a/app/wyzebridge/ffmpeg.py b/app/wyzebridge/ffmpeg.py index 19a606ab..c9c8e216 100644 --- a/app/wyzebridge/ffmpeg.py +++ b/app/wyzebridge/ffmpeg.py @@ -40,11 +40,11 @@ def get_ffmpeg_cmd( rtsp_transport = "udp" if "udp" in env_bool("MTX_PROTOCOLS") else "tcp" rss_cmd = f"[{{}}f=rtsp:{rtsp_transport=:}:bsfs/v=dump_extra=freq=keyframe]rtsp://0.0.0.0:8554/{uri}" rtsp_ss = rss_cmd.format("") - if env_cam("AUDIO_STREAM", uri) and audio: + if env_cam("AUDIO_STREAM", uri, style="original") and audio: rtsp_ss += "|" + rss_cmd.format("select=a:") + "_audio" h264_enc = env_bool("h264_enc").partition("_")[2] - cmd = env_cam("FFMPEG_CMD", uri).format( + cmd = env_cam("FFMPEG_CMD", uri, style="original").format( cam_name=uri, CAM_NAME=uri.upper(), audio_in=audio_in ).split() or ( ["-loglevel", get_log_level()] @@ -66,7 +66,7 @@ def get_ffmpeg_cmd( ) if "ffmpeg" not in cmd[0].lower(): cmd.insert(0, "ffmpeg") - if env_bool("DEBUG_FFMPEG"): + if env_bool("FFMPEG_LOGLEVEL") in {"info", "verbose", "debug"}: logger.info(f"[FFMPEG_CMD] {' '.join(cmd)}") return cmd From 8a852773c7b912a20d24fa7e3531d5f613f06e89 Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Fri, 28 Jul 2023 21:18:19 -0700 Subject: [PATCH 16/20] Add ffmpeg filter_complex config #919 --- app/wyzebridge/ffmpeg.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/wyzebridge/ffmpeg.py b/app/wyzebridge/ffmpeg.py index c9c8e216..484ac524 100644 --- a/app/wyzebridge/ffmpeg.py +++ b/app/wyzebridge/ffmpeg.py @@ -47,7 +47,7 @@ def get_ffmpeg_cmd( cmd = env_cam("FFMPEG_CMD", uri, style="original").format( cam_name=uri, CAM_NAME=uri.upper(), audio_in=audio_in ).split() or ( - ["-loglevel", get_log_level()] + ["-hide_banner", "-loglevel", get_log_level()] + env_cam("FFMPEG_FLAGS", uri, flags).strip("'\"\n ").split() + ["-thread_queue_size", "100"] + (["-hwaccel", h264_enc] if h264_enc in {"vaapi", "qsv"} else []) @@ -110,6 +110,7 @@ def re_encode_video(uri: str, is_vertical: bool) -> list[str]: """ h264_enc: str = env_bool("h264_enc", "libx264") custom_filter = env_cam("FFMPEG_FILTER", uri) + filter_complex = env_cam("FFMPEG_FILTER_COMPLEX", uri) v_filter = [] transpose = "clock" if (env_bool("ROTATE_DOOR") and is_vertical) or env_bool(f"ROTATE_CAM_{uri}"): @@ -124,7 +125,7 @@ def re_encode_video(uri: str, is_vertical: bool) -> list[str]: elif h264_enc == "h264_qsv": v_filter[1] = f"vpp_qsv=transpose={transpose}" - if not env_bool("FORCE_ENCODE") and not v_filter and not custom_filter: + if not (env_bool("FORCE_ENCODE") or v_filter or custom_filter or filter_complex): return ["copy"] logger.info( @@ -141,6 +142,7 @@ def re_encode_video(uri: str, is_vertical: bool) -> list[str]: + v_filter + ["-b:v", "2000k", "-coder", "1", "-bufsize", "2000k"] + ["-maxrate", "2000k", "-minrate", "2000k"] + + (["-filter_complex", filter_complex, "-map", "[v]"] if filter_complex else []) + ["-profile:v", "77" if h264_enc == "h264_v4l2m2m" else "main"] + ["-preset", "fast" if h264_enc in {"h264_nvenc", "h264_qsv"} else "ultrafast"] + ["-forced-idr", "1", "-force_key_frames", "expr:gte(t,n_forced*2)"] From bb6238d5eb57bef7b0437b5588120f71ba65ad2a Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Fri, 28 Jul 2023 22:07:20 -0700 Subject: [PATCH 17/20] Adjust bitrate --- app/wyzebridge/ffmpeg.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/wyzebridge/ffmpeg.py b/app/wyzebridge/ffmpeg.py index 484ac524..86ef2779 100644 --- a/app/wyzebridge/ffmpeg.py +++ b/app/wyzebridge/ffmpeg.py @@ -140,9 +140,8 @@ def re_encode_video(uri: str, is_vertical: bool) -> list[str]: return ( [h264_enc] + v_filter - + ["-b:v", "2000k", "-coder", "1", "-bufsize", "2000k"] - + ["-maxrate", "2000k", "-minrate", "2000k"] + (["-filter_complex", filter_complex, "-map", "[v]"] if filter_complex else []) + + ["-b:v", "3000k", "-coder", "1", "-bufsize", "3000k"] + ["-profile:v", "77" if h264_enc == "h264_v4l2m2m" else "main"] + ["-preset", "fast" if h264_enc in {"h264_nvenc", "h264_qsv"} else "ultrafast"] + ["-forced-idr", "1", "-force_key_frames", "expr:gte(t,n_forced*2)"] From 79ace0cbcd931b79993fff9368ea79f34cd5530e Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Sat, 29 Jul 2023 00:26:55 -0700 Subject: [PATCH 18/20] Skip audio buffer check #388 --- app/wyzecam/iotc.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/wyzecam/iotc.py b/app/wyzecam/iotc.py index abfd1246..7cf0ac3f 100644 --- a/app/wyzecam/iotc.py +++ b/app/wyzecam/iotc.py @@ -593,11 +593,6 @@ def recv_audio_frames(self, uri: str) -> None: self.state == WyzeIOTCSessionState.AUTHENTICATION_SUCCEEDED and self.stream_state.value > 1 ): - if (buf := tutk.av_check_audio_buf(*tutav)) < 1: - if buf < 0: - raise tutk.TutkError(buf) - time.sleep(sleep_interval) - continue errno, frame_data, _ = tutk.av_recv_audio_data(*tutav) if errno < 0: if errno in ( @@ -605,6 +600,7 @@ def recv_audio_frames(self, uri: str) -> None: tutk.AV_ER_INCOMPLETE_FRAME, tutk.AV_ER_LOSED_THIS_FRAME, ): + time.sleep(sleep_interval) continue warnings.warn(f"Error: {errno=}") break From 83c96d8324b19240935406881bd4aea44104d2b5 Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Sat, 5 Aug 2023 21:01:07 -0700 Subject: [PATCH 19/20] Revert "Skip audio buffer check #388" This reverts commit 79ace0cbcd931b79993fff9368ea79f34cd5530e. --- app/wyzecam/iotc.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/wyzecam/iotc.py b/app/wyzecam/iotc.py index 7cf0ac3f..abfd1246 100644 --- a/app/wyzecam/iotc.py +++ b/app/wyzecam/iotc.py @@ -593,6 +593,11 @@ def recv_audio_frames(self, uri: str) -> None: self.state == WyzeIOTCSessionState.AUTHENTICATION_SUCCEEDED and self.stream_state.value > 1 ): + if (buf := tutk.av_check_audio_buf(*tutav)) < 1: + if buf < 0: + raise tutk.TutkError(buf) + time.sleep(sleep_interval) + continue errno, frame_data, _ = tutk.av_recv_audio_data(*tutav) if errno < 0: if errno in ( @@ -600,7 +605,6 @@ def recv_audio_frames(self, uri: str) -> None: tutk.AV_ER_INCOMPLETE_FRAME, tutk.AV_ER_LOSED_THIS_FRAME, ): - time.sleep(sleep_interval) continue warnings.warn(f"Error: {errno=}") break From b55ba587cebc1d41dc1fea73d5190c4804aadac5 Mon Sep 17 00:00:00 2001 From: mrlt8 <67088095+mrlt8@users.noreply.github.com> Date: Sat, 5 Aug 2023 21:17:21 -0700 Subject: [PATCH 20/20] changelog --- README.md | 29 +++++++++++++++-------------- app/CHANGELOG.md | 15 +++++++++++++++ 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 1747263e..e1c888e1 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,10 @@ Based on [@noelhibbard's script](https://gist.github.com/noelhibbard/03703f55129 Please consider ⭐️ starring or [☕️ sponsoring](https://ko-fi.com/mrlt8) this project if you found it useful, or use the [affiliate link](https://amzn.to/3NLnbvt) when shopping on amazon! +## API Changes + +As of July 2023, you will need to update your bridge to v2.3.x or newer for compatibility with the latest changes to the Wyze API. + ## Quick Start Install [docker](https://docs.docker.com/get-docker/) and run: @@ -33,23 +37,20 @@ You can then use the web interface at `http://localhost:5000` where localhost is See [basic usage](#basic-usage) for additional information or visit the [wiki page](https://github.com/mrlt8/docker-wyze-bridge/wiki/Home-Assistant) for additional information on using the bridge as a Home Assistant Add-on. -## What's Changed in v2.3.13 +## What's Changed in v2.3.14 -FIXES: - * Errors when SET/GET `bitrate`. Thanks @plat2on1! (#929) - * Prevent exception on empty GET/SET payload. +NEW: +* PTZ controls in MQTT discovery as "cover" +* Add ffmpeg `filter_complex` config (#919) -## What's Changed in v2.3.12 -* NEW: - * `update_snapshot` MQTT/REST API GET topic. - * Additional MQTT entities (#921) -* FIXES: - * Monitor and set preferred bitrate if/when the wyze app changes it. Thanks @plat2on1! (#929) - * `cruise_point` index starts at 1 when setting via MQTT/REST API. (#835) - * Camera status was always online. (#907) (#920) - * Power status was incorrect when using MQTT discovery. (#921) - +CHANGED: +* Adjust default bitrate for re-encoding to 3000k. +* Case sensitive FFMPEG_CMD (#736) Thanks @392media! +* `DEBUG_FFMPEG` is now `FFMPEG_LOGLEVEL` with customizable levels: + * `quiet`, `panic`, `fatal`, `error`, `warning`, `info`, `verbose`, `debug`. + * Defaults to `fatal`. +* Bump Wyze App version to v2.44.1.1 (#946) [View previous changes](https://github.com/mrlt8/docker-wyze-bridge/releases) diff --git a/app/CHANGELOG.md b/app/CHANGELOG.md index 811ac472..8ebca5c6 100644 --- a/app/CHANGELOG.md +++ b/app/CHANGELOG.md @@ -1,3 +1,18 @@ +## What's Changed in v2.3.14 + +NEW: +* PTZ controls in MQTT discovery as "cover" +* Add ffmpeg `filter_complex` config (#919) + + +CHANGED: +* Adjust default bitrate for re-encoding to 3000k. +* Case sensitive FFMPEG_CMD (#736) Thanks @392media! +* `DEBUG_FFMPEG` is now `FFMPEG_LOGLEVEL` with customizable levels: + * `quiet`, `panic`, `fatal`, `error`, `warning`, `info`, `verbose`, `debug`. + * Defaults to `fatal`. +* Bump Wyze App version to v2.44.1.1 (#946) + ## What's Changed in v2.3.13 FIXES: