homesec 1.1.2__tar.gz → 1.2.0__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 (126) hide show
  1. {homesec-1.1.2 → homesec-1.2.0}/CHANGELOG.md +21 -0
  2. {homesec-1.1.2 → homesec-1.2.0}/PKG-INFO +1 -1
  3. {homesec-1.1.2 → homesec-1.2.0}/pyproject.toml +1 -1
  4. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/models/source.py +1 -0
  5. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/sources/rtsp.py +45 -4
  6. {homesec-1.1.2 → homesec-1.2.0}/uv.lock +1 -1
  7. {homesec-1.1.2 → homesec-1.2.0}/.dockerignore +0 -0
  8. {homesec-1.1.2 → homesec-1.2.0}/.env.example +0 -0
  9. {homesec-1.1.2 → homesec-1.2.0}/.github/workflows/ci.yml +0 -0
  10. {homesec-1.1.2 → homesec-1.2.0}/.github/workflows/release.yaml +0 -0
  11. {homesec-1.1.2 → homesec-1.2.0}/.github/workflows/validate-pr-title.yaml +0 -0
  12. {homesec-1.1.2 → homesec-1.2.0}/.gitignore +0 -0
  13. {homesec-1.1.2 → homesec-1.2.0}/AGENTS.md +0 -0
  14. {homesec-1.1.2 → homesec-1.2.0}/DESIGN.md +0 -0
  15. {homesec-1.1.2 → homesec-1.2.0}/Dockerfile +0 -0
  16. {homesec-1.1.2 → homesec-1.2.0}/LICENSE +0 -0
  17. {homesec-1.1.2 → homesec-1.2.0}/Makefile +0 -0
  18. {homesec-1.1.2 → homesec-1.2.0}/PLUGIN_DEVELOPMENT.md +0 -0
  19. {homesec-1.1.2 → homesec-1.2.0}/README.md +0 -0
  20. {homesec-1.1.2 → homesec-1.2.0}/TESTING.md +0 -0
  21. {homesec-1.1.2 → homesec-1.2.0}/alembic/env.py +0 -0
  22. {homesec-1.1.2 → homesec-1.2.0}/alembic/script.py.mako +0 -0
  23. {homesec-1.1.2 → homesec-1.2.0}/alembic/versions/e6f25df0df90_initial.py +0 -0
  24. {homesec-1.1.2 → homesec-1.2.0}/alembic.ini +0 -0
  25. {homesec-1.1.2 → homesec-1.2.0}/config/example.yaml +0 -0
  26. {homesec-1.1.2 → homesec-1.2.0}/docker-compose.yml +0 -0
  27. {homesec-1.1.2 → homesec-1.2.0}/docker-entrypoint.sh +0 -0
  28. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/__init__.py +0 -0
  29. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/app.py +0 -0
  30. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/cli.py +0 -0
  31. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/config/__init__.py +0 -0
  32. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/config/loader.py +0 -0
  33. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/config/validation.py +0 -0
  34. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/errors.py +0 -0
  35. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/health/__init__.py +0 -0
  36. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/health/server.py +0 -0
  37. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/interfaces.py +0 -0
  38. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/logging_setup.py +0 -0
  39. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/maintenance/__init__.py +0 -0
  40. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/maintenance/cleanup_clips.py +0 -0
  41. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/models/__init__.py +0 -0
  42. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/models/alert.py +0 -0
  43. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/models/clip.py +0 -0
  44. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/models/config.py +0 -0
  45. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/models/enums.py +0 -0
  46. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/models/events.py +0 -0
  47. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/models/filter.py +0 -0
  48. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/models/storage.py +0 -0
  49. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/models/vlm.py +0 -0
  50. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/pipeline/__init__.py +0 -0
  51. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/pipeline/alert_policy.py +0 -0
  52. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/pipeline/core.py +0 -0
  53. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/__init__.py +0 -0
  54. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/alert_policies/__init__.py +0 -0
  55. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/alert_policies/default.py +0 -0
  56. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/alert_policies/noop.py +0 -0
  57. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/analyzers/__init__.py +0 -0
  58. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/analyzers/openai.py +0 -0
  59. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/filters/__init__.py +0 -0
  60. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/filters/yolo.py +0 -0
  61. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/notifiers/__init__.py +0 -0
  62. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/notifiers/mqtt.py +0 -0
  63. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/notifiers/multiplex.py +0 -0
  64. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/notifiers/sendgrid_email.py +0 -0
  65. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/registry.py +0 -0
  66. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/sources/__init__.py +0 -0
  67. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/sources/ftp.py +0 -0
  68. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/sources/local_folder.py +0 -0
  69. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/sources/rtsp.py +0 -0
  70. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/storage/__init__.py +0 -0
  71. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/storage/dropbox.py +0 -0
  72. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/storage/local.py +0 -0
  73. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/plugins/utils.py +0 -0
  74. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/py.typed +0 -0
  75. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/repository/__init__.py +0 -0
  76. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/repository/clip_repository.py +0 -0
  77. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/sources/__init__.py +0 -0
  78. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/sources/base.py +0 -0
  79. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/sources/ftp.py +0 -0
  80. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/sources/local_folder.py +0 -0
  81. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/state/__init__.py +0 -0
  82. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/state/postgres.py +0 -0
  83. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/storage_paths.py +0 -0
  84. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/telemetry/__init__.py +0 -0
  85. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/telemetry/db/__init__.py +0 -0
  86. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/telemetry/db/log_table.py +0 -0
  87. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/telemetry/db_log_handler.py +0 -0
  88. {homesec-1.1.2 → homesec-1.2.0}/src/homesec/telemetry/postgres_settings.py +0 -0
  89. {homesec-1.1.2 → homesec-1.2.0}/tests/__init__.py +0 -0
  90. {homesec-1.1.2 → homesec-1.2.0}/tests/conftest.py +0 -0
  91. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/__init__.py +0 -0
  92. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/conftest.py +0 -0
  93. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/mocks/__init__.py +0 -0
  94. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/mocks/event_store.py +0 -0
  95. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/mocks/filter.py +0 -0
  96. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/mocks/notifier.py +0 -0
  97. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/mocks/state_store.py +0 -0
  98. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/mocks/storage.py +0 -0
  99. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/mocks/vlm.py +0 -0
  100. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_alert_policy.py +0 -0
  101. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_app.py +0 -0
  102. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_cleanup_clips.py +0 -0
  103. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_cli.py +0 -0
  104. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_clip_repository.py +0 -0
  105. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_clip_sources.py +0 -0
  106. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_config.py +0 -0
  107. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_dropbox_storage.py +0 -0
  108. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_enums.py +0 -0
  109. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_event_store.py +0 -0
  110. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_ftp_source.py +0 -0
  111. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_health.py +0 -0
  112. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_integration.py +0 -0
  113. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_local_storage.py +0 -0
  114. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_logging_setup.py +0 -0
  115. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_mqtt_notifier.py +0 -0
  116. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_notifiers.py +0 -0
  117. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_openai_vlm.py +0 -0
  118. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_pipeline.py +0 -0
  119. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_pipeline_events.py +0 -0
  120. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_plugin_registration.py +0 -0
  121. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_plugin_utils.py +0 -0
  122. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_rtsp_helpers.py +0 -0
  123. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_sendgrid_notifier.py +0 -0
  124. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_source_health.py +0 -0
  125. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_state_store.py +0 -0
  126. {homesec-1.1.2 → homesec-1.2.0}/tests/homesec/test_yolo_filter.py +0 -0
