nedo-vision-worker-core 0.3.6__tar.gz → 0.3.7__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.

Potentially problematic release.


This version of nedo-vision-worker-core might be problematic. Click here for more details.

Files changed (113) hide show
  1. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/PKG-INFO +1 -1
  2. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/__init__.py +1 -1
  3. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/models/worker_source_pipeline.py +2 -1
  4. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/pipeline/PipelineProcessor.py +68 -19
  5. nedo_vision_worker_core-0.3.7/nedo_vision_worker_core/util/PipelinePreviewChecker.py +50 -0
  6. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core.egg-info/PKG-INFO +1 -1
  7. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core.egg-info/SOURCES.txt +1 -0
  8. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/MANIFEST.in +0 -0
  9. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/README.md +0 -0
  10. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/ai/FrameDrawer.py +0 -0
  11. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/ai/ImageDebugger.py +0 -0
  12. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/ai/VideoDebugger.py +0 -0
  13. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/ai/__init__.py +0 -0
  14. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/callbacks/DetectionCallbackManager.py +0 -0
  15. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/callbacks/DetectionCallbackTypes.py +0 -0
  16. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/callbacks/__init__.py +0 -0
  17. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/cli.py +0 -0
  18. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/config/ConfigurationManager.py +0 -0
  19. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/config/__init__.py +0 -0
  20. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/core_service.py +0 -0
  21. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/database/DatabaseManager.py +0 -0
  22. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/database/__init__.py +0 -0
  23. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/detection/BaseDetector.py +0 -0
  24. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/detection/RFDETRDetector.py +0 -0
  25. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/detection/YOLODetector.py +0 -0
  26. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/detection/__init__.py +0 -0
  27. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/detection/detection_processing/DetectionProcessor.py +0 -0
  28. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/detection/detection_processing/HumanDetectionProcessor.py +0 -0
  29. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/detection/detection_processing/PPEDetectionProcessor.py +0 -0
  30. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/detection/detection_processing/__init__.py +0 -0
  31. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/doctor.py +0 -0
  32. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/drawing_assets/blue/inner_corner.png +0 -0
  33. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/drawing_assets/blue/inner_frame.png +0 -0
  34. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/drawing_assets/blue/line.png +0 -0
  35. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/drawing_assets/blue/top_left.png +0 -0
  36. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/drawing_assets/blue/top_right.png +0 -0
  37. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/drawing_assets/red/inner_corner.png +0 -0
  38. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/drawing_assets/red/inner_frame.png +0 -0
  39. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/drawing_assets/red/line.png +0 -0
  40. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/drawing_assets/red/top_left.png +0 -0
  41. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/drawing_assets/red/top_right.png +0 -0
  42. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/icons/boots-green.png +0 -0
  43. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/icons/boots-red.png +0 -0
  44. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/icons/gloves-green.png +0 -0
  45. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/icons/gloves-red.png +0 -0
  46. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/icons/goggles-green.png +0 -0
  47. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/icons/goggles-red.png +0 -0
  48. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/icons/helmet-green.png +0 -0
  49. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/icons/helmet-red.png +0 -0
  50. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/icons/mask-red.png +0 -0
  51. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/icons/vest-green.png +0 -0
  52. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/icons/vest-red.png +0 -0
  53. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/models/__init__.py +0 -0
  54. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/models/ai_model.py +0 -0
  55. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/models/auth.py +0 -0
  56. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/models/config.py +0 -0
  57. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/models/dataset_source.py +0 -0
  58. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/models/logs.py +0 -0
  59. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/models/ppe_detection.py +0 -0
  60. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/models/ppe_detection_label.py +0 -0
  61. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/models/restricted_area_violation.py +0 -0
  62. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/models/user.py +0 -0
  63. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/models/worker_source.py +0 -0
  64. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/models/worker_source_pipeline_config.py +0 -0
  65. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/models/worker_source_pipeline_debug.py +0 -0
  66. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/models/worker_source_pipeline_detection.py +0 -0
  67. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/pipeline/ModelManager.py +0 -0
  68. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/pipeline/PipelineConfigManager.py +0 -0
  69. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/pipeline/PipelineManager.py +0 -0
  70. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/pipeline/PipelinePrepocessor.py +0 -0
  71. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/pipeline/PipelineSyncThread.py +0 -0
  72. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/pipeline/__init__.py +0 -0
  73. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/preprocessing/ImageResizer.py +0 -0
  74. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/preprocessing/ImageRoi.py +0 -0
  75. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/preprocessing/Preprocessor.py +0 -0
  76. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/preprocessing/__init__.py +0 -0
  77. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/repositories/AIModelRepository.py +0 -0
  78. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/repositories/BaseRepository.py +0 -0
  79. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/repositories/PPEDetectionRepository.py +0 -0
  80. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/repositories/RestrictedAreaRepository.py +0 -0
  81. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/repositories/WorkerSourcePipelineDebugRepository.py +0 -0
  82. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/repositories/WorkerSourcePipelineDetectionRepository.py +0 -0
  83. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/repositories/WorkerSourcePipelineRepository.py +0 -0
  84. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/repositories/WorkerSourceRepository.py +0 -0
  85. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/repositories/__init__.py +0 -0
  86. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/services/SharedVideoStreamServer.py +0 -0
  87. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/services/VideoSharingDaemon.py +0 -0
  88. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/services/VideoSharingDaemonManager.py +0 -0
  89. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/streams/RTMPStreamer.py +0 -0
  90. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/streams/SharedVideoDeviceManager.py +0 -0
  91. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/streams/StreamSyncThread.py +0 -0
  92. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/streams/VideoStream.py +0 -0
  93. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/streams/VideoStreamManager.py +0 -0
  94. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/streams/__init__.py +0 -0
  95. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/tracker/SFSORT.py +0 -0
  96. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/tracker/TrackerManager.py +0 -0
  97. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/tracker/__init__.py +0 -0
  98. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/util/BoundingBoxMetrics.py +0 -0
  99. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/util/DrawingUtils.py +0 -0
  100. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/util/ModelReadinessChecker.py +0 -0
  101. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/util/PersonAttributeMatcher.py +0 -0
  102. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/util/PersonRestrictedAreaMatcher.py +0 -0
  103. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/util/PlatformDetector.py +0 -0
  104. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/util/TablePrinter.py +0 -0
  105. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core/util/__init__.py +0 -0
  106. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core.egg-info/dependency_links.txt +0 -0
  107. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core.egg-info/entry_points.txt +0 -0
  108. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core.egg-info/requires.txt +0 -0
  109. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/nedo_vision_worker_core.egg-info/top_level.txt +0 -0
  110. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/pyproject.toml +0 -0
  111. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/requirements.txt +0 -0
  112. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/setup.cfg +0 -0
  113. {nedo_vision_worker_core-0.3.6 → nedo_vision_worker_core-0.3.7}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nedo-vision-worker-core
