1+ """
2+ # Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
3+ # This software is dual-licensed to you under the Universal Permissive
4+ # License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or
5+ # Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0.
6+ # You may choose either license.
7+
8+ ##########################################################################
9+ # analyze_video_demo_cv2.py
10+ #
11+ # @author: Anand Jha (anand.j.jha@oracle.com), Aug 2025
12+ #
13+ # Supports Python 3
14+ ##########################################################################
15+ # Info:
16+ usage: stream_video_demo.py [-h] --compartment-id [COMPARTMENT_ID] --camera-url [CAMERA_URL] --namespace [NAMESPACE]
17+ --bucket [BUCKET] --prefix [PREFIX] --feature [FEATURE] [-v]
18+
19+ optional arguments:
20+ -h, --help show this help message and exit
21+ -v, --verbose Print logs
22+ --compartment-id COMPARTMENT_OCID compartment for the resources
23+ --camera-url CAMERA_URL camera url for the stream
24+ --namespace NAMESPACE namespace of the Bucket
25+ --bucket BUCKET_NAME bucket name
26+ --prefix PREFIX prefix
27+ --feature FEATURE feature
28+
29+ ##################################################################################
30+ """
31+
32+ import os
33+ import sys
34+ import json
35+ import math
36+ import time
37+ import logging
38+ import argparse
39+ from glob import glob
40+
41+ import oci
42+
43+ class StreamVideo :
44+ """
45+ A class to
46+ """
47+
48+ def __init__ (
49+ self ,
50+ compartment_id : str ,
51+ camera_url : int ,
52+ namespace : str ,
53+ bucket : str ,
54+ prefix : str ,
55+ feature : str ,
56+ subnet_id : str ,
57+ oci_config : dict ,
58+ service_endpoint : str
59+ ):
60+
61+ self .compartment_id = compartment_id
62+ camera_url = camera_url
63+ namespace = namespace
64+ bucket = bucket
65+ prefix = prefix
66+ feature = feature
67+ subnet_id = subnet_id
68+ self .client = oci .ai_vision .AIServiceVisionClient (
69+ config = oci_config ,
70+ service_endpoint = service_endpoint )
71+
72+ self .create_stream_source_details = oci .ai_vision .models .CreateStreamSourceDetails ()
73+ self .create_stream_job_details = oci .ai_vision .models .CreateStreamJobDetails ()
74+ self .create_stream_group_details = oci .ai_vision .models .CreateStreamGroupDetails ()
75+ self .create_vision_private_endpoint_details = oci .ai_vision .models .CreateVisionPrivateEndpointDetails ()
76+ self .private_stream_network_access_deatils = oci .ai_vision .models .PrivateStreamNetworkAccessDetails ()
77+ self .rtsp_source_details = oci .ai_vision .models .RtspSourceDetails ()
78+ self .update_stream_source_details = oci .ai_vision .models .UpdateStreamSourceDetails ()
79+ self .update_stream_job_details = oci .ai_vision .models .UpdateStreamJobDetails ()
80+ self .update_stream_group_details = oci .ai_vision .models .UpdateStreamGroupDetails ()
81+ self .update_vision_private_endpoint_details = oci .ai_vision .models .UpdateVisionPrivateEndpointDetails ()
82+ self .output_location = oci .ai_vision .models .ObjectStorageOutputLocation ()
83+
84+
85+
86+ def create_private_endpoint (self , display_name = "Vision_Private_Endpoint" ):
87+ """
88+
89+ :param display_name: Display name for the Vision Private Endpoint
90+ :return: None
91+ """
92+
93+ self .create_vision_private_endpoint_details .display_name = display_name
94+ self .create_vision_private_endpoint_details .subnet_id = self .subnet_id
95+ self .create_vision_private_endpoint_details .compartment_id = self .compartment_id
96+
97+ create_private_endpoint_request = self .client .create_vision_private_endpoint (self .create_vision_private_endpoint_details )
98+
99+ while True :
100+ create_private_endpoint_work_request = self .client .get_work_request (create_private_endpoint_request .headers ['opc-work-request-id' ])
101+
102+ if create_private_endpoint_work_request .data .status == 'SUCCEEDED' :
103+ return create_private_endpoint_request .data .id
104+ elif create_private_endpoint_work_request .data .status == 'FAILED' :
105+ return None
106+ time .sleep (30 )
107+
108+ def create_Stream_Source (self , vision_private_endpoint_ocid , display_name = "Vision_Stream_Source" ):
109+
110+ self .private_stream_network_access_deatils .stream_access_type = "PRIVATE"
111+ self .private_stream_network_access_deatils .private_endpoint_id = vision_private_endpoint_ocid
112+ self .rtsp_source_details .camera_url = self .camera_url
113+ self .rtsp_source_details .stream_network_access_details = self .private_stream_network_access_deatils
114+
115+ self .create_stream_source_details .compartment_id = compartment_id
116+ self .create_stream_source_details .display_name = display_name
117+ self .create_stream_source_details .stream_source_details = self .rtsp_source_details
118+
119+ create_stream_source_request = self .client .create_stream_source (self .create_stream_source_details )
120+ while True :
121+ create_stream_source_work_request = self .client .get_work_request (create_stream_source_request .headers ['opc-work-request-id' ])
122+
123+ if create_stream_source_work_request .data .status == 'SUCCEEDED' :
124+ return create_stream_source_request .data .id
125+ elif create_stream_source_work_request .data .status == 'FAILED' :
126+ return None
127+ time .sleep (30 )
128+
129+ def create_Stream_Job (self , stream_source_ocid , display_name = "Vision_Stream_Job" ):
130+ self .create_stream_job_details .stream_source_id = stream_source_ocid
131+ # For Object Tracker (Only "face" supported as of now) - commend if not required
132+ self .create_stream_job_details .features = self .feature
133+
134+ self .output_location .namespace_name = self .namespace
135+ self .output_location .bucket_name = self .bucket
136+ self .output_location .prefix = self .prefix
137+
138+ # Choose output location in object storage, make sure you have created the bucket
139+ self .create_stream_job_details .stream_output_location = self .output_location
140+
141+ self .create_stream_job_details .compartment_id = self .compartment_id
142+ self .create_stream_job_details .display_name = display_name
143+
144+ create_stream_job_request = self .client .create_stream_job (self .create_stream_job_details )
145+ while True :
146+ create_stream_job_work_request = self .client .get_work_request (create_stream_job_request .headers ['opc-work-request-id' ])
147+ if create_stream_job_work_request .data .status == 'SUCCEEDED' :
148+ return create_stream_job_request .data .id
149+ if create_stream_job_work_request .data .status == 'FAILED' :
150+ return None
151+ time .sleep (30 )
152+
153+ def start_Stream_Job (self , stream_job_ocid ):
154+ start_stream_job = self .client .start_stream_job (stream_job_ocid )
155+ while True :
156+ start_stream_job_work_request = self .client .get_work_request (start_stream_job .headers ['opc-work-request-id' ])
157+ print (start_stream_job_work_request .data .status )
158+ if start_stream_job_work_request .data .status == 'SUCCEEDED' :
159+ return True
160+ if start_stream_job_work_request .data .status == 'FAILED' :
161+ return False
162+ time .sleep (30 )
163+
164+ def stop_Stream_Job (self , stream_job_ocid ):
165+ stop_stream_job = self .client .start_stream_job (stream_job_ocid )
166+ while True :
167+ stop_stream_job_work_request = self .client .get_work_request (stop_stream_job .headers ['opc-work-request-id' ])
168+ if stop_stream_job_work_request .data .status == 'SUCCEEDED' :
169+ return True
170+ if stop_stream_job_work_request .data .status == 'FAILED' :
171+ return False
172+ time .sleep (30 )
173+
174+ def delete_Stream_Job (self , stream_job_ocid ):
175+ delete_stream_job = self .client .delete_stream_job (stream_job_ocid )
176+ while True :
177+ delete_stream_job_work_request = self .client .get_work_request (delete_stream_job .headers ['opc-work-request-id' ])
178+ if delete_stream_job_work_request .data .status == 'SUCCEEDED' :
179+ return True
180+ if delete_stream_job_work_request .data .status == 'FAILED' :
181+ return False
182+ time .sleep (30 )
183+
184+
185+ def delete_Stream_Source (self , stream_source_ocid ):
186+ delete_stream_source = self .client .delete_stream_job (stream_source_ocid )
187+ while True :
188+ delete_stream_source_work_request = self .client .get_work_request (delete_stream_source .headers ['opc-work-request-id' ])
189+ if delete_stream_source_work_request .data .status == 'SUCCEEDED' :
190+ return True
191+ if delete_stream_source_work_request .data .status == 'FAILED' :
192+ return False
193+ time .sleep (30 )
194+
195+ def delete_Vision_Private_Endpoint (self , vision_private_endpoint_ocid ):
196+ delete_Vision_Private_Endpoint_request = self .client .delete_vision_private_endpoint (vision_private_endpoint_ocid )
197+ while True :
198+ delete_vision_private_endpoint_work_request = self .client .get_work_request (delete_Vision_Private_Endpoint_request .headers ['opc-work-request-id' ])
199+ if delete_vision_private_endpoint_work_request .data .status == 'SUCCEEDED' :
200+ return True
201+ if delete_vision_private_endpoint_work_request .data .status == 'FAILED' :
202+ return False
203+ time .sleep (30 )
204+
205+ if __name__ == '__main__' :
206+
207+ # pylint: disable=R1732
208+ parser = argparse .ArgumentParser ()
209+ parser .add_argument ('--compartment-id' , type = str , required = True , help = 'Compartment' )
210+ parser .add_argument ("--camera-url" , type = str , help = 'Camera Url for the Stream Source' )
211+ parser .add_argument ("--namespace" , type = str , help = "Namespace of the Bucket" )
212+ parser .add_argument ("--bucket" , type = str , help = "Bucket name" )
213+ parser .add_argument ("--prefix" , type = str , help = "Prefix" )
214+ parser .add_argument ("--feature" , type = json , help = "Json" )
215+ parser .add_argument ("-v" , "--verbose" , help = "Print logs" , action = 'store_true' )
216+ args = parser .parse_args ()
217+
218+ formatter = logging .Formatter (
219+ '%(asctime)s : {%(pathname)s:%(lineno)d} : %(name)s : %(levelname)s : %(message)s' )
220+ logger = logging .getLogger (__name__ )
221+ logger .setLevel (logging .DEBUG )
222+
223+ start_timeit = time .time ()
224+
225+ if args .verbose :
226+ handler = logging .StreamHandler (sys .stdout )
227+ handler .setFormatter (formatter )
228+ logger .addHandler (handler )
229+ else :
230+ file_handler = logging .FileHandler (
231+ 'stream_video_demo.log' , mode = 'w' )
232+ file_handler .setFormatter (formatter )
233+ logger .addHandler (file_handler )
234+
235+ compartment_id = args .compartment_id
236+ camera_url = args .camera_url
237+ namespace = args .namespace
238+ bucket = args .bucket
239+ prefix = args .prefix
240+ feature = args .feature
241+ subnet_id = args .subnet_id
242+
243+
244+ try :
245+ config = oci .config .from_file (
246+ '~/.oci/config' , profile_name = "DEFAULT" )
247+ except oci .exceptions .ConfigFileNotFound as err :
248+ logger .error (err )
249+ sys .exit ()
250+
251+ service_endpoint = \
252+ f"https://vision.aiservice.{ config .get ('region' )} .oci.oraclecloud.com"
253+
254+ stream_videos = StreamVideo (compartment_id = compartment_id , camera_url = camera_url ,
255+ namespace = namespace , bucket = bucket , prefix = prefix , feature = feature ,
256+ subnet_id = subnet_id , oci_config = config , service_endpoint = service_endpoint )
257+
258+
259+ vision_private_endpoint_ocid = StreamVideo .create_private_endpoint ()
260+ if vision_private_endpoint_ocid == None :
261+ sys .exit ("Error: Creation of Vision Private Endpoint Failed....." )
262+
263+ stream_source_ocid = StreamVideo .create_Stream_Source (vision_private_endpoint_ocid )
264+ if StreamVideo .create_Stream_Source (vision_private_endpoint_ocid ) == None :
265+ sys .exit ("Error: Creation of Stream Source Failed....." )
266+
267+ stream_job_ocid = StreamVideo .create_Stream_Job (stream_source_ocid )
268+ if stream_job_ocid == None :
269+ sys .exit ("Error: Creation of Stream Job Failed....." )
270+
271+ start_stream_job = StreamVideo .start_Stream_Job (stream_job_ocid )
272+ if stream_job_ocid == False :
273+ sys .exit ("Error: Start of Stream Job Failed....." )
274+
275+ stop_stream_job = StreamVideo .stop_Stream_Job (stream_job_ocid )
276+ if stop_stream_job == False :
277+ sys .exit ("Error: Stop of Stream Job Failed....." )
278+
279+ delete_stream_job = StreamVideo .delete_Stream_Job (stream_job_ocid )
280+ if delete_stream_job == False :
281+ sys .exit ("Error: Deletion of Stream Job Failed....." )
282+
283+ delete_stream_source = StreamVideo .delete_Stream_Source (stream_source_ocid )
284+ if delete_stream_source == False :
285+ sys .exit ("Error: Deletion of Stream Source Failed....." )
286+
287+ delete_Vision_Private_Endpoint = StreamVideo .delete_Vision_Private_Endpoint (vision_private_endpoint_ocid )
288+ if delete_Vision_Private_Endpoint == False :
289+ sys .exit ("Error: Deletion of Vision Private Endpoint Failed....." )
0 commit comments