1515 MODELS_CACHE_AUTH_CACHE_MAX_SIZE ,
1616 MODELS_CACHE_AUTH_CACHE_TTL ,
1717 MODELS_CACHE_AUTH_ENABLED ,
18+ PRELOAD_HF_IDS ,
1819 PROJECT ,
1920 ROBOFLOW_INTERNAL_SERVICE_SECRET ,
2021 WEBRTC_MODAL_APP_NAME ,
4445from inference .core .interfaces .webrtc_worker .webrtc import (
4546 init_rtc_peer_connection_with_loop ,
4647)
48+ from inference .core .roboflow_api import get_roboflow_workspace
4749from inference .core .version import __version__
4850from inference .usage_tracking .collector import usage_collector
4951from inference .usage_tracking .plan_details import WebRTCPlan
5557
5658
5759if modal is not None :
60+ docker_tag : str = WEBRTC_MODAL_IMAGE_TAG if WEBRTC_MODAL_IMAGE_TAG else __version__
5861 # https://modal.com/docs/reference/modal.Image
5962 video_processing_image = (
60- modal .Image .from_registry (
61- f"{ WEBRTC_MODAL_IMAGE_NAME } :{ WEBRTC_MODAL_IMAGE_TAG if WEBRTC_MODAL_IMAGE_TAG else __version__ } "
62- )
63+ modal .Image .from_registry (f"{ WEBRTC_MODAL_IMAGE_NAME } :{ docker_tag } " )
6364 .pip_install ("modal" )
6465 .entrypoint ([])
6566 )
7172 app = modal .App (
7273 name = WEBRTC_MODAL_APP_NAME ,
7374 image = video_processing_image ,
75+ tags = {"tag" : docker_tag },
7476 )
7577
7678 decorator_kwargs = {
8183 "enable_memory_snapshot" : WEBRTC_MODAL_FUNCTION_ENABLE_MEMORY_SNAPSHOT ,
8284 "max_inputs" : WEBRTC_MODAL_FUNCTION_MAX_INPUTS ,
8385 "env" : {
84- "ROBOFLOW_INTERNAL_SERVICE_SECRET" : ROBOFLOW_INTERNAL_SERVICE_SECRET ,
85- "ROBOFLOW_INTERNAL_SERVICE_NAME" : WEBRTC_MODAL_ROBOFLOW_INTERNAL_SERVICE_NAME ,
86- "PROJECT" : PROJECT ,
87- "LOG_LEVEL" : LOG_LEVEL ,
88- "INTERNAL_WEIGHTS_URL_SUFFIX" : INTERNAL_WEIGHTS_URL_SUFFIX ,
89- "MODELS_CACHE_AUTH_ENABLED" : str (MODELS_CACHE_AUTH_ENABLED ),
90- "MODELS_CACHE_AUTH_CACHE_TTL" : str (MODELS_CACHE_AUTH_CACHE_TTL ),
91- "MODELS_CACHE_AUTH_CACHE_MAX_SIZE" : str (MODELS_CACHE_AUTH_CACHE_MAX_SIZE ),
92- "METRICS_ENABLED" : "False" ,
9386 "ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS" : str (
9487 ALLOW_CUSTOM_PYTHON_EXECUTION_IN_WORKFLOWS
9588 ),
96- "WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE" : WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE ,
89+ "ALLOW_WORKFLOW_BLOCKS_ACCESSING_ENVIRONMENTAL_VARIABLES" : "False" ,
90+ "DISABLE_INFERENCE_CACHE" : "True" ,
91+ "DISABLE_VERSION_CHECK" : "True" ,
92+ "HF_HOME" : Path (MODEL_CACHE_DIR ).joinpath ("hf_home" ).as_posix (),
93+ "INTERNAL_WEIGHTS_URL_SUFFIX" : INTERNAL_WEIGHTS_URL_SUFFIX ,
94+ "METRICS_ENABLED" : "False" ,
9795 "MODAL_TOKEN_ID" : MODAL_TOKEN_ID ,
9896 "MODAL_TOKEN_SECRET" : MODAL_TOKEN_SECRET ,
9997 "MODAL_WORKSPACE_NAME" : MODAL_WORKSPACE_NAME ,
100- "ALLOW_WORKFLOW_BLOCKS_ACCESSING_ENVIRONMENTAL_VARIABLES" : "False" ,
101- "DISABLE_VERSION_CHECK" : "True" ,
10298 "MODEL_CACHE_DIR" : MODEL_CACHE_DIR ,
103- "HF_HOME" : Path (MODEL_CACHE_DIR ).joinpath ("hf_home" ).as_posix (),
99+ "MODELS_CACHE_AUTH_CACHE_MAX_SIZE" : str (MODELS_CACHE_AUTH_CACHE_MAX_SIZE ),
100+ "MODELS_CACHE_AUTH_CACHE_TTL" : str (MODELS_CACHE_AUTH_CACHE_TTL ),
101+ "MODELS_CACHE_AUTH_ENABLED" : str (MODELS_CACHE_AUTH_ENABLED ),
102+ "LOG_LEVEL" : LOG_LEVEL ,
103+ "ONNXRUNTIME_EXECUTION_PROVIDERS" : "[CUDAExecutionProvider,CPUExecutionProvider]" ,
104+ "PRELOAD_HF_IDS" : PRELOAD_HF_IDS ,
105+ "PROJECT" : PROJECT ,
106+ "ROBOFLOW_INTERNAL_SERVICE_NAME" : WEBRTC_MODAL_ROBOFLOW_INTERNAL_SERVICE_NAME ,
107+ "ROBOFLOW_INTERNAL_SERVICE_SECRET" : ROBOFLOW_INTERNAL_SERVICE_SECRET ,
108+ "WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE" : WORKFLOWS_CUSTOM_PYTHON_EXECUTION_MODE ,
104109 "TELEMETRY_USE_PERSISTENT_QUEUE" : "False" ,
105- "DISABLE_INFERENCE_CACHE" : "True" ,
106- "WEBRTC_MODAL_FUNCTION_GPU" : WEBRTC_MODAL_FUNCTION_GPU ,
107- "WEBRTC_MODAL_FUNCTION_SCALEDOWN_WINDOW" : str (
108- WEBRTC_MODAL_FUNCTION_SCALEDOWN_WINDOW
109- ),
110110 "WEBRTC_MODAL_FUNCTION_BUFFER_CONTAINERS" : str (
111111 WEBRTC_MODAL_FUNCTION_BUFFER_CONTAINERS
112112 ),
113+ "WEBRTC_MODAL_FUNCTION_GPU" : WEBRTC_MODAL_FUNCTION_GPU ,
113114 "WEBRTC_MODAL_FUNCTION_MIN_CONTAINERS" : str (
114115 WEBRTC_MODAL_FUNCTION_MIN_CONTAINERS
115116 ),
117+ "WEBRTC_MODAL_FUNCTION_SCALEDOWN_WINDOW" : str (
118+ WEBRTC_MODAL_FUNCTION_SCALEDOWN_WINDOW
119+ ),
116120 "WEBRTC_MODAL_FUNCTION_TIME_LIMIT" : str (WEBRTC_MODAL_FUNCTION_TIME_LIMIT ),
117121 "WEBRTC_MODAL_IMAGE_NAME" : WEBRTC_MODAL_IMAGE_NAME ,
118122 "WEBRTC_MODAL_IMAGE_TAG" : WEBRTC_MODAL_IMAGE_TAG ,
119123 "WEBRTC_MODAL_RTSP_PLACEHOLDER" : WEBRTC_MODAL_RTSP_PLACEHOLDER ,
120124 "WEBRTC_MODAL_RTSP_PLACEHOLDER_URL" : WEBRTC_MODAL_RTSP_PLACEHOLDER_URL ,
121- "ONNXRUNTIME_EXECUTION_PROVIDERS" : "[CUDAExecutionProvider,CPUExecutionProvider]" ,
122125 },
123126 "volumes" : {MODEL_CACHE_DIR : rfcache_volume },
124127 }
125128
126129 class RTCPeerConnectionModal :
127130 _webrtc_request : Optional [WebRTCWorkerRequest ] = modal .parameter (default = None )
128- _exec_session_started : Optional [datetime .datetime ] = modal .parameter (
129- default = None
130- )
131- _exec_session_stopped : Optional [datetime .datetime ] = modal .parameter (
132- default = None
133- )
134131
135132 @modal .method ()
136133 def rtc_peer_connection_modal (
@@ -139,6 +136,12 @@ def rtc_peer_connection_modal(
139136 q : modal .Queue ,
140137 ):
141138 logger .info ("*** Spawning %s:" , self .__class__ .__name__ )
139+ logger .info ("Inference tag: %s" , docker_tag )
140+ _exec_session_started = datetime .datetime .now ()
141+ webrtc_request .processing_session_started = _exec_session_started
142+ logger .info (
143+ "WebRTC session started at %s" , _exec_session_started .isoformat ()
144+ )
142145 logger .info (
143146 "webrtc_realtime_processing: %s" ,
144147 webrtc_request .webrtc_realtime_processing ,
@@ -171,18 +174,11 @@ def send_answer(obj: WebRTCWorkerResult):
171174 send_answer = send_answer ,
172175 )
173176 )
174-
175- # https://modal.com/docs/reference/modal.enter
176- # Modal usage calculation is relying on no concurrency and no hot instances
177- @modal .enter ()
178- def start (self ):
179- self ._exec_session_started = datetime .datetime .now ()
180-
181- @modal .exit ()
182- def stop (self ):
183- if not self ._webrtc_request :
184- return
185- self ._exec_session_stopped = datetime .datetime .now ()
177+ _exec_session_stopped = datetime .datetime .now ()
178+ logger .info (
179+ "WebRTC session stopped at %s" ,
180+ _exec_session_stopped .isoformat (),
181+ )
186182 workflow_id = self ._webrtc_request .workflow_configuration .workflow_id
187183 if not workflow_id :
188184 if self ._webrtc_request .workflow_configuration .workflow_specification :
@@ -195,16 +191,38 @@ def stop(self):
195191 # requested plan is guaranteed to be set due to validation in spawn_rtc_peer_connection_modal
196192 webrtc_plan = self ._webrtc_request .requested_plan
197193
194+ video_source = "realtime browser stream"
195+ if self ._webrtc_request .rtsp_url :
196+ video_source = "rtsp"
197+ elif not self ._webrtc_request .webrtc_realtime_processing :
198+ video_source = "buffered browser stream"
199+
198200 usage_collector .record_usage (
199201 source = workflow_id ,
200202 category = "modal" ,
201203 api_key = self ._webrtc_request .api_key ,
202- resource_details = {"plan" : webrtc_plan },
204+ resource_details = {
205+ "plan" : webrtc_plan ,
206+ "billable" : True ,
207+ "video_source" : video_source ,
208+ },
203209 execution_duration = (
204- self . _exec_session_stopped - self . _exec_session_started
210+ _exec_session_stopped - _exec_session_started
205211 ).total_seconds (),
206212 )
207213 usage_collector .push_usage_payloads ()
214+ logger .info ("Function completed" )
215+
216+ # https://modal.com/docs/reference/modal.enter
217+ # https://modal.com/docs/guide/memory-snapshot#gpu-memory-snapshot
218+ @modal .enter (snap = True )
219+ def start (self ):
220+ # TODO: pre-load models
221+ logger .info ("Starting container" )
222+
223+ @modal .exit ()
224+ def stop (self ):
225+ logger .info ("Stopping container" )
208226
209227 # Modal derives function name from class name
210228 # https://modal.com/docs/reference/modal.App#cls
@@ -217,7 +235,6 @@ class RTCPeerConnectionModalCPU(RTCPeerConnectionModal):
217235 @app .cls (
218236 ** {
219237 ** decorator_kwargs ,
220- "enable_memory_snapshot" : False ,
221238 "gpu" : WEBRTC_MODAL_FUNCTION_GPU , # https://modal.com/docs/guide/gpu#specifying-gpu-type
222239 "experimental_options" : {
223240 "enable_gpu_snapshot" : WEBRTC_MODAL_FUNCTION_ENABLE_MEMORY_SNAPSHOT
@@ -266,7 +283,21 @@ def spawn_rtc_peer_connection_modal(
266283 )
267284 except modal .exception .NotFoundError :
268285 logger .info ("Deploying webrtc modal app %s" , WEBRTC_MODAL_APP_NAME )
269- app .deploy (name = WEBRTC_MODAL_APP_NAME , client = client )
286+ app .deploy (name = WEBRTC_MODAL_APP_NAME , client = client , tag = docker_tag )
287+
288+ workspace_id = webrtc_request .workflow_configuration .workspace_name
289+ if not workspace_id :
290+ try :
291+ workspace_id = get_roboflow_workspace (api_key = webrtc_request .api_key )
292+ webrtc_request .workflow_configuration .workspace_name = workspace_id
293+ except Exception :
294+ pass
295+
296+ tags = {"tag" : docker_tag }
297+ if workspace_id :
298+ tags ["workspace_id" ] = workspace_id
299+
300+ # TODO: tag function run
270301
271302 if webrtc_request .requested_gpu :
272303 RTCPeerConnectionModal = RTCPeerConnectionModalGPU
0 commit comments