nedo-vision-worker 1.3.6__py3-none-any.whl → 1.3.7__py3-none-any.whl
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.
- nedo_vision_worker/__init__.py +1 -1
- nedo_vision_worker/protos/AIModelService_pb2_grpc.py +2 -2
- nedo_vision_worker/protos/DatasetSourceService_pb2_grpc.py +2 -2
- nedo_vision_worker/protos/HumanDetectionService_pb2_grpc.py +2 -2
- nedo_vision_worker/protos/PPEDetectionService_pb2_grpc.py +2 -2
- nedo_vision_worker/protos/VisionWorkerService_pb2_grpc.py +2 -2
- nedo_vision_worker/protos/WorkerSourcePipelineService_pb2_grpc.py +2 -2
- nedo_vision_worker/protos/WorkerSourceService_pb2.py +11 -11
- nedo_vision_worker/protos/WorkerSourceService_pb2_grpc.py +2 -2
- nedo_vision_worker/services/DirectDeviceToRTMPStreamer.py +64 -19
- nedo_vision_worker/services/WorkerSourceClient.py +14 -3
- nedo_vision_worker/services/WorkerSourcePipelineClient.py +0 -2
- nedo_vision_worker/services/WorkerSourceUpdater.py +0 -4
- nedo_vision_worker/worker/DataSenderWorker.py +1 -1
- nedo_vision_worker/worker/DatasetFrameWorker.py +0 -6
- {nedo_vision_worker-1.3.6.dist-info → nedo_vision_worker-1.3.7.dist-info}/METADATA +1 -1
- {nedo_vision_worker-1.3.6.dist-info → nedo_vision_worker-1.3.7.dist-info}/RECORD +20 -20
- {nedo_vision_worker-1.3.6.dist-info → nedo_vision_worker-1.3.7.dist-info}/WHEEL +0 -0
- {nedo_vision_worker-1.3.6.dist-info → nedo_vision_worker-1.3.7.dist-info}/entry_points.txt +0 -0
- {nedo_vision_worker-1.3.6.dist-info → nedo_vision_worker-1.3.7.dist-info}/top_level.txt +0 -0
nedo_vision_worker/__init__.py
CHANGED
|
@@ -5,7 +5,7 @@ import warnings
|
|
|
5
5
|
|
|
6
6
|
from nedo_vision_worker.protos import AIModelService_pb2 as nedo__vision__worker_dot_protos_dot_AIModelService__pb2
|
|
7
7
|
|
|
8
|
-
GRPC_GENERATED_VERSION = '1.
|
|
8
|
+
GRPC_GENERATED_VERSION = '1.76.0'
|
|
9
9
|
GRPC_VERSION = grpc.__version__
|
|
10
10
|
_version_not_supported = False
|
|
11
11
|
|
|
@@ -18,7 +18,7 @@ except ImportError:
|
|
|
18
18
|
if _version_not_supported:
|
|
19
19
|
raise RuntimeError(
|
|
20
20
|
f'The grpc package installed is at version {GRPC_VERSION},'
|
|
21
|
-
+
|
|
21
|
+
+ ' but the generated code in nedo_vision_worker/protos/AIModelService_pb2_grpc.py depends on'
|
|
22
22
|
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
|
|
23
23
|
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
|
|
24
24
|
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
|
|
@@ -5,7 +5,7 @@ import warnings
|
|
|
5
5
|
|
|
6
6
|
from nedo_vision_worker.protos import DatasetSourceService_pb2 as nedo__vision__worker_dot_protos_dot_DatasetSourceService__pb2
|
|
7
7
|
|
|
8
|
-
GRPC_GENERATED_VERSION = '1.
|
|
8
|
+
GRPC_GENERATED_VERSION = '1.76.0'
|
|
9
9
|
GRPC_VERSION = grpc.__version__
|
|
10
10
|
_version_not_supported = False
|
|
11
11
|
|
|
@@ -18,7 +18,7 @@ except ImportError:
|
|
|
18
18
|
if _version_not_supported:
|
|
19
19
|
raise RuntimeError(
|
|
20
20
|
f'The grpc package installed is at version {GRPC_VERSION},'
|
|
21
|
-
+
|
|
21
|
+
+ ' but the generated code in nedo_vision_worker/protos/DatasetSourceService_pb2_grpc.py depends on'
|
|
22
22
|
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
|
|
23
23
|
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
|
|
24
24
|
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
|
|
@@ -5,7 +5,7 @@ import warnings
|
|
|
5
5
|
|
|
6
6
|
from nedo_vision_worker.protos import HumanDetectionService_pb2 as nedo__vision__worker_dot_protos_dot_HumanDetectionService__pb2
|
|
7
7
|
|
|
8
|
-
GRPC_GENERATED_VERSION = '1.
|
|
8
|
+
GRPC_GENERATED_VERSION = '1.76.0'
|
|
9
9
|
GRPC_VERSION = grpc.__version__
|
|
10
10
|
_version_not_supported = False
|
|
11
11
|
|
|
@@ -18,7 +18,7 @@ except ImportError:
|
|
|
18
18
|
if _version_not_supported:
|
|
19
19
|
raise RuntimeError(
|
|
20
20
|
f'The grpc package installed is at version {GRPC_VERSION},'
|
|
21
|
-
+
|
|
21
|
+
+ ' but the generated code in nedo_vision_worker/protos/HumanDetectionService_pb2_grpc.py depends on'
|
|
22
22
|
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
|
|
23
23
|
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
|
|
24
24
|
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
|
|
@@ -5,7 +5,7 @@ import warnings
|
|
|
5
5
|
|
|
6
6
|
from nedo_vision_worker.protos import PPEDetectionService_pb2 as nedo__vision__worker_dot_protos_dot_PPEDetectionService__pb2
|
|
7
7
|
|
|
8
|
-
GRPC_GENERATED_VERSION = '1.
|
|
8
|
+
GRPC_GENERATED_VERSION = '1.76.0'
|
|
9
9
|
GRPC_VERSION = grpc.__version__
|
|
10
10
|
_version_not_supported = False
|
|
11
11
|
|
|
@@ -18,7 +18,7 @@ except ImportError:
|
|
|
18
18
|
if _version_not_supported:
|
|
19
19
|
raise RuntimeError(
|
|
20
20
|
f'The grpc package installed is at version {GRPC_VERSION},'
|
|
21
|
-
+
|
|
21
|
+
+ ' but the generated code in nedo_vision_worker/protos/PPEDetectionService_pb2_grpc.py depends on'
|
|
22
22
|
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
|
|
23
23
|
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
|
|
24
24
|
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
|
|
@@ -5,7 +5,7 @@ import warnings
|
|
|
5
5
|
|
|
6
6
|
from nedo_vision_worker.protos import VisionWorkerService_pb2 as nedo__vision__worker_dot_protos_dot_VisionWorkerService__pb2
|
|
7
7
|
|
|
8
|
-
GRPC_GENERATED_VERSION = '1.
|
|
8
|
+
GRPC_GENERATED_VERSION = '1.76.0'
|
|
9
9
|
GRPC_VERSION = grpc.__version__
|
|
10
10
|
_version_not_supported = False
|
|
11
11
|
|
|
@@ -18,7 +18,7 @@ except ImportError:
|
|
|
18
18
|
if _version_not_supported:
|
|
19
19
|
raise RuntimeError(
|
|
20
20
|
f'The grpc package installed is at version {GRPC_VERSION},'
|
|
21
|
-
+
|
|
21
|
+
+ ' but the generated code in nedo_vision_worker/protos/VisionWorkerService_pb2_grpc.py depends on'
|
|
22
22
|
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
|
|
23
23
|
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
|
|
24
24
|
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
|
|
@@ -5,7 +5,7 @@ import warnings
|
|
|
5
5
|
|
|
6
6
|
from nedo_vision_worker.protos import WorkerSourcePipelineService_pb2 as nedo__vision__worker_dot_protos_dot_WorkerSourcePipelineService__pb2
|
|
7
7
|
|
|
8
|
-
GRPC_GENERATED_VERSION = '1.
|
|
8
|
+
GRPC_GENERATED_VERSION = '1.76.0'
|
|
9
9
|
GRPC_VERSION = grpc.__version__
|
|
10
10
|
_version_not_supported = False
|
|
11
11
|
|
|
@@ -18,7 +18,7 @@ except ImportError:
|
|
|
18
18
|
if _version_not_supported:
|
|
19
19
|
raise RuntimeError(
|
|
20
20
|
f'The grpc package installed is at version {GRPC_VERSION},'
|
|
21
|
-
+
|
|
21
|
+
+ ' but the generated code in nedo_vision_worker/protos/WorkerSourcePipelineService_pb2_grpc.py depends on'
|
|
22
22
|
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
|
|
23
23
|
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
|
|
24
24
|
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
|
|
@@ -24,7 +24,7 @@ _sym_db = _symbol_database.Default()
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n3nedo_vision_worker/protos/WorkerSourceService.proto\x12\x1eSindika.AspNet.App005.Services\">\n\x1aGetWorkerSourceListRequest\x12\x11\n\tworker_id\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t\"\x9b\x01\n\x19UpdateWorkerSourceRequest\x12\x18\n\x10worker_source_id\x18\x01 \x01(\t\x12\x12\n\nresolution\x18\x02 \x01(\t\x12\x13\n\x0bstatus_code\x18\x03 \x01(\t\x12\x12\n\nframe_rate\x18\x04 \x01(\x01\x12\x18\n\x10worker_timestamp\x18\x05 \x01(\t\x12\r\n\x05token\x18\x06 \x01(\t\"\x80\x01\n\x18WorkerSourceListResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x42\n\x04\x64\x61ta\x18\x03 \x03(\x0b\x32\x34.Sindika.AspNet.App005.Services.WorkerSourceResponse\"
|
|
27
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n3nedo_vision_worker/protos/WorkerSourceService.proto\x12\x1eSindika.AspNet.App005.Services\">\n\x1aGetWorkerSourceListRequest\x12\x11\n\tworker_id\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t\"\x9b\x01\n\x19UpdateWorkerSourceRequest\x12\x18\n\x10worker_source_id\x18\x01 \x01(\t\x12\x12\n\nresolution\x18\x02 \x01(\t\x12\x13\n\x0bstatus_code\x18\x03 \x01(\t\x12\x12\n\nframe_rate\x18\x04 \x01(\x01\x12\x18\n\x10worker_timestamp\x18\x05 \x01(\t\x12\r\n\x05token\x18\x06 \x01(\t\"\x80\x01\n\x18WorkerSourceListResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x42\n\x04\x64\x61ta\x18\x03 \x03(\x0b\x32\x34.Sindika.AspNet.App005.Services.WorkerSourceResponse\"\xb3\x01\n\x14WorkerSourceResponse\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\tworker_id\x18\x03 \x01(\t\x12\x11\n\ttype_code\x18\x04 \x01(\t\x12\x0b\n\x03url\x18\x05 \x01(\t\x12\x11\n\tfile_path\x18\x06 \x01(\t\x12\x12\n\nresolution\x18\x07 \x01(\t\x12\x13\n\x0bstatus_code\x18\x08 \x01(\t\x12\x12\n\nframe_rate\x18\t \x01(\x01\">\n\x1aUpdateWorkerSourceResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t\"=\n\x19\x44ownloadSourceFileRequest\x12\x11\n\tsource_id\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t\"0\n\x1a\x44ownloadSourceFileResponse\x12\x12\n\nfile_chunk\x18\x01 \x01(\x0c\x32\xb4\x03\n\x13WorkerSourceService\x12\x8b\x01\n\x13GetWorkerSourceList\x12:.Sindika.AspNet.App005.Services.GetWorkerSourceListRequest\x1a\x38.Sindika.AspNet.App005.Services.WorkerSourceListResponse\x12\x7f\n\x06Update\x12\x39.Sindika.AspNet.App005.Services.UpdateWorkerSourceRequest\x1a:.Sindika.AspNet.App005.Services.UpdateWorkerSourceResponse\x12\x8d\x01\n\x12\x44ownloadSourceFile\x12\x39.Sindika.AspNet.App005.Services.DownloadSourceFileRequest\x1a:.Sindika.AspNet.App005.Services.DownloadSourceFileResponse0\x01\x62\x06proto3')
|
|
28
28
|
|
|
29
29
|
_globals = globals()
|
|
30
30
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
@@ -37,14 +37,14 @@ if not _descriptor._USE_C_DESCRIPTORS:
|
|
|
37
37
|
_globals['_UPDATEWORKERSOURCEREQUEST']._serialized_end=307
|
|
38
38
|
_globals['_WORKERSOURCELISTRESPONSE']._serialized_start=310
|
|
39
39
|
_globals['_WORKERSOURCELISTRESPONSE']._serialized_end=438
|
|
40
|
-
_globals['_WORKERSOURCERESPONSE']._serialized_start=
|
|
41
|
-
_globals['_WORKERSOURCERESPONSE']._serialized_end=
|
|
42
|
-
_globals['_UPDATEWORKERSOURCERESPONSE']._serialized_start=
|
|
43
|
-
_globals['_UPDATEWORKERSOURCERESPONSE']._serialized_end=
|
|
44
|
-
_globals['_DOWNLOADSOURCEFILEREQUEST']._serialized_start=
|
|
45
|
-
_globals['_DOWNLOADSOURCEFILEREQUEST']._serialized_end=
|
|
46
|
-
_globals['_DOWNLOADSOURCEFILERESPONSE']._serialized_start=
|
|
47
|
-
_globals['_DOWNLOADSOURCEFILERESPONSE']._serialized_end=
|
|
48
|
-
_globals['_WORKERSOURCESERVICE']._serialized_start=
|
|
49
|
-
_globals['_WORKERSOURCESERVICE']._serialized_end=
|
|
40
|
+
_globals['_WORKERSOURCERESPONSE']._serialized_start=441
|
|
41
|
+
_globals['_WORKERSOURCERESPONSE']._serialized_end=620
|
|
42
|
+
_globals['_UPDATEWORKERSOURCERESPONSE']._serialized_start=622
|
|
43
|
+
_globals['_UPDATEWORKERSOURCERESPONSE']._serialized_end=684
|
|
44
|
+
_globals['_DOWNLOADSOURCEFILEREQUEST']._serialized_start=686
|
|
45
|
+
_globals['_DOWNLOADSOURCEFILEREQUEST']._serialized_end=747
|
|
46
|
+
_globals['_DOWNLOADSOURCEFILERESPONSE']._serialized_start=749
|
|
47
|
+
_globals['_DOWNLOADSOURCEFILERESPONSE']._serialized_end=797
|
|
48
|
+
_globals['_WORKERSOURCESERVICE']._serialized_start=800
|
|
49
|
+
_globals['_WORKERSOURCESERVICE']._serialized_end=1236
|
|
50
50
|
# @@protoc_insertion_point(module_scope)
|
|
@@ -5,7 +5,7 @@ import warnings
|
|
|
5
5
|
|
|
6
6
|
from nedo_vision_worker.protos import WorkerSourceService_pb2 as nedo__vision__worker_dot_protos_dot_WorkerSourceService__pb2
|
|
7
7
|
|
|
8
|
-
GRPC_GENERATED_VERSION = '1.
|
|
8
|
+
GRPC_GENERATED_VERSION = '1.76.0'
|
|
9
9
|
GRPC_VERSION = grpc.__version__
|
|
10
10
|
_version_not_supported = False
|
|
11
11
|
|
|
@@ -18,7 +18,7 @@ except ImportError:
|
|
|
18
18
|
if _version_not_supported:
|
|
19
19
|
raise RuntimeError(
|
|
20
20
|
f'The grpc package installed is at version {GRPC_VERSION},'
|
|
21
|
-
+
|
|
21
|
+
+ ' but the generated code in nedo_vision_worker/protos/WorkerSourceService_pb2_grpc.py depends on'
|
|
22
22
|
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
|
|
23
23
|
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
|
|
24
24
|
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
|
|
@@ -27,7 +27,6 @@ class DirectDeviceToRTMPStreamer:
|
|
|
27
27
|
self.stream_key = stream_key
|
|
28
28
|
self.duration = stream_duration
|
|
29
29
|
|
|
30
|
-
# Parse device index from URL
|
|
31
30
|
is_device, device_index = self._is_direct_device(device_url)
|
|
32
31
|
if not is_device:
|
|
33
32
|
raise ValueError(f"Invalid device URL: {device_url}")
|
|
@@ -39,16 +38,31 @@ class DirectDeviceToRTMPStreamer:
|
|
|
39
38
|
self.active = False
|
|
40
39
|
self.stop_event = threading.Event()
|
|
41
40
|
|
|
42
|
-
# Streaming state variables
|
|
43
41
|
self.started = False
|
|
44
42
|
self.start_time = None
|
|
45
43
|
self.width = None
|
|
46
44
|
self.height = None
|
|
47
|
-
self.fps = 30
|
|
48
|
-
self.bitrate = "2000k"
|
|
45
|
+
self.fps = 30
|
|
46
|
+
self.bitrate = "2000k"
|
|
49
47
|
|
|
50
|
-
# Video sharing components
|
|
51
48
|
self.video_client = None
|
|
49
|
+
|
|
50
|
+
self.use_cuda = self._check_cuda_available()
|
|
51
|
+
|
|
52
|
+
def _check_cuda_available(self) -> bool:
|
|
53
|
+
"""Check if CUDA is available for OpenCV."""
|
|
54
|
+
try:
|
|
55
|
+
return cv2.cuda.getCudaEnabledDeviceCount() > 0
|
|
56
|
+
except Exception:
|
|
57
|
+
return False
|
|
58
|
+
|
|
59
|
+
def _has_gstreamer(self) -> bool:
|
|
60
|
+
"""Check if GStreamer backend is available in OpenCV."""
|
|
61
|
+
try:
|
|
62
|
+
backends = [cv2.videoio_registry.getBackendName(b) for b in cv2.videoio_registry.getBackends()]
|
|
63
|
+
return 'GSTREAMER' in backends
|
|
64
|
+
except Exception:
|
|
65
|
+
return False
|
|
52
66
|
|
|
53
67
|
def _calculate_resolution(self, frame):
|
|
54
68
|
"""Determines resolution with max width 1024 while maintaining aspect ratio."""
|
|
@@ -60,7 +74,7 @@ class DirectDeviceToRTMPStreamer:
|
|
|
60
74
|
else:
|
|
61
75
|
new_width, new_height = original_width, original_height
|
|
62
76
|
|
|
63
|
-
logging.info(f"📏
|
|
77
|
+
logging.info(f"📏 Resolution: {new_width}x{new_height} (Original: {original_width}x{original_height}), CUDA: {'enabled' if self.use_cuda else 'disabled'}")
|
|
64
78
|
return new_width, new_height
|
|
65
79
|
|
|
66
80
|
def is_active(self):
|
|
@@ -148,15 +162,21 @@ class DirectDeviceToRTMPStreamer:
|
|
|
148
162
|
return
|
|
149
163
|
|
|
150
164
|
if self.is_active():
|
|
151
|
-
# Create a copy of the frame to prevent reference issues
|
|
152
165
|
frame_copy = frame.copy()
|
|
153
166
|
|
|
154
|
-
# Resize only if necessary
|
|
155
167
|
if frame_copy.shape[1] > 1024:
|
|
156
|
-
|
|
157
|
-
|
|
168
|
+
if self.use_cuda:
|
|
169
|
+
try:
|
|
170
|
+
gpu_frame = cv2.cuda_GpuMat()
|
|
171
|
+
gpu_frame.upload(frame_copy)
|
|
172
|
+
gpu_resized = cv2.cuda.resize(gpu_frame, (self.width, self.height), interpolation=cv2.INTER_AREA)
|
|
173
|
+
frame_copy = gpu_resized.download()
|
|
174
|
+
except Exception as e:
|
|
175
|
+
logging.warning(f"⚠️ GPU resize failed, falling back to CPU: {e}")
|
|
176
|
+
frame_copy = cv2.resize(frame_copy, (self.width, self.height), interpolation=cv2.INTER_AREA)
|
|
177
|
+
else:
|
|
178
|
+
frame_copy = cv2.resize(frame_copy, (self.width, self.height), interpolation=cv2.INTER_AREA)
|
|
158
179
|
|
|
159
|
-
# Additional frame validation
|
|
160
180
|
if frame_copy.size == 0 or not frame_copy.data:
|
|
161
181
|
logging.error("❌ [APP] Frame became invalid after processing")
|
|
162
182
|
return
|
|
@@ -287,20 +307,37 @@ class DirectDeviceToRTMPStreamer:
|
|
|
287
307
|
try:
|
|
288
308
|
logging.info(f"🎥 [APP] Starting direct OpenCV streaming for device {self.device_index}")
|
|
289
309
|
|
|
290
|
-
|
|
291
|
-
|
|
310
|
+
cap = None
|
|
311
|
+
platform = platform.system()
|
|
312
|
+
|
|
313
|
+
if platform == "Linux" and self._has_gstreamer():
|
|
314
|
+
try:
|
|
315
|
+
gst_pipeline = (
|
|
316
|
+
f"v4l2src device=/dev/video{self.device_index} ! "
|
|
317
|
+
"video/x-raw,format=BGR ! "
|
|
318
|
+
"appsink drop=1 max-buffers=1"
|
|
319
|
+
)
|
|
320
|
+
cap = cv2.VideoCapture(gst_pipeline, cv2.CAP_GSTREAMER)
|
|
321
|
+
if cap.isOpened():
|
|
322
|
+
logging.info(f"✅ [APP] Using GStreamer backend for device {self.device_index}")
|
|
323
|
+
except Exception as e:
|
|
324
|
+
logging.warning(f"⚠️ [APP] GStreamer failed, falling back to default: {e}")
|
|
325
|
+
cap = None
|
|
326
|
+
|
|
327
|
+
if not cap or not cap.isOpened():
|
|
328
|
+
cap = cv2.VideoCapture(self.device_index)
|
|
329
|
+
if cap.isOpened():
|
|
330
|
+
logging.info(f"✅ [APP] Using default backend for device {self.device_index}")
|
|
331
|
+
|
|
292
332
|
if not cap.isOpened():
|
|
293
333
|
logging.error(f"❌ [APP] Failed to open device {self.device_index} with OpenCV")
|
|
294
334
|
return False
|
|
295
335
|
|
|
296
|
-
# Set buffer size to reduce latency
|
|
297
336
|
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
|
|
298
337
|
|
|
299
|
-
# Get camera properties
|
|
300
338
|
original_fps = cap.get(cv2.CAP_PROP_FPS)
|
|
301
339
|
self.fps = original_fps if original_fps > 0 else 30
|
|
302
340
|
|
|
303
|
-
# Test reading a frame to ensure camera works
|
|
304
341
|
ret, test_frame = cap.read()
|
|
305
342
|
if not ret or test_frame is None:
|
|
306
343
|
logging.error(f"❌ [APP] Failed to read test frame from device {self.device_index}")
|
|
@@ -372,11 +409,19 @@ class DirectDeviceToRTMPStreamer:
|
|
|
372
409
|
if not self.is_active():
|
|
373
410
|
return
|
|
374
411
|
|
|
375
|
-
# Resize frame if necessary
|
|
376
412
|
if frame.shape[1] > 1024:
|
|
377
|
-
|
|
413
|
+
if self.use_cuda:
|
|
414
|
+
try:
|
|
415
|
+
gpu_frame = cv2.cuda_GpuMat()
|
|
416
|
+
gpu_frame.upload(frame)
|
|
417
|
+
gpu_resized = cv2.cuda.resize(gpu_frame, (self.width, self.height), interpolation=cv2.INTER_AREA)
|
|
418
|
+
frame = gpu_resized.download()
|
|
419
|
+
except Exception as e:
|
|
420
|
+
logging.warning(f"⚠️ GPU resize failed, falling back to CPU: {e}")
|
|
421
|
+
frame = cv2.resize(frame, (self.width, self.height), interpolation=cv2.INTER_AREA)
|
|
422
|
+
else:
|
|
423
|
+
frame = cv2.resize(frame, (self.width, self.height), interpolation=cv2.INTER_AREA)
|
|
378
424
|
|
|
379
|
-
# Send frame to FFmpeg
|
|
380
425
|
if self.ffmpeg_process and self.ffmpeg_process.stdin:
|
|
381
426
|
self.ffmpeg_process.stdin.write(frame.tobytes())
|
|
382
427
|
|
|
@@ -81,7 +81,6 @@ class WorkerSourceClient(GrpcClientBase):
|
|
|
81
81
|
"""Handle source that exists locally but might need updates."""
|
|
82
82
|
changes = []
|
|
83
83
|
|
|
84
|
-
# Check for field changes and log them
|
|
85
84
|
if existing_source.name != source.name:
|
|
86
85
|
changes.append(f"name: '{existing_source.name}' → '{source.name}'")
|
|
87
86
|
if existing_source.worker_id != source.worker_id:
|
|
@@ -100,14 +99,23 @@ class WorkerSourceClient(GrpcClientBase):
|
|
|
100
99
|
self.download_source_file(source)
|
|
101
100
|
|
|
102
101
|
changes.append(f"file_path: {existing_source.file_path} → {source.file_path}")
|
|
102
|
+
|
|
103
|
+
if existing_source.resolution != source.resolution:
|
|
104
|
+
changes.append(f"resolution: {existing_source.resolution} → {source.resolution}")
|
|
105
|
+
if existing_source.status_code != source.status_code:
|
|
106
|
+
changes.append(f"status_code: {existing_source.status_code} → {source.status_code}")
|
|
107
|
+
if existing_source.frame_rate != source.frame_rate:
|
|
108
|
+
changes.append(f"frame_rate: {existing_source.frame_rate} → {source.frame_rate}")
|
|
103
109
|
|
|
104
110
|
if changes:
|
|
105
|
-
# Update existing record
|
|
106
111
|
existing_source.name = source.name
|
|
107
112
|
existing_source.worker_id = source.worker_id
|
|
108
113
|
existing_source.type_code = source.type_code
|
|
109
114
|
existing_source.url = source.url
|
|
110
115
|
existing_source.file_path = source.file_path
|
|
116
|
+
existing_source.resolution = source.resolution
|
|
117
|
+
existing_source.status_code = source.status_code
|
|
118
|
+
existing_source.frame_rate = source.frame_rate
|
|
111
119
|
|
|
112
120
|
updated_sources.append(existing_source)
|
|
113
121
|
changed_records.append(f"🔄 [APP] [UPDATE] Worker Source ID {source.id}: " + ", ".join(changes))
|
|
@@ -120,7 +128,10 @@ class WorkerSourceClient(GrpcClientBase):
|
|
|
120
128
|
worker_id=source.worker_id,
|
|
121
129
|
type_code=source.type_code,
|
|
122
130
|
file_path=source.file_path,
|
|
123
|
-
url=source.url
|
|
131
|
+
url=source.url,
|
|
132
|
+
resolution=source.resolution,
|
|
133
|
+
status_code=source.status_code,
|
|
134
|
+
frame_rate=source.frame_rate
|
|
124
135
|
)
|
|
125
136
|
new_sources.append(new_record)
|
|
126
137
|
logger.info(f"🆕 [APP] [INSERT] Added Worker Source ID {source.id} - {source.name}")
|
|
@@ -238,12 +238,10 @@ class WorkerSourcePipelineClient(GrpcClientBase):
|
|
|
238
238
|
logging.error(f"Video file does not exist: {file_path}")
|
|
239
239
|
return None
|
|
240
240
|
pos = self._get_current_video_position(str(file_path))
|
|
241
|
-
logging.info(f"🎬 [APP] Capturing video frame at {pos:.2f}s from {file_path}")
|
|
242
241
|
cmd = self._build_ffmpeg_cmd_video_file(str(file_path), pos)
|
|
243
242
|
|
|
244
243
|
elif stream_type == "image_file":
|
|
245
244
|
file_path = self.source_file_path / os.path.basename(url)
|
|
246
|
-
logging.info(f"🖼️ [APP] Capturing image frame from {file_path}")
|
|
247
245
|
cmd = self._build_ffmpeg_cmd_image_file(str(file_path))
|
|
248
246
|
|
|
249
247
|
else:
|
|
@@ -104,10 +104,8 @@ class WorkerSourceUpdater:
|
|
|
104
104
|
if frame_rate is None and source.frame_rate is not None:
|
|
105
105
|
frame_rate = source.frame_rate
|
|
106
106
|
|
|
107
|
-
# .NET Compatible time
|
|
108
107
|
worker_timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z"
|
|
109
108
|
|
|
110
|
-
# Compare with local database values
|
|
111
109
|
if (
|
|
112
110
|
source.resolution != resolution or
|
|
113
111
|
source.frame_rate != frame_rate or
|
|
@@ -120,13 +118,11 @@ class WorkerSourceUpdater:
|
|
|
120
118
|
f"status: {source.status_code} -> {status_code}]"
|
|
121
119
|
)
|
|
122
120
|
|
|
123
|
-
# Update local database
|
|
124
121
|
source.resolution = resolution
|
|
125
122
|
source.frame_rate = frame_rate
|
|
126
123
|
source.status_code = status_code
|
|
127
124
|
updated_records.append(source)
|
|
128
125
|
|
|
129
|
-
# Send gRPC update request (client is thread-safe)
|
|
130
126
|
response = self.client.update_worker_source(
|
|
131
127
|
worker_source_id=source.id,
|
|
132
128
|
resolution=resolution,
|
|
@@ -189,7 +189,7 @@ class DataSenderWorker:
|
|
|
189
189
|
|
|
190
190
|
if stats:
|
|
191
191
|
total_sent = sum(stats.values())
|
|
192
|
-
logger.info(f"📤 [APP] Sent {total_sent} dataset frames
|
|
192
|
+
logger.info(f"📤 [APP] Sent {total_sent} dataset frames")
|
|
193
193
|
else:
|
|
194
194
|
pending_count = self.dataset_frame_sender.get_pending_frame_count()
|
|
195
195
|
if pending_count > 0:
|
|
@@ -149,12 +149,6 @@ class DatasetSourceThread:
|
|
|
149
149
|
|
|
150
150
|
frame_bytes = self.pipeline_client._get_single_frame_bytes(source_url)
|
|
151
151
|
|
|
152
|
-
if frame_bytes and stream_type == "video_file":
|
|
153
|
-
status = self.pipeline_client.get_video_positions_status()
|
|
154
|
-
for video_path, info in status.items():
|
|
155
|
-
if info["duration"]:
|
|
156
|
-
logger.info(f"📊 [APP] Video progress: {info['progress_percent']:.1f}% ({info['current_position']:.2f}s / {info['duration']:.2f}s)")
|
|
157
|
-
|
|
158
152
|
return frame_bytes
|
|
159
153
|
except Exception as e:
|
|
160
154
|
logger.error(f"🚨 [APP] Error getting frame from source {source_url}: {e}", exc_info=True)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nedo-vision-worker
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.7
|
|
4
4
|
Summary: Nedo Vision Worker Service 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>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
nedo_vision_worker/__init__.py,sha256=
|
|
1
|
+
nedo_vision_worker/__init__.py,sha256=SoFfn_lr0mgpPFESSvD3Wg3PDoyi4bwdY5gGVadDJPg,203
|
|
2
2
|
nedo_vision_worker/cli.py,sha256=ddWspJmSgVkcUYvRdkvTtMNuMTDvNCqLLuMVU9KE3Ik,7457
|
|
3
3
|
nedo_vision_worker/doctor.py,sha256=wNkpe8gLVd76Y_ViyK2h1ZFdqeSl37MnzZN5frWKu30,48410
|
|
4
4
|
nedo_vision_worker/worker_service.py,sha256=9zz8hKwDwqwpfS0KPQfftGJtRci0uj_wiwcr_TGf-E0,11039
|
|
@@ -24,19 +24,19 @@ nedo_vision_worker/models/worker_source_pipeline_config.py,sha256=dGYTpcTFFu6pmG
|
|
|
24
24
|
nedo_vision_worker/models/worker_source_pipeline_debug.py,sha256=6S7TkN37FrAT4VwsEB38DWSad7QfvNhsOGtSEK8D1Qs,594
|
|
25
25
|
nedo_vision_worker/models/worker_source_pipeline_detection.py,sha256=p6CJsiVCKprTYrNxJsiTB8njXdHkjZKVEyBceRVE6fY,560
|
|
26
26
|
nedo_vision_worker/protos/AIModelService_pb2.py,sha256=0S0fUgyMHmfS6FVGuZ2Okz71f61vPXLoU8tosIzf7sI,3545
|
|
27
|
-
nedo_vision_worker/protos/AIModelService_pb2_grpc.py,sha256=
|
|
27
|
+
nedo_vision_worker/protos/AIModelService_pb2_grpc.py,sha256=gLyVJ08Wy-GhmfEX3kGZgIOnmyIhs4pPu3jUErt2g3Y,6075
|
|
28
28
|
nedo_vision_worker/protos/DatasetSourceService_pb2.py,sha256=plHyTJvGqWCtup2vI7Y_NocITV-q47aCV3xddgwrhRQ,3362
|
|
29
|
-
nedo_vision_worker/protos/DatasetSourceService_pb2_grpc.py,sha256=
|
|
29
|
+
nedo_vision_worker/protos/DatasetSourceService_pb2_grpc.py,sha256=gwtQGTttFxXDUdyT8chQZ28RwJ10puR915pA56yXIKE,6264
|
|
30
30
|
nedo_vision_worker/protos/HumanDetectionService_pb2.py,sha256=ltufKuBaXkOChbqOUVvbcRNxNTiaEj204QqktBcMstU,3277
|
|
31
|
-
nedo_vision_worker/protos/HumanDetectionService_pb2_grpc.py,sha256=
|
|
31
|
+
nedo_vision_worker/protos/HumanDetectionService_pb2_grpc.py,sha256=4ZJXy7NE9SZbaFp9qBFo6CERIXV28z5mMG32Kx0VolY,6259
|
|
32
32
|
nedo_vision_worker/protos/PPEDetectionService_pb2.py,sha256=c1v864-pcMiHekQU7kxqV0wQg-p8zloDPVegF8JHd5c,3582
|
|
33
|
-
nedo_vision_worker/protos/PPEDetectionService_pb2_grpc.py,sha256=
|
|
33
|
+
nedo_vision_worker/protos/PPEDetectionService_pb2_grpc.py,sha256=BT_NezGVweaHYadG30CUQNyatQbXMaI3ZNSOXfWs49A,6185
|
|
34
34
|
nedo_vision_worker/protos/VisionWorkerService_pb2.py,sha256=d88SWd1orMP--zvhuJCFpGhadoxeC0FPprh6zZPt4pE,7146
|
|
35
|
-
nedo_vision_worker/protos/VisionWorkerService_pb2_grpc.py,sha256=
|
|
35
|
+
nedo_vision_worker/protos/VisionWorkerService_pb2_grpc.py,sha256=21fAcktkwTfY8oz1FZAR23bq4le0I1WBy-ZzwGNqO_E,18936
|
|
36
36
|
nedo_vision_worker/protos/WorkerSourcePipelineService_pb2.py,sha256=61xX4pKm_eBDdgpPpQtLcB45cDOD0ON6n5syE1_iKrM,7058
|
|
37
|
-
nedo_vision_worker/protos/WorkerSourcePipelineService_pb2_grpc.py,sha256=
|
|
38
|
-
nedo_vision_worker/protos/WorkerSourceService_pb2.py,sha256=
|
|
39
|
-
nedo_vision_worker/protos/WorkerSourceService_pb2_grpc.py,sha256=
|
|
37
|
+
nedo_vision_worker/protos/WorkerSourcePipelineService_pb2_grpc.py,sha256=eqr6BVSyxIoKzRXnrsPH7koaIOj3pK53zj1W3ZKBOrY,15383
|
|
38
|
+
nedo_vision_worker/protos/WorkerSourceService_pb2.py,sha256=CxPGRi5L0R5jnHyAH5e5aVPZKnJNZBqkp-MrtM6Qqqk,4050
|
|
39
|
+
nedo_vision_worker/protos/WorkerSourceService_pb2_grpc.py,sha256=ArcAFizg5IkKpjBL3YEg4pyQXPIYi5k1TW1j53KSlwk,8313
|
|
40
40
|
nedo_vision_worker/protos/__init__.py,sha256=Nqnn8clbgv-5l0PgxcTOldg8mkMKrFn4TvPL-rYUUGg,1
|
|
41
41
|
nedo_vision_worker/repositories/AIModelRepository.py,sha256=35cQ2EnJvMdArewumPrVIaiwueGy6cXU_g5J1Qcj6_Y,1415
|
|
42
42
|
nedo_vision_worker/repositories/DatasetSourceRepository.py,sha256=MOUbXY1-7WUPhY15aMpdXl6rl0afSvu3Cq8jNtp9nzM,8595
|
|
@@ -50,7 +50,7 @@ nedo_vision_worker/repositories/__init__.py,sha256=Nqnn8clbgv-5l0PgxcTOldg8mkMKr
|
|
|
50
50
|
nedo_vision_worker/services/AIModelClient.py,sha256=lxRNax6FR-pV0G1NpJnlaqjbQeu3kRolIUNSw1RkoZA,15406
|
|
51
51
|
nedo_vision_worker/services/ConnectionInfoClient.py,sha256=toC9zuY2Hrx1Cwq8Gycy_iFlaG1DvFT4qewlLlitpEQ,2214
|
|
52
52
|
nedo_vision_worker/services/DatasetSourceClient.py,sha256=O5a7onxFl0z47zXaMXWxHAMPuuc-i_vzkd2w5fwrukc,3319
|
|
53
|
-
nedo_vision_worker/services/DirectDeviceToRTMPStreamer.py,sha256=
|
|
53
|
+
nedo_vision_worker/services/DirectDeviceToRTMPStreamer.py,sha256=Ypcc0fh1WiUMkICN_KRRAvGmeGkgF8jQ06gfiRYReW4,24747
|
|
54
54
|
nedo_vision_worker/services/FileToRTMPServer.py,sha256=0hY5pmeAzLw_d3uPR2Qp6gSAYb4rJHiAunuNe08OvkM,2870
|
|
55
55
|
nedo_vision_worker/services/GrpcClientBase.py,sha256=hPyxOGw3aGSW1FhmY3wp3Iq8U1MArXBmvEMdmd63NZ4,6827
|
|
56
56
|
nedo_vision_worker/services/GrpcClientManager.py,sha256=DLXekmxlQogLo8V9-TNDXtyHT_UG-BaggqwsIups55k,5568
|
|
@@ -65,9 +65,9 @@ nedo_vision_worker/services/SystemUsageClient.py,sha256=Yf77dooQeNh6CDL5FkWVrX95
|
|
|
65
65
|
nedo_vision_worker/services/SystemWideDeviceCoordinator.py,sha256=9zBJMCbTMZS7gwN67rFpoUiTr82El2rpIO7DKFzeMjM,9417
|
|
66
66
|
nedo_vision_worker/services/VideoSharingDaemon.py,sha256=hYMjUIKNUVT1qSxuUuHN-7Bd85MDkxfqslxDLe2PBYQ,29721
|
|
67
67
|
nedo_vision_worker/services/VideoStreamClient.py,sha256=QSgUV3LijYrNdnBG1ylABOdUaSatQamfXaqJhAiol9M,7260
|
|
68
|
-
nedo_vision_worker/services/WorkerSourceClient.py,sha256=
|
|
69
|
-
nedo_vision_worker/services/WorkerSourcePipelineClient.py,sha256=
|
|
70
|
-
nedo_vision_worker/services/WorkerSourceUpdater.py,sha256=
|
|
68
|
+
nedo_vision_worker/services/WorkerSourceClient.py,sha256=rS5X1Se51YWXTkEiDUJbTSYgtrzpom6811aZ1SXIwkw,9939
|
|
69
|
+
nedo_vision_worker/services/WorkerSourcePipelineClient.py,sha256=9qj65uBujCVoUE3kqGkc7ztLKW0L28_POZIDY3e1rhk,18058
|
|
70
|
+
nedo_vision_worker/services/WorkerSourceUpdater.py,sha256=RUNkiL1FRrKkW4UDm4i4i8ShgJy__MhTTrNlfouDAZc,8892
|
|
71
71
|
nedo_vision_worker/services/WorkerStatusClient.py,sha256=7kC5EZjEBwWtHOE6UQ29OPCpYnv_6HSuH7Tc0alK_2Q,2531
|
|
72
72
|
nedo_vision_worker/services/__init__.py,sha256=Nqnn8clbgv-5l0PgxcTOldg8mkMKrFn4TvPL-rYUUGg,1
|
|
73
73
|
nedo_vision_worker/util/EncoderSelector.py,sha256=-9lZwVmiKzJr1cELeuCXi-jRonty2bpociZq4KDScmA,3399
|
|
@@ -80,10 +80,10 @@ nedo_vision_worker/util/SystemMonitor.py,sha256=2kkqj9mOlywAS2fHdN1TaIXSXvCApcIH
|
|
|
80
80
|
nedo_vision_worker/util/VideoProbeUtil.py,sha256=cF-vJ7hIDlXfEJby2a0s9tqwkPGVz_6B3Vv4D5pMmIw,12876
|
|
81
81
|
nedo_vision_worker/util/__init__.py,sha256=Nqnn8clbgv-5l0PgxcTOldg8mkMKrFn4TvPL-rYUUGg,1
|
|
82
82
|
nedo_vision_worker/worker/CoreActionWorker.py,sha256=lb7zPY3yui6I3F4rX4Ii7JwpWZahLEO72rh3iWOgFmg,5441
|
|
83
|
-
nedo_vision_worker/worker/DataSenderWorker.py,sha256=
|
|
83
|
+
nedo_vision_worker/worker/DataSenderWorker.py,sha256=TpMLhjpuuW-70TP6BzKpR9irPqVr9dDyFsBAA5s2N3U,8784
|
|
84
84
|
nedo_vision_worker/worker/DataSyncWorker.py,sha256=LmDPt2J1frmXwuR46L6b0MjlFOHfgG-4_0MGQa78zF4,6288
|
|
85
85
|
nedo_vision_worker/worker/DatasetFrameSender.py,sha256=1SFYj8LJFNi-anBTapsbq8U_NGMM7mnoMKg9NeFAHys,8087
|
|
86
|
-
nedo_vision_worker/worker/DatasetFrameWorker.py,sha256=
|
|
86
|
+
nedo_vision_worker/worker/DatasetFrameWorker.py,sha256=vzl6bab58a8MyXm6lfDom-kuGKwRj70moFIizePAnU0,18931
|
|
87
87
|
nedo_vision_worker/worker/PPEDetectionManager.py,sha256=sXeOjvhCzi4oUhDZwH5-8DSxI9b__Jp0de8QksgaYGw,6063
|
|
88
88
|
nedo_vision_worker/worker/PipelineActionWorker.py,sha256=xgvryjKtEsMj4BKqWzDIaK_lFny-DfMCj5Y2DxHnWww,5651
|
|
89
89
|
nedo_vision_worker/worker/PipelineImageWorker.py,sha256=J8VBUG0cwcH3qOJp2zTl30B-XhmPFyvJLjxitKJYq0E,5642
|
|
@@ -94,8 +94,8 @@ nedo_vision_worker/worker/SystemUsageManager.py,sha256=mkh4sT-HkIEY1CJHMEG6LP9AT
|
|
|
94
94
|
nedo_vision_worker/worker/VideoStreamWorker.py,sha256=5n6v1PNO7IB-jj_McALLkUP-cBjJoIEw4UiSAs3vTb0,7606
|
|
95
95
|
nedo_vision_worker/worker/WorkerManager.py,sha256=2bxXi19fp3p1qjYBStYRdVVgko8dnevXx1_M_sqH5og,5521
|
|
96
96
|
nedo_vision_worker/worker/__init__.py,sha256=Nqnn8clbgv-5l0PgxcTOldg8mkMKrFn4TvPL-rYUUGg,1
|
|
97
|
-
nedo_vision_worker-1.3.
|
|
98
|
-
nedo_vision_worker-1.3.
|
|
99
|
-
nedo_vision_worker-1.3.
|
|
100
|
-
nedo_vision_worker-1.3.
|
|
101
|
-
nedo_vision_worker-1.3.
|
|
97
|
+
nedo_vision_worker-1.3.7.dist-info/METADATA,sha256=PFsTaJvY-oOl6159V_lzBNIcFG7lKODrjYWNsYqzPAU,14728
|
|
98
|
+
nedo_vision_worker-1.3.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
99
|
+
nedo_vision_worker-1.3.7.dist-info/entry_points.txt,sha256=LrglS-8nCi8C_PL_pa6uxdgCe879hBETHDVXAckvs-8,60
|
|
100
|
+
nedo_vision_worker-1.3.7.dist-info/top_level.txt,sha256=vgilhlkyD34YsEKkaBabmhIpcKSvF3XpzD2By68L-XI,19
|
|
101
|
+
nedo_vision_worker-1.3.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|