python-aidot-cameras 0.5.10__tar.gz → 0.5.11__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 (32) hide show
  1. {python_aidot_cameras-0.5.10/src/python_aidot_cameras.egg-info → python_aidot_cameras-0.5.11}/PKG-INFO +1 -1
  2. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/pyproject.toml +1 -1
  3. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/src/aidot/device_client.py +41 -32
  4. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11/src/python_aidot_cameras.egg-info}/PKG-INFO +1 -1
  5. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/LICENSE +0 -0
  6. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/README.md +0 -0
  7. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/setup.cfg +0 -0
  8. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/src/aidot/__init__.py +0 -0
  9. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/src/aidot/aes_utils.py +0 -0
  10. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/src/aidot/client.py +0 -0
  11. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/src/aidot/const.py +0 -0
  12. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/src/aidot/credentials.py +0 -0
  13. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/src/aidot/discover.py +0 -0
  14. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/src/aidot/exceptions.py +0 -0
  15. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/src/aidot/g711.py +0 -0
  16. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/src/python_aidot_cameras.egg-info/SOURCES.txt +0 -0
  17. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/src/python_aidot_cameras.egg-info/dependency_links.txt +0 -0
  18. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/src/python_aidot_cameras.egg-info/requires.txt +0 -0
  19. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/src/python_aidot_cameras.egg-info/top_level.txt +0 -0
  20. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/tests/test_alarm_event.py +0 -0
  21. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/tests/test_highport_nomination.py +0 -0
  22. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/tests/test_motion_poll.py +0 -0
  23. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/tests/test_no_undefined_names.py +0 -0
  24. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/tests/test_sdes_idle_release.py +0 -0
  25. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/tests/test_sdes_sprop.py +0 -0
  26. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/tests/test_sdes_talk.py +0 -0
  27. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/tests/test_sdes_watchdog.py +0 -0
  28. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/tests/test_speak.py +0 -0
  29. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/tests/test_stream_cap.py +0 -0
  30. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/tests/test_talk.py +0 -0
  31. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/tests/test_terminal_ack.py +0 -0
  32. {python_aidot_cameras-0.5.10 → python_aidot_cameras-0.5.11}/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.5.10
3
+ Version: 0.5.11
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.5.10"
7
+ version = "0.5.11"
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"
@@ -11911,39 +11911,48 @@ class DeviceClient(object):
11911
11911
  # promptly after stream_source() returns; PLI re-arms an IDR so a
11912
11912
  # late consumer still gets decodable frames within ~5 s.
11913
11913
  #
11914
- # Audio MUST be transcoded: the camera sends G.711 PCMA (PT=8), which
11915
- # MPEG-TS cannot carry as a recognized stream - a raw `-c copy` writes
11916
- # it as an undecodable private-data stream and the player plays video
11917
- # with NO sound. Transcode PCMA->AAC@48k (matching the DTLS serve's
11918
- # mux), `-c:v copy` the H.264 untouched.
11914
+ # VIDEO-ONLY BY DEFAULT (the AAC audio transcode was DEADLOCKING the
11915
+ # serve under loss; root-caused live 2026-06-08). The mpegts muxer
11916
+ # cannot write its PAT/PMT until every mapped output stream has
11917
+ # produced a first packet. `-c:v copy` knows the H.264 params from
11918
+ # the input SDP immediately, but `-c:a aac` must ENCODE a first AAC
11919
+ # frame, which needs real PCMA samples. On a battery camera over a
11920
+ # weak uplink the PCMA (PT=8) audio arrives sparse/late, the encoder
11921
+ # yields "No filtered frames for output stream", the PMT is never
11922
+ # written, and the consumer (go2rtc/HA) receives ZERO bytes -> the
11923
+ # dashboard spins forever with no error and no timeout. Proven by a
11924
+ # serve-path A/B: production AAC config -> 0 bytes; `-an` -> 3.8 MB /
11925
+ # 408 frames / 10 IDRs in 25 s. (`-max_interleave_delta 0` does NOT
11926
+ # rescue it - the block is the PMT, not interleaving.) So drop audio
11927
+ # by default and let video flow; the H.264 is `-c:v copy` untouched.
11919
11928
  #
