Skip to content

Commit 8030df0

Browse files
committed
Stream Video
1 parent 05cb2e2 commit 8030df0

File tree

3 files changed

+387
-0
lines changed

3 files changed

+387
-0
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
vision-service python sample for streaming service (detecting object) video using sync API and final output is saved in json file.
2+
3+
# MAC OS:
4+
5+
## 0. Set up
6+
```
7+
Follow links below to generate a config file and a key pair in your ~/.oci directory
8+
https://docs.oracle.com/en-us/iaas/Content/API/Concepts/sdkconfig.htm
9+
https://docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm
10+
https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/cliinstall.htm#configfile
11+
12+
After completion, you should have following 2 things in your ~/.oci directory
13+
14+
a. A config file(where key file point to private key:key_file=~/.oci/oci_api_key.pem)
15+
b. A key pair named oci_api_key.pem and oci_api_key_public.pem
16+
17+
Now make sure you change the reference of key file in config file (where key file point to private key:key_file=/YOUR_DIR_TO_KEY_FILE/oci_api_key.pem)
18+
```
19+
## 1. Make sure you are in the root directory of this project:
20+
```
21+
cd ~/stream-video
22+
```
23+
24+
## 2. Upload Public Key
25+
```
26+
# Upload your oci_api_key_public.pem to console:
27+
https://docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm#three
28+
29+
Just in case you do not have your own config and oci_api_key.pem ready to use, we have
30+
a pair of keys and a config file in /sample_secrets folder, you can use those to run demo code for testing purposes.
31+
```
32+
33+
## 3. Make sure you have python installed on your machine
34+
```
35+
python --version
36+
```
37+
And I see following:
38+
'''
39+
Python 3.9.6
40+
'''
41+
42+
## 4. Install all dependencies(include our beta version SDK):
43+
```
44+
# Make sure you are on either Oracle Corp VPN or OCNA, and have enabled proxy
45+
export http_proxy=http://www-proxy-adcq7.us.oracle.com:80;
46+
export https_proxy=http://www-proxy-adcq7.us.oracle.com:80;
47+
export no_proxy=localhost,127.0.0.1,.us.oracle.com,oraclecorp.com;
48+
pip install -r requirements.txt
49+
50+
```
51+
52+
## 5. Stream video python sample scripts usage
53+
54+
```
55+
usage: stream_video_demo.py [-h] --compartment-id [COMPARTMENT_ID] --camera-url [CAMERA_URL] --namespace [NAMESPACE]
56+
--bucket [BUCKET] --prefix [PREFIX] --feature [FEATURE] [-v]
57+
58+
optional arguments:
59+
-h, --help show this help message and exit
60+
-v, --verbose Print logs
61+
--compartment-id COMPARTMENT_OCID compartment for the resources
62+
--camera-url CAMERA_URL camera url for the stream
63+
--namespace NAMESPACE namespace of the Bucket
64+
--bucket BUCKET_NAME bucket name
65+
--prefix PREFIX prefix
66+
--feature FEATURE feature
67+
```
68+
69+
## 6. Some examples commands:
70+
```
71+
python3.9 stream_video_demo.py --compartment-id --camera-url "rtsp://64.181.159.98:443/stream" --namespace "idvbwij6bjry" --bucket "stream-test" --prefix "testing" --feature FEATURES "[
72+
{
73+
"featureType": "OBJECT_TRACKING",
74+
75+
"trackingTypes":[
76+
{
77+
"objects": ["face"],
78+
"maxResults": 5,
79+
"shouldReturnLandmarks": True,
80+
"biometricStoreId": "ocid1.aibiometricstore.oc1.phx.amaaaaaat4fqliqahiowefua5gnv4vclqzejnjbt6udryjuqrmsqvppkp74a",
81+
"biometricStoreCompartmentId": "ocid1.tenancy.oc1..aaaaaaaanvgztn3ytxqdpryxvcv6xfx4xaggt7n243kjzim36xstqbymdgkq"
82+
}
83+
]
84+
}
85+
]"
86+
87+
Above command will create stream source, stream job and stream group, then start and stop stream job and finally delete everything
88+
89+
90+
```
91+
92+
## 7. After running above script, You should see output in json, format is video-file_fps_output-frame-rate_responses.json.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
oci==2.156.1+preview.1.257
2+
--index-url="https://artifactory.oci.oraclecorp.com/api/pypi/global-release-pypi/simple"
3+
--extra-index-url="https://artifactory.oci.oraclecorp.com/api/pypi/ocas-service-platform-dev-pypi-local/simple/"
4+
--extra-index-url="https://artifactory-builds.oci.oraclecorp.com/api/pypi/ocas-service-platform-dev-pypi-local/simple"
5+
--trusted-host="artifactory.oci.oraclecorp.com"
6+
vision-service-python-client-internal==0.3.155
Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
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

Comments
 (0)