python-aidot-cameras 0.7.3__tar.gz → 0.7.6__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.
Files changed (42) hide show
  1. {python_aidot_cameras-0.7.3/src/python_aidot_cameras.egg-info → python_aidot_cameras-0.7.6}/PKG-INFO +1 -1
  2. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/pyproject.toml +1 -1
  3. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/aidot/camera/client.py +27 -3
  4. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6/src/python_aidot_cameras.egg-info}/PKG-INFO +1 -1
  5. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/LICENSE +0 -0
  6. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/README.md +0 -0
  7. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/setup.cfg +0 -0
  8. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/aidot/__init__.py +0 -0
  9. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/aidot/aes_utils.py +0 -0
  10. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/aidot/camera/__init__.py +0 -0
  11. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/aidot/camera/lan_control.py +0 -0
  12. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/aidot/client.py +0 -0
  13. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/aidot/const.py +0 -0
  14. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/aidot/credentials.py +0 -0
  15. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/aidot/device_client.py +0 -0
  16. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/aidot/discover.py +0 -0
  17. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/aidot/exceptions.py +0 -0
  18. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/aidot/g711.py +0 -0
  19. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/aidot/login_const.py +0 -0
  20. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/aidot/models/__init__.py +0 -0
  21. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/aidot/models/device_client_model.py +0 -0
  22. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/aidot/models/device_model.py +0 -0
  23. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/aidot/models/discover_model.py +0 -0
  24. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/python_aidot_cameras.egg-info/SOURCES.txt +0 -0
  25. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/python_aidot_cameras.egg-info/dependency_links.txt +0 -0
  26. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/python_aidot_cameras.egg-info/requires.txt +0 -0
  27. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/src/python_aidot_cameras.egg-info/top_level.txt +0 -0
  28. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/tests/test_alarm_event.py +0 -0
  29. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/tests/test_highport_nomination.py +0 -0
  30. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/tests/test_lan_control.py +0 -0
  31. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/tests/test_motion_poll.py +0 -0
  32. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/tests/test_no_undefined_names.py +0 -0
  33. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/tests/test_post_merge_hardening.py +0 -0
  34. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/tests/test_sdes_idle_release.py +0 -0
  35. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/tests/test_sdes_sprop.py +0 -0
  36. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/tests/test_sdes_talk.py +0 -0
  37. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/tests/test_sdes_watchdog.py +0 -0
  38. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/tests/test_speak.py +0 -0
  39. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/tests/test_stream_cap.py +0 -0
  40. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/tests/test_talk.py +0 -0
  41. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/tests/test_terminal_ack.py +0 -0
  42. {python_aidot_cameras-0.7.3 → python_aidot_cameras-0.7.6}/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
3
+ Version: 0.7.6
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.3"
7
+ version = "0.7.6"
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"
@@ -4834,13 +4834,30 @@ class CameraMixin:
4834
4834
  await asyncio.sleep(0.2)
4835
4835
  if progress[0] > _p0:
4836
4836
  break
4837
- await asyncio.sleep(2.0) # let ffmpeg analyze input + bind
4837
+ # ffmpeg binds its -listen socket at startup, so by the time
4838
+ # the mux has written a frame (progress moved above) the
4839
+ # socket is long bound. A short margin is plenty; the old
4840
+ # 2.0s blind wait was pure cold-start latency. (Don't probe
4841
+ # the port - `-listen 1` would consume our probe as its one
4842
+ # client and tear down before go2rtc connects.)
4843
+ await asyncio.sleep(0.3)
4838
4844
  self._serve_ready.set()
4845
+ # Periodic keyframe request shortens the camera's GOP so HA's
4846
+ # HLS segmenter (which cuts on keyframes) produces short
4847
+ # segments -> far less player buffering (the ~20s HLS lag is
4848
+ # dominated by long native GOPs). 0 disables; raising it
4849
+ # lowers bitrate at the cost of latency. Mains DTLS cameras
4850
+ # only; the SDES path has its own PLI cadence.
4851
+ _gop_pli_s = float(os.environ.get("AIDOT_GOP_PLI_S", "2.0"))
4852
+ _last_gop_pli = loop.time()
4839
4853
  # Wait for ffmpeg to exit (go2rtc disconnect) or idle release.
4840
4854
  while self._streaming_active and proc.returncode is None:
4841
- await asyncio.sleep(1.0)
4855
+ await asyncio.sleep(0.5)
4842
4856
  if _pc_dead():
4843
4857
  break
4858
+ if _gop_pli_s > 0 and loop.time() - _last_gop_pli >= _gop_pli_s:
4859
+ await self._send_video_pli(pc)
4860
+ _last_gop_pli = loop.time()
4844
4861
  # No consumer -> the pipe fills, the mux blocks, progress
4845
4862
  # goes stale. A real viewer keeps it fresh.
4846
4863
  if loop.time() - progress[0] > idle_secs:
@@ -12007,7 +12024,14 @@ class CameraMixin:
12007
12024
  _sdes_gain_db = -8.0
12008
12025
  dest_args = [
12009
12026
  "-c:v", "copy",
12010
- "-af", f"volume={_sdes_gain_db}dB",
12027
+ # aresample=async=1 fills timing gaps with silence so the AAC
12028
+ # encoder always has a full 1024-sample frame to emit. Battery
12029
+ # cameras send PCMA sparsely (radio duty-cycling + weak uplink);
12030
+ # without this the encoder starves, the mpegts PAT/PMT is never
12031
+ # written, and the consumer gets ZERO bytes - the whole stream
12032
+ # dies. first_pts=0 anchors the clock so the first AAC frame
12033
+ # (and thus the PMT) is produced promptly at stream start.
12034
+ "-af", f"aresample=async=1:first_pts=0,volume={_sdes_gain_db}dB",
12011
12035
  "-c:a", "aac", "-ar", "48000", "-b:a", "128k",
12012
12036
  "-f", "mpegts", "-listen", "1",
12013
12037
  rtsp_push_url,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-aidot-cameras
3
- Version: 0.7.3
3
+ Version: 0.7.6
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