nomadicml 0.0.1__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.
- nomadicml-0.0.1/LICENSE +21 -0
- nomadicml-0.0.1/MANIFEST.in +4 -0
- nomadicml-0.0.1/PKG-INFO +219 -0
- nomadicml-0.0.1/README.md +198 -0
- nomadicml-0.0.1/examples/basic_usage.py +226 -0
- nomadicml-0.0.1/nomadicml/__init__.py +42 -0
- nomadicml-0.0.1/nomadicml/client.py +164 -0
- nomadicml-0.0.1/nomadicml/exceptions.py +41 -0
- nomadicml-0.0.1/nomadicml/types.py +180 -0
- nomadicml-0.0.1/nomadicml/utils.py +131 -0
- nomadicml-0.0.1/nomadicml/video.py +744 -0
- nomadicml-0.0.1/nomadicml.egg-info/PKG-INFO +219 -0
- nomadicml-0.0.1/nomadicml.egg-info/SOURCES.txt +21 -0
- nomadicml-0.0.1/nomadicml.egg-info/dependency_links.txt +1 -0
- nomadicml-0.0.1/nomadicml.egg-info/requires.txt +10 -0
- nomadicml-0.0.1/nomadicml.egg-info/top_level.txt +2 -0
- nomadicml-0.0.1/pyproject.toml +18 -0
- nomadicml-0.0.1/requirements.txt +8 -0
- nomadicml-0.0.1/setup.cfg +4 -0
- nomadicml-0.0.1/setup.py +45 -0
- nomadicml-0.0.1/tests/__init__.py +1 -0
- nomadicml-0.0.1/tests/test_client.py +104 -0
- nomadicml-0.0.1/tests/test_video.py +234 -0
nomadicml-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 NomadicML
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
nomadicml-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: nomadicml
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Python SDK for NomadicML's DriveMonitor API
|
|
5
|
+
Author: NomadicML Inc
|
|
6
|
+
Author-email: info@nomadicml.com
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Requires-Python: >=3.8
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
|
|
22
|
+
# NomadicML Python SDK
|
|
23
|
+
|
|
24
|
+
A Python client library for the NomadicML DriveMonitor API, allowing you to upload and analyze driving videos programmatically.
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
### From PyPI (for users)
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install nomadicml
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### For Development (from source)
|
|
35
|
+
|
|
36
|
+
To install the package in development mode, where changes to the code will be immediately reflected without reinstallation:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Clone the repository
|
|
40
|
+
git clone https://github.com/nomadic-ml/drivemonitor.git
|
|
41
|
+
cd sdk
|
|
42
|
+
|
|
43
|
+
# For development: Install in editable mode
|
|
44
|
+
pip install -e .
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
With this installation, any changes you make to the code will be immediately available when you import the package.
|
|
48
|
+
|
|
49
|
+
## Quick Start
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
from nomadicml import NomadicML
|
|
53
|
+
|
|
54
|
+
# Initialize the client with your API key
|
|
55
|
+
client = NomadicML(api_key="your_api_key")
|
|
56
|
+
|
|
57
|
+
# Upload a video and analyze it in one step
|
|
58
|
+
result = client.video.upload_and_analyze("path/to/your/video.mp4")
|
|
59
|
+
|
|
60
|
+
# Print the detected events
|
|
61
|
+
for event in result["events"]:
|
|
62
|
+
print(f"Event: {event['type']} at {event['time']}s - {event['description']}")
|
|
63
|
+
#For a batch upload
|
|
64
|
+
|
|
65
|
+
videos_list = [.....]#list of video paths
|
|
66
|
+
batch_results = client.video.upload_and_analyze_videos(videos_list, wait_for_completion=False)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
video_ids = [
|
|
70
|
+
res.get("video_id")
|
|
71
|
+
for res in batch_results
|
|
72
|
+
if res # safety for None
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
full_results = client.video.wait_for_analyses(video_ids)
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Authentication
|
|
81
|
+
|
|
82
|
+
You need an API key to use the NomadicML API. You can get one by:
|
|
83
|
+
|
|
84
|
+
1. Log in to your DriveMonitor account
|
|
85
|
+
2. Go to Profile > API Key
|
|
86
|
+
3. Generate a new API key
|
|
87
|
+
|
|
88
|
+
Then use this key when initializing the client:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
client = NomadicML(api_key="your_api_key")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Video Upload and Analysis
|
|
95
|
+
|
|
96
|
+
### Upload a video
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
# Upload a local video file
|
|
100
|
+
result = client.video.upload_video(
|
|
101
|
+
source="file",
|
|
102
|
+
file_path="path/to/video.mp4"
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Or upload from YouTube
|
|
106
|
+
result = client.video.upload_video(
|
|
107
|
+
source="youtube",
|
|
108
|
+
youtube_url="https://www.youtube.com/watch?v=VIDEO_ID"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
# Get the video ID from the response
|
|
112
|
+
video_id = result["video_id"]
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Analyze a video
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
# Start analysis
|
|
119
|
+
client.video.analyze_video(video_id)
|
|
120
|
+
|
|
121
|
+
# Wait for analysis to complete
|
|
122
|
+
status = client.video.wait_for_analysis(video_id)
|
|
123
|
+
|
|
124
|
+
# Get analysis results
|
|
125
|
+
analysis = client.video.get_video_analysis(video_id)
|
|
126
|
+
|
|
127
|
+
# Get detected events
|
|
128
|
+
events = client.video.get_video_events(video_id)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Upload and analyze in one step
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
# Upload and analyze a video, waiting for results
|
|
135
|
+
analysis = client.video.upload_and_analyze("path/to/video.mp4")
|
|
136
|
+
|
|
137
|
+
# Or just start the process without waiting
|
|
138
|
+
result = client.video.upload_and_analyze("path/to/video.mp4", wait_for_completion=False)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Advanced Usage
|
|
142
|
+
|
|
143
|
+
### Filter events by severity or type
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
# Get only high severity events
|
|
147
|
+
high_severity_events = client.video.get_video_events(
|
|
148
|
+
video_id=video_id,
|
|
149
|
+
severity="high"
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
# Get only traffic violation events
|
|
153
|
+
traffic_violations = client.video.get_video_events(
|
|
154
|
+
video_id=video_id,
|
|
155
|
+
event_type="Traffic Violation"
|
|
156
|
+
)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Custom timeout and polling interval
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
# Wait for analysis with a custom timeout and polling interval
|
|
163
|
+
client.video.wait_for_analysis(
|
|
164
|
+
video_id=video_id,
|
|
165
|
+
timeout=1200, # 20 minutes
|
|
166
|
+
poll_interval=10 # Check every 10 seconds
|
|
167
|
+
)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Custom API endpoint
|
|
171
|
+
|
|
172
|
+
If you're using a custom deployment of the DriveMonitor backend:
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
# Connect to a local or custom deployment
|
|
176
|
+
client = NomadicML(
|
|
177
|
+
api_key="your_api_key",
|
|
178
|
+
base_url="http://localhost:8099"
|
|
179
|
+
)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Error Handling
|
|
183
|
+
|
|
184
|
+
The SDK provides specific exceptions for different error types:
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
from nomadicml import NomadicMLError, AuthenticationError, VideoUploadError
|
|
188
|
+
|
|
189
|
+
try:
|
|
190
|
+
client.video.upload_and_analyze("path/to/video.mp4")
|
|
191
|
+
except AuthenticationError:
|
|
192
|
+
print("API key is invalid or expired")
|
|
193
|
+
except VideoUploadError as e:
|
|
194
|
+
print(f"Failed to upload video: {e}")
|
|
195
|
+
except NomadicMLError as e:
|
|
196
|
+
print(f"An error occurred: {e}")
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Development
|
|
200
|
+
|
|
201
|
+
### Setup
|
|
202
|
+
|
|
203
|
+
Clone the repository and install development dependencies:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
git clone https://github.com/nomadicml/nomadicml-python.git
|
|
207
|
+
cd nomadicml-python
|
|
208
|
+
pip install -e ".[dev]"
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Running tests
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
pytest
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## License
|
|
218
|
+
|
|
219
|
+
MIT License. See LICENSE file for details.
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# NomadicML Python SDK
|
|
2
|
+
|
|
3
|
+
A Python client library for the NomadicML DriveMonitor API, allowing you to upload and analyze driving videos programmatically.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
### From PyPI (for users)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install nomadicml
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### For Development (from source)
|
|
14
|
+
|
|
15
|
+
To install the package in development mode, where changes to the code will be immediately reflected without reinstallation:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Clone the repository
|
|
19
|
+
git clone https://github.com/nomadic-ml/drivemonitor.git
|
|
20
|
+
cd sdk
|
|
21
|
+
|
|
22
|
+
# For development: Install in editable mode
|
|
23
|
+
pip install -e .
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
With this installation, any changes you make to the code will be immediately available when you import the package.
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from nomadicml import NomadicML
|
|
32
|
+
|
|
33
|
+
# Initialize the client with your API key
|
|
34
|
+
client = NomadicML(api_key="your_api_key")
|
|
35
|
+
|
|
36
|
+
# Upload a video and analyze it in one step
|
|
37
|
+
result = client.video.upload_and_analyze("path/to/your/video.mp4")
|
|
38
|
+
|
|
39
|
+
# Print the detected events
|
|
40
|
+
for event in result["events"]:
|
|
41
|
+
print(f"Event: {event['type']} at {event['time']}s - {event['description']}")
|
|
42
|
+
#For a batch upload
|
|
43
|
+
|
|
44
|
+
videos_list = [.....]#list of video paths
|
|
45
|
+
batch_results = client.video.upload_and_analyze_videos(videos_list, wait_for_completion=False)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
video_ids = [
|
|
49
|
+
res.get("video_id")
|
|
50
|
+
for res in batch_results
|
|
51
|
+
if res # safety for None
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
full_results = client.video.wait_for_analyses(video_ids)
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Authentication
|
|
60
|
+
|
|
61
|
+
You need an API key to use the NomadicML API. You can get one by:
|
|
62
|
+
|
|
63
|
+
1. Log in to your DriveMonitor account
|
|
64
|
+
2. Go to Profile > API Key
|
|
65
|
+
3. Generate a new API key
|
|
66
|
+
|
|
67
|
+
Then use this key when initializing the client:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
client = NomadicML(api_key="your_api_key")
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Video Upload and Analysis
|
|
74
|
+
|
|
75
|
+
### Upload a video
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
# Upload a local video file
|
|
79
|
+
result = client.video.upload_video(
|
|
80
|
+
source="file",
|
|
81
|
+
file_path="path/to/video.mp4"
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Or upload from YouTube
|
|
85
|
+
result = client.video.upload_video(
|
|
86
|
+
source="youtube",
|
|
87
|
+
youtube_url="https://www.youtube.com/watch?v=VIDEO_ID"
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# Get the video ID from the response
|
|
91
|
+
video_id = result["video_id"]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Analyze a video
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
# Start analysis
|
|
98
|
+
client.video.analyze_video(video_id)
|
|
99
|
+
|
|
100
|
+
# Wait for analysis to complete
|
|
101
|
+
status = client.video.wait_for_analysis(video_id)
|
|
102
|
+
|
|
103
|
+
# Get analysis results
|
|
104
|
+
analysis = client.video.get_video_analysis(video_id)
|
|
105
|
+
|
|
106
|
+
# Get detected events
|
|
107
|
+
events = client.video.get_video_events(video_id)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Upload and analyze in one step
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
# Upload and analyze a video, waiting for results
|
|
114
|
+
analysis = client.video.upload_and_analyze("path/to/video.mp4")
|
|
115
|
+
|
|
116
|
+
# Or just start the process without waiting
|
|
117
|
+
result = client.video.upload_and_analyze("path/to/video.mp4", wait_for_completion=False)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Advanced Usage
|
|
121
|
+
|
|
122
|
+
### Filter events by severity or type
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
# Get only high severity events
|
|
126
|
+
high_severity_events = client.video.get_video_events(
|
|
127
|
+
video_id=video_id,
|
|
128
|
+
severity="high"
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# Get only traffic violation events
|
|
132
|
+
traffic_violations = client.video.get_video_events(
|
|
133
|
+
video_id=video_id,
|
|
134
|
+
event_type="Traffic Violation"
|
|
135
|
+
)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Custom timeout and polling interval
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
# Wait for analysis with a custom timeout and polling interval
|
|
142
|
+
client.video.wait_for_analysis(
|
|
143
|
+
video_id=video_id,
|
|
144
|
+
timeout=1200, # 20 minutes
|
|
145
|
+
poll_interval=10 # Check every 10 seconds
|
|
146
|
+
)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Custom API endpoint
|
|
150
|
+
|
|
151
|
+
If you're using a custom deployment of the DriveMonitor backend:
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
# Connect to a local or custom deployment
|
|
155
|
+
client = NomadicML(
|
|
156
|
+
api_key="your_api_key",
|
|
157
|
+
base_url="http://localhost:8099"
|
|
158
|
+
)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Error Handling
|
|
162
|
+
|
|
163
|
+
The SDK provides specific exceptions for different error types:
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
from nomadicml import NomadicMLError, AuthenticationError, VideoUploadError
|
|
167
|
+
|
|
168
|
+
try:
|
|
169
|
+
client.video.upload_and_analyze("path/to/video.mp4")
|
|
170
|
+
except AuthenticationError:
|
|
171
|
+
print("API key is invalid or expired")
|
|
172
|
+
except VideoUploadError as e:
|
|
173
|
+
print(f"Failed to upload video: {e}")
|
|
174
|
+
except NomadicMLError as e:
|
|
175
|
+
print(f"An error occurred: {e}")
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Development
|
|
179
|
+
|
|
180
|
+
### Setup
|
|
181
|
+
|
|
182
|
+
Clone the repository and install development dependencies:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
git clone https://github.com/nomadicml/nomadicml-python.git
|
|
186
|
+
cd nomadicml-python
|
|
187
|
+
pip install -e ".[dev]"
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Running tests
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
pytest
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## License
|
|
197
|
+
|
|
198
|
+
MIT License. See LICENSE file for details.
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Basic usage examples for the NomadicML SDK.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import logging
|
|
7
|
+
from nomadicml import NomadicML
|
|
8
|
+
|
|
9
|
+
# Set up logging to see progress information
|
|
10
|
+
logging.basicConfig(level=logging.INFO)
|
|
11
|
+
|
|
12
|
+
# Get API key from environment variable or input
|
|
13
|
+
API_KEY = os.environ.get("NOMADICML_API_KEY") or input("Enter your NomadicML API key: ")
|
|
14
|
+
|
|
15
|
+
# Path to a video file for testing
|
|
16
|
+
VIDEO_PATH = os.environ.get("VIDEO_PATH") or input("Enter path to a video file: ")
|
|
17
|
+
|
|
18
|
+
# Initialize the client with your API key
|
|
19
|
+
# Add base_url for development use
|
|
20
|
+
# Change collection_name to "videos" for production use
|
|
21
|
+
client = NomadicML(api_key=API_KEY, collection_name="videos_dev")
|
|
22
|
+
|
|
23
|
+
def verify_authentication():
|
|
24
|
+
"""
|
|
25
|
+
Verify that the API key is valid.
|
|
26
|
+
"""
|
|
27
|
+
print("\n=== Verifying Authentication ===")
|
|
28
|
+
try:
|
|
29
|
+
# Verify authentication
|
|
30
|
+
auth_info = client.verify_auth()
|
|
31
|
+
print(f"Authentication successful: {auth_info}")
|
|
32
|
+
return True
|
|
33
|
+
except Exception as e:
|
|
34
|
+
print(f"Authentication failed due to error: {e}")
|
|
35
|
+
return False
|
|
36
|
+
|
|
37
|
+
def upload_video():
|
|
38
|
+
"""
|
|
39
|
+
Upload a video file to the DriveMonitor API.
|
|
40
|
+
"""
|
|
41
|
+
print("\n=== Uploading Video ===")
|
|
42
|
+
try:
|
|
43
|
+
# Upload the video
|
|
44
|
+
result = client.video.upload_video(
|
|
45
|
+
source="file",
|
|
46
|
+
file_path=VIDEO_PATH
|
|
47
|
+
)
|
|
48
|
+
video_id = result["video_id"]
|
|
49
|
+
print(f"Video uploaded successfully. ID: {video_id}")
|
|
50
|
+
return video_id
|
|
51
|
+
except Exception as e:
|
|
52
|
+
print(f"Video upload failed: {e}")
|
|
53
|
+
return None
|
|
54
|
+
|
|
55
|
+
def analyze_video(video_id):
|
|
56
|
+
"""
|
|
57
|
+
Start analysis for the uploaded video.
|
|
58
|
+
"""
|
|
59
|
+
print("\n=== Starting Video Analysis ===")
|
|
60
|
+
try:
|
|
61
|
+
# Start analysis
|
|
62
|
+
result = client.video.analyze_video(video_id)
|
|
63
|
+
print(f"Analysis started: {result}")
|
|
64
|
+
return True
|
|
65
|
+
except Exception as e:
|
|
66
|
+
print(f"Failed to start analysis: {e}")
|
|
67
|
+
return False
|
|
68
|
+
|
|
69
|
+
def check_status(video_id):
|
|
70
|
+
"""
|
|
71
|
+
Check the status of the video analysis.
|
|
72
|
+
"""
|
|
73
|
+
print("\n=== Checking Video Status ===")
|
|
74
|
+
try:
|
|
75
|
+
# Get the status
|
|
76
|
+
status = client.video.get_video_status(video_id)
|
|
77
|
+
print(f"Current status: {status}")
|
|
78
|
+
return status
|
|
79
|
+
except Exception as e:
|
|
80
|
+
print(f"Failed to get status: {e}")
|
|
81
|
+
return None
|
|
82
|
+
|
|
83
|
+
def wait_for_completion(video_id):
|
|
84
|
+
"""
|
|
85
|
+
Wait for the video analysis to complete.
|
|
86
|
+
"""
|
|
87
|
+
print("\n=== Waiting for Analysis to Complete ===")
|
|
88
|
+
try:
|
|
89
|
+
# Wait for completion with a shorter timeout for the example
|
|
90
|
+
final_status = client.video.wait_for_analysis(video_id, timeout=180)
|
|
91
|
+
print(f"Analysis completed: {final_status.get('status', 'Unknown')}")
|
|
92
|
+
return True
|
|
93
|
+
except Exception as e:
|
|
94
|
+
print(f"Error waiting for completion: {e}")
|
|
95
|
+
return False
|
|
96
|
+
|
|
97
|
+
def get_results(video_id):
|
|
98
|
+
"""
|
|
99
|
+
Get the full analysis results.
|
|
100
|
+
"""
|
|
101
|
+
print("\n=== Getting Analysis Results ===")
|
|
102
|
+
try:
|
|
103
|
+
# Get the analysis
|
|
104
|
+
analysis = client.video.get_video_analysis(video_id)
|
|
105
|
+
print(f"Analysis summary:")
|
|
106
|
+
|
|
107
|
+
# Print metadata if available
|
|
108
|
+
if "metadata" in analysis:
|
|
109
|
+
metadata = analysis["metadata"]
|
|
110
|
+
print(f" Video: {metadata.get('filename', 'Unknown')}")
|
|
111
|
+
if "duration" in metadata:
|
|
112
|
+
print(f" Duration: {metadata['duration']:.2f} seconds")
|
|
113
|
+
if "width" in metadata and "height" in metadata:
|
|
114
|
+
print(f" Resolution: {metadata['width']}x{metadata['height']}")
|
|
115
|
+
|
|
116
|
+
# Print events if available
|
|
117
|
+
if "events" in analysis and analysis["events"]:
|
|
118
|
+
print(f"\nDetected events ({len(analysis['events'])}):")
|
|
119
|
+
else:
|
|
120
|
+
print("\nNo events detected.")
|
|
121
|
+
|
|
122
|
+
return analysis
|
|
123
|
+
except Exception as e:
|
|
124
|
+
print(f"Failed to get analysis results: {e}")
|
|
125
|
+
return None
|
|
126
|
+
|
|
127
|
+
def upload_and_analyze_in_one_step(return_subset: bool = True):
|
|
128
|
+
"""
|
|
129
|
+
Upload and analyze a video in one operation.
|
|
130
|
+
"""
|
|
131
|
+
print("\n=== Upload and Analyze in One Step ===")
|
|
132
|
+
try:
|
|
133
|
+
# Upload and analyze with a shorter timeout for the example
|
|
134
|
+
analysis = client.video.upload_and_analyze(
|
|
135
|
+
file_path=VIDEO_PATH,
|
|
136
|
+
timeout=180,
|
|
137
|
+
return_subset=return_subset
|
|
138
|
+
)
|
|
139
|
+
print(f"Upload and analysis completed successfully.")
|
|
140
|
+
|
|
141
|
+
# Print a summary of the results
|
|
142
|
+
if hasattr(analysis, 'visual_analysis') and analysis.visual_analysis and hasattr(analysis.visual_analysis, 'events') and analysis.visual_analysis.events:
|
|
143
|
+
print(f"\nDetected {len(analysis.visual_analysis.events)} events.")
|
|
144
|
+
elif isinstance(analysis, dict) and "events" in analysis and analysis["events"]: # Keep compatibility if return_subset=False
|
|
145
|
+
print(f"\nDetected {len(analysis['events'])} events.")
|
|
146
|
+
else:
|
|
147
|
+
print("\nNo events detected.")
|
|
148
|
+
|
|
149
|
+
return analysis
|
|
150
|
+
except Exception as e:
|
|
151
|
+
print(f"Upload and analyze failed: {e}")
|
|
152
|
+
return None
|
|
153
|
+
|
|
154
|
+
def main():
|
|
155
|
+
"""
|
|
156
|
+
Run the examples.
|
|
157
|
+
"""
|
|
158
|
+
print("=== NomadicML SDK Basic Usage Example ===")
|
|
159
|
+
|
|
160
|
+
# Verify authentication
|
|
161
|
+
if not verify_authentication():
|
|
162
|
+
print("Exiting due to authentication failure.")
|
|
163
|
+
return
|
|
164
|
+
|
|
165
|
+
# Ask which example to run
|
|
166
|
+
print("\nChoose an example to run:")
|
|
167
|
+
print("1. Step-by-step (upload, analyze, get results)")
|
|
168
|
+
print("2. All-in-one (upload and analyze in one step)")
|
|
169
|
+
print("3. Only upload video")
|
|
170
|
+
print("4. Only analyze video")
|
|
171
|
+
|
|
172
|
+
choice = input("Enter your choice (1, 2, 3 or 4): ").strip()
|
|
173
|
+
|
|
174
|
+
if choice == "1":
|
|
175
|
+
# Step-by-step example
|
|
176
|
+
video_id = upload_video()
|
|
177
|
+
if not video_id:
|
|
178
|
+
print("Exiting due to upload failure.")
|
|
179
|
+
return
|
|
180
|
+
|
|
181
|
+
if not analyze_video(video_id):
|
|
182
|
+
print("Exiting due to analysis startup failure.")
|
|
183
|
+
return
|
|
184
|
+
|
|
185
|
+
status = check_status(video_id)
|
|
186
|
+
if not status:
|
|
187
|
+
print("Exiting due to status check failure.")
|
|
188
|
+
return
|
|
189
|
+
|
|
190
|
+
if not wait_for_completion(video_id):
|
|
191
|
+
print("Exiting due to timeout or error while waiting for completion.")
|
|
192
|
+
return
|
|
193
|
+
|
|
194
|
+
results = get_results(video_id)
|
|
195
|
+
if not results:
|
|
196
|
+
print("Exiting due to failure getting results.")
|
|
197
|
+
return
|
|
198
|
+
|
|
199
|
+
elif choice == "2":
|
|
200
|
+
# All-in-one example
|
|
201
|
+
results = upload_and_analyze_in_one_step()
|
|
202
|
+
if not results:
|
|
203
|
+
print("Exiting due to upload and analyze failure.")
|
|
204
|
+
return
|
|
205
|
+
elif choice == "3":
|
|
206
|
+
# Only upload video
|
|
207
|
+
print("\n=== Only Uploading Video ===")
|
|
208
|
+
video_id = upload_video()
|
|
209
|
+
if not video_id:
|
|
210
|
+
print("Exiting due to upload failure.")
|
|
211
|
+
return
|
|
212
|
+
elif choice == "4":
|
|
213
|
+
# Only analyze video
|
|
214
|
+
print("\n=== Only Analyzing Video ===")
|
|
215
|
+
video_id = input("Enter the video ID to analyze: ")
|
|
216
|
+
if not analyze_video(video_id):
|
|
217
|
+
print("Exiting due to analysis startup failure.")
|
|
218
|
+
return
|
|
219
|
+
else:
|
|
220
|
+
print("Invalid choice. Exiting.")
|
|
221
|
+
return
|
|
222
|
+
|
|
223
|
+
print("\n=== Example Completed Successfully ===")
|
|
224
|
+
|
|
225
|
+
if __name__ == "__main__":
|
|
226
|
+
main()
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""
|
|
2
|
+
NomadicML Python SDK for the DriveMonitor API.
|
|
3
|
+
|
|
4
|
+
This SDK provides a simple interface to interact with the
|
|
5
|
+
DriveMonitor backend for analyzing driving videos.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
__version__ = "0.1.0"
|
|
9
|
+
|
|
10
|
+
from .client import NomadicML
|
|
11
|
+
from .video import VideoClient
|
|
12
|
+
from .exceptions import NomadicMLError, AuthenticationError, APIError, VideoUploadError, AnalysisError
|
|
13
|
+
from .types import VideoSource, ProcessingStatus, Severity, convert_to_upload_analyze_response_subset
|
|
14
|
+
|
|
15
|
+
# Add video client to NomadicML
|
|
16
|
+
def _add_video_client(client):
|
|
17
|
+
client.video = VideoClient(client)
|
|
18
|
+
return client
|
|
19
|
+
|
|
20
|
+
# Patch the NomadicML class
|
|
21
|
+
_original_init = NomadicML.__init__
|
|
22
|
+
|
|
23
|
+
def _patched_init(self, *args, **kwargs):
|
|
24
|
+
_original_init(self, *args, **kwargs)
|
|
25
|
+
_add_video_client(self)
|
|
26
|
+
|
|
27
|
+
NomadicML.__init__ = _patched_init
|
|
28
|
+
|
|
29
|
+
__all__ = [
|
|
30
|
+
"NomadicML",
|
|
31
|
+
"VideoClient",
|
|
32
|
+
"NomadicMLError",
|
|
33
|
+
"AuthenticationError",
|
|
34
|
+
"APIError",
|
|
35
|
+
"VideoUploadError",
|
|
36
|
+
"AnalysisError",
|
|
37
|
+
"VideoSource",
|
|
38
|
+
"ProcessingStatus",
|
|
39
|
+
"EventType",
|
|
40
|
+
"Severity",
|
|
41
|
+
"convert_to_upload_analyze_response_subset",
|
|
42
|
+
]
|