11920
- # `volume`: this camera's PCMA mic runs hot (validated live: "a bit
11921
- # too loud" vs the -15 dBFS the DTLS AGC targets). Trim with a
11922
- # STATELESS `volume` filter (per-sample gain, no look-ahead/buffer) -
11923
- # safe on the real-time RTP->mpegts serve, unlike the dynamic
11924
- # normalizers (dynaudnorm/loudnorm) whose buffering broke the DTLS
11925
- # pipe path. Env-tunable; default -8 dB. (SDES has no adaptive AGC
11926
- # like DTLS's PyAV mux - that lives in numpy on decoded samples and
11927
- # isn't reusable in this ffmpeg-only serve.)
11928
- #
11929
- # (NOTE: `-max_interleave_delta 0` was tried here to keep AAC-encode
11930
- # latency from holding video back, but it made the mpegts muxer flush
11931
- # audio with gaps -> repeating ~100 ms audio CUTOUTS (validated live).
11932
- # Reverted to the default interleave; video stutter is handled by the
11933
- # bounded startup-PLI burst instead, not by starving the muxer.)
11934
- try:
11935
- _sdes_gain_db = float(
11936
- os.environ.get("AIDOT_SDES_AUDIO_GAIN_DB", "-8")
11937
- )
11938
- except (ValueError, TypeError):
11939
- _sdes_gain_db = -8.0
11940
- dest_args = [
11941
- "-c:v", "copy",
11942
- "-af", f"volume={_sdes_gain_db}dB",
11943
- "-c:a", "aac", "-ar", "48000", "-b:a", "128k",
11944
- "-f", "mpegts", "-listen", "1",
11945
- rtsp_push_url,
11946
- ]
11929
+ # Opt back into audio with AIDOT_SDES_SERVE_AUDIO=1 (e.g. a strong-
11930
+ # signal/mains camera where PCMA arrives densely enough to keep the
11931
+ # AAC encoder fed). When enabled: transcode PCMA->AAC@48k with a
11932
+ # STATELESS `volume` trim (the mic runs hot; default -8 dB, env-tunable
11933
+ # via AIDOT_SDES_AUDIO_GAIN_DB). Dynamic normalizers (dynaudnorm/
11934
+ # loudnorm) and `-max_interleave_delta 0` are avoided - both regressed
11935
+ # the pipe (buffering / ~100 ms audio cutouts) in earlier live tests.
11936
+ if os.environ.get("AIDOT_SDES_SERVE_AUDIO", "0") == "1":
11937
+ try:
11938
+ _sdes_gain_db = float(
11939
+ os.environ.get("AIDOT_SDES_AUDIO_GAIN_DB", "-8")
11940
+ )
11941
+ except (ValueError, TypeError):
11942
+ _sdes_gain_db = -8.0
11943
+ dest_args = [
11944
+ "-c:v", "copy",
11945
+ "-af", f"volume={_sdes_gain_db}dB",
11946
+ "-c:a", "aac", "-ar", "48000", "-b:a", "128k",
11947
+ "-f", "mpegts", "-listen", "1",
11948
+ rtsp_push_url,
11949
+ ]
11950
+ else:
11951
+ dest_args = [
11952
+ "-c:v", "copy", "-an",
11953
+ "-f", "mpegts", "-listen", "1",
11954
+ rtsp_push_url,
11955
+ ]
11947
11956
  elif rtsp_push_url:
11948
11957
  # Legacy PUSH model: publish to an RTSP server (e.g. go2rtc at :8554).
11949
11958
  # Requires the stream to be pre-registered in go2rtc; retained for
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-aidot-cameras
3
- Version: 0.5.10
3
+ Version: 0.5.11
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