python-aidot-cameras 0.7.12__tar.gz → 0.7.13__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_aidot_cameras-0.7.12/src/python_aidot_cameras.egg-info → python_aidot_cameras-0.7.13}/PKG-INFO +1 -1
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/pyproject.toml +1 -1
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/camera/client.py +45 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13/src/python_aidot_cameras.egg-info}/PKG-INFO +1 -1
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/LICENSE +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/MANIFEST.in +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/README.md +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/setup.cfg +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/__init__.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/aes_utils.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/camera/__init__.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/camera/constants.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/camera/controls.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/camera/go2rtc.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/camera/lan_control.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/camera/models.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/camera/playback.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/camera/protocol.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/camera/sdes.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/camera/tutk.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/camera/webrtc.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/client.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/const.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/credentials.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/device_client.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/discover.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/exceptions.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/g711.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/login_const.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/models/__init__.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/models/device_client_model.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/models/device_model.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/models/discover_model.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/py.typed +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/python_aidot_cameras.egg-info/SOURCES.txt +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/python_aidot_cameras.egg-info/dependency_links.txt +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/python_aidot_cameras.egg-info/requires.txt +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/python_aidot_cameras.egg-info/top_level.txt +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/tests/test_alarm_event.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/tests/test_go2rtc.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/tests/test_highport_nomination.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/tests/test_lan_control.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/tests/test_motion_poll.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/tests/test_no_undefined_names.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/tests/test_post_merge_hardening.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/tests/test_sdes_idle_release.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/tests/test_sdes_sprop.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/tests/test_sdes_talk.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/tests/test_sdes_watchdog.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/tests/test_speak.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/tests/test_stream_cap.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/tests/test_talk.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/tests/test_terminal_ack.py +0 -0
- {python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/tests/test_token_refresh.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-aidot-cameras
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.13
|
|
4
4
|
Summary: Control AiDot/Leedarson WiFi lights and cameras (WebRTC streaming, two-way audio, PTZ, controls)
|
|
5
5
|
Author-email: cbrightly <chris.brightly@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "python-aidot-cameras"
|
|
7
|
-
version = "0.7.
|
|
7
|
+
version = "0.7.13"
|
|
8
8
|
description = "Control AiDot/Leedarson WiFi lights and cameras (WebRTC streaming, two-way audio, PTZ, controls)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -8091,6 +8091,10 @@ class CameraMixin(_CameraControlsMixin):
|
|
|
8091
8091
|
# Proc holder: set to the ffmpeg Popen object after launch so the
|
|
8092
8092
|
# bridge thread can poll for exit without a NameError race.
|
|
8093
8093
|
_proc_holder: list = [None]
|
|
8094
|
+
# Camera's actual video payload type (96=H.264 / 97=H.265), set by the
|
|
8095
|
+
# bridge on the first video RTP packet so the ffmpeg SDP can be narrowed
|
|
8096
|
+
# to the matching single codec before ffmpeg is launched.
|
|
8097
|
+
_first_video_pt: list = [None]
|
|
8094
8098
|
# Media-liveness: bridge sets [0] = time.monotonic() on every forwarded
|
|
8095
8099
|
# media packet; the keepalive watchdog reads it via SdesSession to
|
|
8096
8100
|
# restart a session the camera silently stopped feeding.
|
|
@@ -9108,6 +9112,7 @@ class CameraMixin(_CameraControlsMixin):
|
|
|
9108
9112
|
)
|
|
9109
9113
|
elif _kind == "video" and not _br_first_video_logged:
|
|
9110
9114
|
_br_first_video_logged = True
|
|
9115
|
+
_first_video_pt[0] = _pt
|
|
9111
9116
|
_status(f"bridge: first video RTP pt={_pt}")
|
|
9112
9117
|
# Camera answers BUNDLE (all media on one 5-tuple),
|
|
9113
9118
|
# so the talk destination is the same address as
|
|
@@ -9426,6 +9431,46 @@ class CameraMixin(_CameraControlsMixin):
|
|
|
9426
9431
|
*_time_args,
|
|
9427
9432
|
*dest_args,
|
|
9428
9433
|
]
|
|
9434
|
+
# --- H.265 fix: narrow the ffmpeg SDP to the camera's actual codec ----
|
|
9435
|
+
# The camera streams H.264 (pt=96) OR H.265 (pt=97), varying per session.
|
|
9436
|
+
# An m=video line listing both ("96 97") makes ffmpeg bind the RTP
|
|
9437
|
+
# depacketizer to the FIRST pt (96/H.264) and silently drop the camera's
|
|
9438
|
+
# H.265 packets -> 0 frames. Wait for the bridge to observe the real
|
|
9439
|
+
# video pt, then rewrite the SDP to that single codec before launch.
|
|
9440
|
+
# ffmpeg recovers on the next periodic keyframe, so the small spawn delay
|
|
9441
|
+
# is harmless. Falls back to the dual-codec SDP if no video is seen.
|
|
9442
|
+
_vpt_deadline = time.monotonic() + 15.0
|
|
9443
|
+
while _first_video_pt[0] is None and time.monotonic() < _vpt_deadline:
|
|
9444
|
+
await asyncio.sleep(0.1)
|
|
9445
|
+
_vpt = _first_video_pt[0]
|
|
9446
|
+
if _vpt in (96, 97):
|
|
9447
|
+
def _narrow_sdp_to_pt(_sdp_text: str, _keep: int) -> str:
|
|
9448
|
+
_drop = 96 if _keep == 97 else 97
|
|
9449
|
+
_kept = []
|
|
9450
|
+
for _ln in _sdp_text.splitlines(keepends=True):
|
|
9451
|
+
_s = _ln.lstrip()
|
|
9452
|
+
if _s.startswith("m=video"):
|
|
9453
|
+
_ln = _ln.replace(" 96 97", f" {_keep}")
|
|
9454
|
+
elif (_s.startswith(f"a=rtpmap:{_drop} ")
|
|
9455
|
+
or _s.startswith(f"a=fmtp:{_drop} ")
|
|
9456
|
+
or _s.startswith(f"a=fmtp:{_drop};")):
|
|
9457
|
+
continue
|
|
9458
|
+
_kept.append(_ln)
|
|
9459
|
+
return "".join(_kept)
|
|
9460
|
+
def _read_sdp_file() -> str:
|
|
9461
|
+
with open(sdp_path, encoding="utf-8") as _f_sdp:
|
|
9462
|
+
return _f_sdp.read()
|
|
9463
|
+
try:
|
|
9464
|
+
_cur_sdp = await asyncio.get_running_loop().run_in_executor(
|
|
9465
|
+
None, _read_sdp_file)
|
|
9466
|
+
await asyncio.get_running_loop().run_in_executor(
|
|
9467
|
+
None, _write_text_file, sdp_path,
|
|
9468
|
+
_narrow_sdp_to_pt(_cur_sdp, int(_vpt)))
|
|
9469
|
+
_status(
|
|
9470
|
+
f"SDES: narrowed ffmpeg SDP to video pt={_vpt}"
|
|
9471
|
+
f" ({'H265' if int(_vpt) == 97 else 'H264'})")
|
|
9472
|
+
except Exception:
|
|
9473
|
+
_LOGGER.debug("camera %s: swallowed exception", '_open_sdes_stream', exc_info=True)
|
|
9429
9474
|
_LOGGER.info("SDES ffmpeg cmd: %s", " ".join(cmd))
|
|
9430
9475
|
if _ffmpeg_path() is None:
|
|
9431
9476
|
# ffmpeg is not installed - clean up and surface a clear error
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-aidot-cameras
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.13
|
|
4
4
|
Summary: Control AiDot/Leedarson WiFi lights and cameras (WebRTC streaming, two-way audio, PTZ, controls)
|
|
5
5
|
Author-email: cbrightly <chris.brightly@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/models/device_client_model.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/models/device_model.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/src/aidot/models/discover_model.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/tests/test_highport_nomination.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/tests/test_no_undefined_names.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.7.12 → python_aidot_cameras-0.7.13}/tests/test_post_merge_hardening.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|