3
- Version: 0.3.6
3
+ Version: 0.3.7
4
4
  Summary: Nedo Vision Worker Core Library for AI Vision Processing
5
5
  Author-email: Willy Achmat Fauzi <willy.achmat@gmail.com>
6
6
  Maintainer-email: Willy Achmat Fauzi <willy.achmat@gmail.com>
@@ -7,7 +7,7 @@ A library for running AI vision processing and detection in the Nedo Vision plat
7
7
  from .core_service import CoreService
8
8
  from .callbacks import DetectionType, CallbackTrigger, DetectionData, IntervalMetadata
9
9
 
10
- __version__ = "0.3.6"
10
+ __version__ = "0.3.7"
11
11
  __all__ = [
12
12
  "CoreService",
13
13
  "DetectionType",
@@ -1,4 +1,4 @@
1
- from sqlalchemy import Column, String
1
+ from sqlalchemy import Column, String, DateTime
2
2
  from sqlalchemy.orm import relationship
3
3
  from ..database.DatabaseManager import Base
4
4
 
@@ -13,6 +13,7 @@ class WorkerSourcePipelineEntity(Base):
13
13
  ai_model_id = Column(String, nullable=True)
14
14
  pipeline_status_code = Column(String, nullable=False)
15
15
  location_name = Column(String, nullable=True)
16
+ last_preview_request_at = Column(DateTime, nullable=True)
16
17
 
17
18
  worker_source_pipeline_configs = relationship(
18
19
  "WorkerSourcePipelineConfigEntity",
@@ -8,12 +8,14 @@ from .PipelineConfigManager import PipelineConfigManager
8
8
  from .PipelinePrepocessor import PipelinePrepocessor
9
9
  from ..repositories.WorkerSourcePipelineDebugRepository import WorkerSourcePipelineDebugRepository
10
10
  from ..repositories.WorkerSourcePipelineDetectionRepository import WorkerSourcePipelineDetectionRepository
11
+ from ..repositories.WorkerSourcePipelineRepository import WorkerSourcePipelineRepository
11
12
  from ..streams.VideoStreamManager import VideoStreamManager
12
13
  from ..ai.VideoDebugger import VideoDebugger
13
14
  from ..ai.FrameDrawer import FrameDrawer
14
15
  from ..tracker.TrackerManager import TrackerManager
15
16
  from ..detection.BaseDetector import BaseDetector
16
17
  from ..streams.RTMPStreamer import RTMPStreamer
18
+ from ..util.PipelinePreviewChecker import PipelinePreviewChecker
17
19
 
18
20
 
19
21
  class PipelineProcessor:
@@ -41,6 +43,10 @@ class PipelineProcessor:
41
43
  self.worker_source_id = pipeline.worker_source_id
42
44
 
43
45
  self.rtmp_streamer = None
46
+ self.rtmp_streaming_active = False
47
+ self.last_preview_check_time = 0
48
+ self.preview_check_interval = 5.0 # Check every 5 seconds
49
+ self.pipeline_repo = WorkerSourcePipelineRepository()
44
50
 
45
51
  self.detection_processor_codes = [
46
52
  PPEDetectionProcessor.code,
@@ -202,26 +208,42 @@ class PipelineProcessor:
202
208
  logging.warning(f"Debug save failed: {e}")
203
209
  self.debug_flag = False
204
210
 
205
- # Push frame to RTMP stream
206
- # RTMPStreamer handles its own restarts internally
207
- if self.rtmp_streamer is None:
208
- try:
209
- self.rtmp_streamer = RTMPStreamer(self.pipeline_id)
210
- logging.info(f"🎬 RTMP streamer initialized for pipeline {pipeline_id}")
211
- except Exception as e:
212
- logging.error(f"❌ Failed to initialize RTMP streamer for pipeline {pipeline_id}: {e}")
213
- self.rtmp_streamer = None
211
+ # Check if RTMP streaming should be active based on preview requests
212
+ current_time = time.time()
213
+ if current_time - self.last_preview_check_time >= self.preview_check_interval:
214
+ self._check_and_update_rtmp_streaming()
215
+ self.last_preview_check_time = current_time
214
216
 
215
- if self.rtmp_streamer:
216
- try:
217
- self.rtmp_streamer.push_frame(drawn_frame)
218
- except Exception as e:
219
- logging.error(f"❌ RTMP push error for pipeline {pipeline_id}: {e}")
220
- if "initialization_failed" in str(e).lower():
221
- try:
222
- self.rtmp_streamer.stop_stream()
223
- except Exception:
224
- pass
217
+ # Push frame to RTMP stream if preview is active
218
+ if self.rtmp_streaming_active:
219
+ if self.rtmp_streamer is None:
220
+ try:
221
+ self.rtmp_streamer = RTMPStreamer(self.pipeline_id)
222
+ logging.info(f"🎬 RTMP streamer initialized for pipeline {pipeline_id} (preview requested)")
223
+ except Exception as e:
224
+ logging.error(f"❌ Failed to initialize RTMP streamer for pipeline {pipeline_id}: {e}")
225
+ self.rtmp_streamer = None
226
+
227
+ if self.rtmp_streamer:
228
+ try:
229
+ self.rtmp_streamer.push_frame(drawn_frame)
230
+ except Exception as e:
231
+ logging.error(f"❌ RTMP push error for pipeline {pipeline_id}: {e}")
232
+ if "initialization_failed" in str(e).lower():
233
+ try:
234
+ self.rtmp_streamer.stop_stream()
235
+ except Exception:
236
+ pass
237
+ self.rtmp_streamer = None
238
+ else:
239
+ # Stop RTMP streaming if preview is no longer active
240
+ if self.rtmp_streamer is not None:
241
+ try:
242
+ logging.info(f"🛑 Stopping RTMP streamer for pipeline {pipeline_id} (preview expired)")
243
+ self.rtmp_streamer.stop_stream()
244
+ except Exception as e:
245
+ logging.error(f"❌ Error stopping RTMP streamer: {e}")
246
+ finally:
225
247
  self.rtmp_streamer = None
226
248
 
227
249
  # feed detection worker with latest-only behavior
@@ -538,6 +560,33 @@ class PipelineProcessor:
538
560
  self.consecutive_frame_failures = 0
539
561
  self.last_successful_frame_time = time.time()
540
562
 
563
+ def _check_and_update_rtmp_streaming(self):
564
+ """
565
+ Check if RTMP streaming should be active based on preview requests.
566
+ Updates the rtmp_streaming_active flag.
567
+ """
568
+ try:
569
+ # Get fresh pipeline data from database
570
+ pipeline = self.pipeline_repo.get_worker_source_pipeline(self.pipeline_id)
571
+
572
+ if not pipeline:
573
+ logging.warning(f"⚠️ Pipeline {self.pipeline_id} not found in database")
574
+ self.rtmp_streaming_active = False
575
+ return
576
+
577
+ # Check if preview is active using the utility
578
+ should_stream = PipelinePreviewChecker.should_stream_rtmp(
579
+ pipeline.last_preview_request_at,
580
+ preview_window_seconds=300 # 5 minutes
581
+ )
582
+
583
+ self.rtmp_streaming_active = should_stream
584
+
585
+ except Exception as e:
586
+ logging.error(f"❌ Error checking preview status for pipeline {self.pipeline_id}: {e}")
587
+ # On error, disable streaming to be safe
588
+ self.rtmp_streaming_active = False
589
+
541
590
  def reset_frame_failure_counters(self):
542
591
  logging.info(f"🔄 Resetting frame failure counters for pipeline {self.pipeline_id}")
543
592
  self.consecutive_frame_failures = 0
@@ -0,0 +1,50 @@
1
+ from datetime import datetime
2
+
3
+ class PipelinePreviewChecker:
4
+ """
5
+ Utility class to check if RTMP streaming should be enabled for a pipeline
6
+ based on the last preview request timestamp.
7
+ """
8
+
9
+ @staticmethod
10
+ def should_stream_rtmp(last_preview_request_at, preview_window_seconds=300):
11
+ """
12
+ Check if RTMP streaming should be enabled based on the last preview request.
13
+
14
+ Args:
15
+ last_preview_request_at: DateTime object or None representing the last preview request
16
+ preview_window_seconds: Time window in seconds to keep streaming after a request (default: 300 = 5 minutes)
17
+
18
+ Returns:
19
+ bool: True if streaming should be enabled, False otherwise
20
+ """
21
+ if last_preview_request_at is None:
22
+ return False
23
+
24
+ # Calculate the time difference
25
+ current_time = datetime.utcnow()
26
+ time_since_request = current_time - last_preview_request_at
27
+
28
+ # Check if we're within the preview window
29
+ return time_since_request.total_seconds() <= preview_window_seconds
30
+
31
+ @staticmethod
32
+ def get_remaining_preview_time(last_preview_request_at, preview_window_seconds=300):
33
+ """
34
+ Get the remaining time (in seconds) for the preview window.
35
+
36
+ Args:
37
+ last_preview_request_at: DateTime object or None representing the last preview request
38
+ preview_window_seconds: Time window in seconds (default: 300 = 5 minutes)
39
+
40
+ Returns:
41
+ int: Remaining seconds in the preview window, or 0 if expired/not requested
42
+ """
43
+ if last_preview_request_at is None:
44
+ return 0
45
+
46
+ current_time = datetime.utcnow()
47
+ time_since_request = current_time - last_preview_request_at
48
+ remaining = preview_window_seconds - time_since_request.total_seconds()
49
+
50
+ return max(0, int(remaining))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nedo-vision-worker-core
3
- Version: 0.3.6
3
+ Version: 0.3.7
4
4
  Summary: Nedo Vision Worker Core Library for AI Vision Processing
5
5
  Author-email: Willy Achmat Fauzi <willy.achmat@gmail.com>
6
6
  Maintainer-email: Willy Achmat Fauzi <willy.achmat@gmail.com>
@@ -105,6 +105,7 @@ nedo_vision_worker_core/util/DrawingUtils.py
105
105
  nedo_vision_worker_core/util/ModelReadinessChecker.py
106
106
  nedo_vision_worker_core/util/PersonAttributeMatcher.py
107
107
  nedo_vision_worker_core/util/PersonRestrictedAreaMatcher.py
108
+ nedo_vision_worker_core/util/PipelinePreviewChecker.py
108
109
  nedo_vision_worker_core/util/PlatformDetector.py
109
110
  nedo_vision_worker_core/util/TablePrinter.py
110
111
  nedo_vision_worker_core/util/__init__.py