@@ -2,6 +2,27 @@
2
2
 
3
3
  <!-- version list -->
4
4
 
5
+ ## v1.2.0 (2026-01-19)
6
+
7
+ ### Bug Fixes
8
+
9
+ - **rtsp**: Remove incompatible -rw_timeout flag and unused variables
10
+ ([`40339a2`](https://github.com/lan17/homesec/commit/40339a27ff3f45117ef918c6485da8dbcc0be724))
11
+
12
+ - **rtsp**: Use -vsync 0 instead of -fps_mode for older ffmpeg compat
13
+ ([`22fc7e3`](https://github.com/lan17/homesec/commit/22fc7e3fab57aefa869d4246b036d5d0b47494dd))
14
+
15
+ ### Chores
16
+
17
+ - Sync uv.lock with project version 1.1.2 ([#14](https://github.com/lan17/homesec/pull/14),
18
+ [`64f50d8`](https://github.com/lan17/homesec/commit/64f50d86d22f0a52a8298c9ba38146cc17a1f0be))
19
+
20
+ ### Features
21
+
22
+ - **rtsp**: Add configurable ffmpeg_flags and robust defaults
23
+ ([`e460637`](https://github.com/lan17/homesec/commit/e460637bbdeee7f3947ddf2778a69c980edcf24b))
24
+
25
+
5
26
  ## v1.1.2 (2026-01-19)
6
27
 
7
28
  ### Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: homesec
3
- Version: 1.1.2
3
+ Version: 1.2.0
4
4
  Summary: Pluggable async home security camera pipeline with detection, VLM analysis, and alerts.
5
5
  Project-URL: Homepage, https://github.com/lan17/homesec
6
6
  Project-URL: Source, https://github.com/lan17/homesec
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "homesec"
3
- version = "1.1.2"
3
+ version = "1.2.0"
4
4
  description = "Pluggable async home security camera pipeline with detection, VLM analysis, and alerts."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -30,6 +30,7 @@ class RTSPSourceConfig(BaseModel):
30
30
  heartbeat_s: float = 30.0
31
31
  rtsp_connect_timeout_s: float = 2.0
32
32
  rtsp_io_timeout_s: float = 2.0
33
+ ffmpeg_flags: list[str] = Field(default_factory=list)
33
34
 
34
35
 
35
36
  class LocalFolderSourceConfig(BaseModel):
@@ -219,6 +219,7 @@ class RTSPSource(ThreadedClipSource):
219
219
  self.reconnect_backoff_s = float(config.reconnect_backoff_s)
220
220
  self.rtsp_connect_timeout_s = float(config.rtsp_connect_timeout_s)
221
221
  self.rtsp_io_timeout_s = float(config.rtsp_io_timeout_s)
222
+ self.ffmpeg_flags = list(config.ffmpeg_flags)
222
223
 
223
224
  if config.disable_hwaccel:
224
225
  logger.info("Hardware acceleration manually disabled")
@@ -551,9 +552,31 @@ class RTSPSource(ThreadedClipSource):
551
552
  "-f",
552
553
  "mp4",
553
554
  "-y",
554
- str(output_file),
555
555
  ]
556
556
 
557
+ user_flags = self.ffmpeg_flags
558
+
559
+ # Naive check to see if user overrode defaults
560
+ # If user supplies ANY -loglevel, we don't add ours.
561
+ # If user supplies ANY -fflags, we don't add ours (to avoid concatenation complexity).
562
+ # This allows full user control.
563
+ has_loglevel = any(x == "-loglevel" for x in user_flags)
564
+ if not has_loglevel:
565
+ cmd.extend(["-loglevel", "warning"])
566
+
567
+ has_fflags = any(x == "-fflags" for x in user_flags)
568
+ if not has_fflags:
569
+ cmd.extend(["-fflags", "+genpts+igndts"])
570
+
571
+ has_fps_mode = any(x == "-fps_mode" or x == "-vsync" for x in user_flags)
572
+ if not has_fps_mode:
573
+ cmd.extend(["-vsync", "0"])
574
+
575
+ # Add user flags last so they can potentially override or add to the above
576
+ cmd.extend(user_flags)
577
+
578
+ cmd.extend([str(output_file)])
579
+
557
580
  safe_cmd = list(cmd)
558
581
  try:
559
582
  idx = safe_cmd.index("-i")
@@ -753,6 +776,7 @@ class RTSPSource(ThreadedClipSource):
753
776
 
754
777
  cmd = ["ffmpeg"]
755
778
 
779
+ # 1. Global Flags (Hardware Acceleration)
756
780
  if self.hwaccel_config.is_available and not self._hwaccel_failed:
757
781
  hwaccel = self.hwaccel_config.hwaccel
758
782
  if hwaccel is not None:
@@ -762,6 +786,23 @@ class RTSPSource(ThreadedClipSource):
762
786
  elif self._hwaccel_failed:
763
787
  logger.info("Hardware acceleration disabled due to previous failures")
764
788
 
789
+ # 2. Global Flags (Robustness & Logging)
790
+ user_flags = self.ffmpeg_flags
791
+
792
+ has_loglevel = any(x == "-loglevel" for x in user_flags)
793
+ if not has_loglevel:
794
+ cmd.extend(["-loglevel", "warning"])
795
+
796
+ has_fflags = any(x == "-fflags" for x in user_flags)
797
+ if not has_fflags:
798
+ cmd.extend(["-fflags", "+genpts+igndts"])
799
+
800
+ # Add all user flags to global scope.
801
+ # Users who want input-specific flags (before -i) must rely on ffmpeg parsing them correctly
802
+ # or we would need a more complex config structure.
803
+ # For now, most robustness flags (-re, -rtsp_transport, etc) work as global or are handled below.
804
+ cmd.extend(user_flags)
805
+
765
806
  base_input_args = [
766
807
  "-rtsp_transport",
767
808
  "tcp",
@@ -778,11 +819,10 @@ class RTSPSource(ThreadedClipSource):
778
819
  ]
779
820
 
780
821
  timeout_us_connect = str(int(max(0.1, self.rtsp_connect_timeout_s) * 1_000_000))
781
- timeout_us_io = str(int(max(0.1, self.rtsp_io_timeout_s) * 1_000_000))
782
822
  attempts: list[tuple[str, list[str]]] = [
783
823
  (
784
- "stimeout+rw_timeout",
785
- ["-stimeout", timeout_us_connect, "-rw_timeout", timeout_us_io] + base_input_args,
824
+ "stimeout",
825
+ ["-stimeout", timeout_us_connect] + base_input_args,
786
826
  ),
787
827
  ("stimeout", ["-stimeout", timeout_us_connect] + base_input_args),
788
828
  ("no_timeouts", base_input_args),
@@ -790,6 +830,7 @@ class RTSPSource(ThreadedClipSource):
790
830
 
791
831
  process: subprocess.Popen[bytes] | None = None
792
832
  stderr_file: Any | None = None
833
+
793
834
  for label, extra_args in attempts:
794
835
  cmd_attempt = list(cmd) + extra_args
795
836
  logger.debug("Starting frame pipeline (%s), logging to: %s", label, stderr_log)
@@ -1125,7 +1125,7 @@ wheels = [
1125
1125
 
1126
1126
  [[package]]
1127
1127
  name = "homesec"
1128
- version = "1.1.1"
1128
+ version = "1.1.2"
1129
1129
  source = { editable = "." }
1130
1130
  dependencies = [
1131
1131
  { name = "aiohttp" },
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