Amanpreet Singh commited on
Commit
d24b4dd
·
1 Parent(s): 0b7c508
Files changed (4) hide show
  1. .gitignore +3 -0
  2. app.py +343 -0
  3. requirements.txt +7 -0
  4. video-to-bvh-converter.ipynb +189 -0
.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ .streamlit
2
+ venv
3
+ *.toml
app.py ADDED
@@ -0,0 +1,343 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import requests
3
+ import tempfile
4
+ import shutil
5
+ from kaggle.api.kaggle_api_extended import KaggleApi
6
+ import os
7
+ import time
8
+ import json
9
+ import subprocess
10
+ from google.oauth2.credentials import Credentials
11
+ from googleapiclient.discovery import build
12
+ from googleapiclient.http import MediaFileUpload
13
+ from googleapiclient.errors import HttpError
14
+
15
+ def setup_kaggle_api():
16
+ try:
17
+ os.environ["KAGGLE_USERNAME"] = st.secrets["KAGGLE_USERNAME"]
18
+ os.environ["KAGGLE_KEY"] = st.secrets["KAGGLE_KEY"]
19
+ api = KaggleApi()
20
+ api.authenticate()
21
+ return api
22
+ except KeyError as e:
23
+ st.error(f"Missing Kaggle secret: {e}")
24
+ st.stop()
25
+ except Exception as e:
26
+ st.error(f"Kaggle API setup failed: {e}")
27
+ st.stop()
28
+
29
+ def setup_drive_service():
30
+ try:
31
+ credentials_dict = dict(st.secrets["GOOGLE_SERVICE_ACCOUNT"])
32
+ credentials = Credentials(
33
+ token=credentials_dict["access_token"],
34
+ refresh_token=credentials_dict["refresh_token"],
35
+ client_id=credentials_dict["client_id"],
36
+ client_secret=credentials_dict["client_secret"],
37
+ token_uri=credentials_dict["token_uri"],
38
+ scopes=credentials_dict["scopes"]
39
+ )
40
+ if credentials.expired and credentials.refresh_token:
41
+ credentials.refresh(requests.Request())
42
+ drive_service = build('drive', 'v3', credentials=credentials)
43
+ return drive_service
44
+ except KeyError as e:
45
+ st.error(f"Missing key in GOOGLE_SERVICE_ACCOUNT: {e}")
46
+ st.stop()
47
+ except Exception as e:
48
+ st.error(f"Google Drive auth failed: {e}")
49
+ st.stop()
50
+
51
+ def upload_to_drive(drive_service, file_path, title, folder_id="1T6v7Iqc90-NA-F3I-HeHDSvEaIyFibKd"):
52
+ try:
53
+ file_metadata = {'name': title, 'parents': [folder_id]}
54
+ media = MediaFileUpload(file_path, resumable=True)
55
+ file = drive_service.files().create(
56
+ body=file_metadata, media_body=media, fields='id, name'
57
+ ).execute()
58
+ file_id = file['id']
59
+ drive_service.permissions().create(
60
+ fileId=file_id,
61
+ body={'type': 'anyone', 'role': 'reader'},
62
+ fields='id'
63
+ ).execute()
64
+ shareable_link = f"https://drive.google.com/file/d/{file_id}/view?usp=sharing"
65
+ return file_id, shareable_link
66
+ except HttpError as e:
67
+ st.error(f"Drive upload failed: {e}")
68
+ raise
69
+ except Exception as e:
70
+ st.error(f"Unexpected error during upload: {e}")
71
+ raise
72
+
73
+ def delete_from_drive(drive_service, file_id):
74
+ try:
75
+ drive_service.files().delete(fileId=file_id).execute()
76
+ except Exception as e:
77
+ st.error(f"Failed to delete file {file_id} from Drive: {e}")
78
+
79
+ def get_bvh_from_folder(drive_service, folder_id="1T6v7Iqc90-NA-F3I-HeHDSvEaIyFibKd"):
80
+ try:
81
+ query = f"'{folder_id}' in parents and name contains '.bvh'"
82
+ response = drive_service.files().list(q=query, fields="files(id, name, mimeType)", pageSize=1).execute()
83
+ files = response.get('files', [])
84
+ if files:
85
+ bvh_file = files[0]
86
+ bvh_id = bvh_file['id']
87
+ bvh_url = f"https://drive.google.com/uc?id={bvh_id}"
88
+ return bvh_id, bvh_url
89
+ return None, None
90
+ except Exception as e:
91
+ st.error(f"Error checking folder for BVH: {e}")
92
+ return None, None
93
+
94
+ def push_kaggle_kernel(api, temp_dir, notebook_slug):
95
+ try:
96
+ local_notebook_path = os.path.join(os.path.dirname(__file__), 'video-to-bvh-converter.ipynb')
97
+ if not os.path.exists(local_notebook_path):
98
+ st.error(f"Notebook file not found")
99
+ raise FileNotFoundError
100
+
101
+ kernel_file = os.path.join(temp_dir, 'kernel.ipynb')
102
+ shutil.copy(local_notebook_path, kernel_file)
103
+
104
+ code_file = "kernel.ipynb"
105
+ kernel_type = "notebook"
106
+
107
+ metadata = {
108
+ "id": notebook_slug,
109
+ "title": "video-to-bvh-converter",
110
+ "code_file": code_file,
111
+ "language": "python",
112
+ "kernel_type": kernel_type,
113
+ "enable_gpu": True,
114
+ "enable_internet": True,
115
+ "is_private": True,
116
+ "competition_sources": [],
117
+ "dataset_sources": [],
118
+ "kernel_sources": []
119
+ }
120
+ metadata_file = os.path.join(temp_dir, 'kernel-metadata.json')
121
+ with open(metadata_file, 'w') as f:
122
+ json.dump(metadata, f)
123
+
124
+ cmd = f"kaggle kernels push -p {temp_dir}"
125
+ result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
126
+ if result.returncode != 0:
127
+ st.error(f"Kaggle push failed: {result.stderr}")
128
+ raise Exception
129
+
130
+ kernel_url = f"https://www.kaggle.com/code/{notebook_slug}"
131
+ return kernel_url
132
+ except Exception as e:
133
+ st.error(f"Failed to push kernel: {str(e)}")
134
+ raise
135
+
136
+ def check_kernel_exists(api, notebook_slug):
137
+ try:
138
+ kernels = api.kernels_list(mine=True, search=notebook_slug)
139
+ for kernel in kernels:
140
+ if kernel.ref == notebook_slug:
141
+ return True
142
+ return False
143
+ except Exception as e:
144
+ st.error(f"Kernel check failed: {e}")
145
+ return False
146
+
147
+ def process_video(api, drive_service, video_file):
148
+ video_file_id = None
149
+ bvh_file_id = None
150
+ try:
151
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.mp4') as tmp_file:
152
+ tmp_file.write(video_file.read())
153
+ video_path = tmp_file.name
154
+
155
+ video_file_id, video_shareable_link = upload_to_drive(drive_service, video_path, "input_video.mp4")
156
+ st.success(f"Video uploaded to Drive: {video_shareable_link}")
157
+
158
+ username = st.secrets['KAGGLE_USERNAME']
159
+ notebook_slug = f"{username}/video-to-bvh-converter"
160
+
161
+ kernel_exists = check_kernel_exists(api, notebook_slug)
162
+ if not kernel_exists:
163
+ pass
164
+
165
+ temp_dir = tempfile.mkdtemp()
166
+
167
+ with st.spinner("Triggering Kaggle notebook..."):
168
+ kernel_url = push_kaggle_kernel(api, temp_dir, notebook_slug)
169
+
170
+ progress_bar = st.progress(0.0)
171
+ progress_text = st.empty()
172
+
173
+ with st.spinner("Waiting for video processing..."):
174
+ start_time = time.time()
175
+ execution_started = False
176
+ retry_count = 0
177
+ max_retries = 3
178
+ overall_timeout = 1800
179
+
180
+ while time.time() - start_time < overall_timeout:
181
+ try:
182
+ status_response = api.kernels_status(notebook_slug)
183
+ current_status = status_response.status if hasattr(status_response, 'status') else 'unknown'
184
+
185
+ if current_status in ['queued', 'running']:
186
+ execution_started = True
187
+ if current_status == 'queued':
188
+ progress_bar.progress(0.2)
189
+ progress_text.text("Queued - Waiting for GPU...")
190
+ elif current_status == 'running':
191
+ progress_bar.progress(0.4)
192
+ progress_text.text("Processing video...")
193
+ elif current_status == 'complete' and not execution_started:
194
+ push_kaggle_kernel(api, temp_dir, notebook_slug)
195
+ time.sleep(10)
196
+ continue
197
+ elif current_status == 'error' and not execution_started:
198
+ if retry_count < max_retries:
199
+ time.sleep(10)
200
+ push_kaggle_kernel(api, temp_dir, notebook_slug)
201
+ retry_count += 1
202
+ start_time = time.time()
203
+ continue
204
+ else:
205
+ if video_file_id:
206
+ delete_from_drive(drive_service, video_file_id)
207
+ return None
208
+
209
+ bvh_file_id, bvh_url = get_bvh_from_folder(drive_service)
210
+ if bvh_url:
211
+ response = requests.get(bvh_url)
212
+ if response.status_code == 200:
213
+ progress_bar.progress(1.0)
214
+ progress_text.text("Complete!")
215
+ if video_file_id:
216
+ delete_from_drive(drive_service, video_file_id)
217
+ if bvh_file_id:
218
+ delete_from_drive(drive_service, bvh_file_id)
219
+ st.write("BVH generated")
220
+ return {'bvh_data': response.content}
221
+
222
+ if execution_started and current_status in ['complete', 'error']:
223
+ progress_bar.progress(0.8 if current_status == 'complete' else 0.6)
224
+ progress_text.text("Finalizing..." if current_status == 'complete' else "Error occurred...")
225
+ if current_status == 'error':
226
+ if video_file_id:
227
+ delete_from_drive(drive_service, video_file_id)
228
+ return None
229
+
230
+ time.sleep(10)
231
+
232
+ except Exception as e:
233
+ st.error(f"Status check failed: {str(e)}")
234
+ time.sleep(10)
235
+
236
+ if video_file_id:
237
+ delete_from_drive(drive_service, video_file_id)
238
+ return None
239
+
240
+ except Exception as e:
241
+ st.error(f"Processing error: {e}")
242
+ if video_file_id:
243
+ delete_from_drive(drive_service, video_file_id)
244
+ if bvh_file_id:
245
+ delete_from_drive(drive_service, bvh_file_id)
246
+ return None
247
+ finally:
248
+ if 'video_path' in locals():
249
+ os.unlink(video_path)
250
+ if 'temp_dir' in locals() and os.path.exists(temp_dir):
251
+ shutil.rmtree(temp_dir)
252
+
253
+ def main():
254
+ st.set_page_config(
255
+ page_title="Motion Capture Studio | Video to BVH Converter",
256
+ page_icon="🎬",
257
+ layout="wide",
258
+ initial_sidebar_state="collapsed"
259
+ )
260
+
261
+ st.markdown("""
262
+ <style>
263
+ :root {
264
+ --bg-color: #1a1a1a;
265
+ --card-bg: #252525;
266
+ --primary-color: #bb86fc;
267
+ --secondary-color: #03dac6;
268
+ --error-color: #cf6679;
269
+ --text-color: #e0e0e0;
270
+ --text-secondary: #a0a0a0;
271
+ }
272
+ .stApp { background-color: var(--bg-color); }
273
+ h1, h2, h3, p, div { color: var(--text-color) !important; }
274
+ .card { background-color: var(--card-bg); border-radius: 20px; padding: 2rem; margin: 1rem auto; max-width: 1200px; }
275
+ .main-title { font-size: 3.5rem; font-weight: 900; background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; text-align: center; }
276
+ .subtitle { font-size: 1.3rem; color: var(--text-secondary); text-align: center; }
277
+ .section-title { font-size: 1.5rem; font-weight: 700; color: var(--primary-color) !important; }
278
+ .stButton > button { background: linear-gradient(135deg, var(--primary-color), #9b59f5); color: #fff !important; border-radius: 12px; padding: 0.8rem 2.5rem; font-weight: 600; font-size: 1.2rem; border: none; width: 100%; }
279
+ .stDownloadButton > button { background: linear-gradient(135deg, var(--secondary-color), #02b3a3); color: #fff !important; border-radius: 12px; padding: 0.8rem 2.5rem; font-weight: 600; font-size: 1.2rem; border: none; width: 100%; }
280
+ </style>
281
+ """, unsafe_allow_html=True)
282
+
283
+ st.markdown('<h1 class="main-title">Motion Capture Studio</h1>', unsafe_allow_html=True)
284
+ st.markdown('<p class="subtitle">Convert videos to BVH with AI</p>', unsafe_allow_html=True)
285
+
286
+ api = setup_kaggle_api()
287
+ drive_service = setup_drive_service()
288
+
289
+ st.markdown('<div class="card">', unsafe_allow_html=True)
290
+
291
+ st.markdown('<h3 class="section-title"></h3>', unsafe_allow_html=True)
292
+ status_col1, status_col2 = st.columns(2)
293
+ with status_col1:
294
+ try:
295
+ username = st.secrets['KAGGLE_USERNAME']
296
+ notebook_slug = f"{username}/video-to-bvh-converter"
297
+ kernel_exists = check_kernel_exists(api, notebook_slug)
298
+ if kernel_exists:
299
+ st.success(f"✅ Kaggle kernel found: {notebook_slug}")
300
+ else:
301
+ st.error(f"❌ Kaggle kernel not found: {notebook_slug}")
302
+ except Exception as e:
303
+ st.error(f"❌failed: {e}")
304
+
305
+ with status_col2:
306
+ try:
307
+ drive_about = drive_service.about().get(fields="user,storageQuota").execute()
308
+ storage_used = int(drive_about.get('storageQuota', {}).get('usage', 0)) / (1024 * 1024)
309
+ # st.success(f"✅ Google Drive: {storage_used:.2f} MB used")
310
+ except Exception as e:
311
+ st.error(f"❌Drive check failed: {e}")
312
+
313
+ col1, col2 = st.columns(2)
314
+ with col1:
315
+ st.markdown('<h3 class="section-title">Upload Video</h3>', unsafe_allow_html=True)
316
+ uploaded_file = st.file_uploader("Upload a video", type=['mp4', 'avi', 'mov'])
317
+ if uploaded_file:
318
+ st.session_state['uploaded_file'] = uploaded_file
319
+ with col2:
320
+ st.markdown('<h3 class="section-title">Preview</h3>', unsafe_allow_html=True)
321
+ if uploaded_file := st.session_state.get('uploaded_file'):
322
+ st.video(uploaded_file)
323
+
324
+ if st.session_state.get('uploaded_file'):
325
+ st.markdown('<h3 class="section-title">Processing Options</h3>', unsafe_allow_html=True)
326
+
327
+ if st.button("Start Motion Capture"):
328
+ result = process_video(api, drive_service, st.session_state['uploaded_file'])
329
+
330
+ if result and 'bvh_data' in result:
331
+ st.success("Motion capture complete!")
332
+ st.download_button(
333
+ label="Download BVH",
334
+ data=result['bvh_data'],
335
+ file_name="motion_capture.bvh",
336
+ mime="application/octet-stream"
337
+ )
338
+ else:
339
+ st.error("Failed to retrieve BVH file.")
340
+ st.markdown('</div>', unsafe_allow_html=True)
341
+
342
+ if __name__ == "__main__":
343
+ main()
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ streamlit
2
+ requests
3
+ kaggle
4
+ google-auth
5
+ google-auth-oauthlib
6
+ google-auth-httplib2
7
+ google-api-python-client
video-to-bvh-converter.ipynb ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "id": "89e3002b",
7
+ "metadata": {
8
+ "execution": {
9
+ "iopub.execute_input": "2025-03-14T05:12:16.674040Z",
10
+ "iopub.status.busy": "2025-03-14T05:12:16.673708Z",
11
+ "iopub.status.idle": "2025-03-14T05:13:18.208584Z",
12
+ "shell.execute_reply": "2025-03-14T05:13:18.207541Z"
13
+ },
14
+ "papermill": {
15
+ "duration": 61.539518,
16
+ "end_time": "2025-03-14T05:13:18.210064",
17
+ "exception": false,
18
+ "start_time": "2025-03-14T05:12:16.670546",
19
+ "status": "completed"
20
+ },
21
+ "tags": []
22
+ },
23
+ "outputs": [],
24
+ "source": [
25
+ "print(\"Notebook starting... Processing video\")\n",
26
+ "import torch\n",
27
+ "print(f\"CUDA available: {torch.cuda.is_available()}\")\n",
28
+ "if not torch.cuda.is_available():\n",
29
+ " print(\"Error: GPU not enabled!\")\n",
30
+ " raise SystemExit\n",
31
+ "\n",
32
+ "!pip install yacs filterpy\n",
33
+ "\n",
34
+ "print(\"Step 1: Setting up credentials\")\n",
35
+ "import json\n",
36
+ "from google.oauth2.credentials import Credentials\n",
37
+ "from googleapiclient.discovery import build\n",
38
+ "from googleapiclient.http import MediaFileUpload\n",
39
+ "import requests\n",
40
+ "import os\n",
41
+ "\n",
42
+ "# Your Google Service Account credentials\n",
43
+ "creds_json_str = '''{\n",
44
+ " \\\"access_token\\\": \\\"ya29.a0AeXRPp5eK0IR7UOeIaD7V3ZOO37FC-rt1sD7tPtI1j4LvplLP9E7_tPG2rrUntaJHkyfmsNxoniVZvYNkzWPZm7paz65QorGwH80JdUJpZmQ4cfYHMfd0iGg66xXExIRCOHKbviIhhT-w7NwVIAThev4AThLcxv9pPoqT4rXaCgYKAYISARASFQHGX2MinmOp3txeX39z5NSXJLwLVw0175\\\",\n",
45
+ " \\\"client_id\\\": \\\"139895089923-huvuh3go85dvt35cegmp03qc889hq2f5.apps.googleusercontent.com\\\",\n",
46
+ " \\\"client_secret\\\": \\\"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\\\",\n",
47
+ " \\\"refresh_token\\\": \\\"1//0gWY-U2AQ2zTSCgYIARAAGBASNwF-L9IrM2ekQEbgTPYOhgcGuRds2WineBX7yvMGNZbfje4p37n_82H17dr6gZbopnMwbzLn5dw\\\",\n",
48
+ " \\\"token_uri\\\": \\\"https://oauth2.googleapis.com/token\\\",\n",
49
+ " \\\"scopes\\\": [\\\"https://www.googleapis.com/auth/drive\\\"]\n",
50
+ "}'''\n",
51
+ "creds_json = json.loads(creds_json_str)\n",
52
+ "credentials = Credentials(\n",
53
+ " token=creds_json['access_token'],\n",
54
+ " refresh_token=creds_json['refresh_token'],\n",
55
+ " client_id=creds_json['client_id'],\n",
56
+ " client_secret=creds_json['client_secret'],\n",
57
+ " token_uri=creds_json['token_uri'],\n",
58
+ " scopes=creds_json['scopes']\n",
59
+ ")\n",
60
+ "if credentials.expired and credentials.refresh_token:\n",
61
+ " credentials.refresh(requests.Request())\n",
62
+ "drive_service = build('drive', 'v3', credentials=credentials)\n",
63
+ "\n",
64
+ "print(\"Step 2: Downloading pipeline ZIP\")\n",
65
+ "ZIP_FILE_ID = \"1KkmkzZLDePje6O3W7u0DvA8wKQJcRg_q\" # Your pipeline.zip file ID\n",
66
+ "zip_path = \"/kaggle/working/pipeline.zip\"\n",
67
+ "try:\n",
68
+ " request = drive_service.files().get_media(fileId=ZIP_FILE_ID)\n",
69
+ " with open(zip_path, 'wb') as f:\n",
70
+ " downloader = request.execute()\n",
71
+ " f.write(downloader)\n",
72
+ "except Exception as e:\n",
73
+ " print(f\"Error downloading ZIP: {str(e)}\")\n",
74
+ " raise SystemExit\n",
75
+ "\n",
76
+ "import zipfile\n",
77
+ "extract_dir = \"/kaggle/working/pipeline\"\n",
78
+ "os.makedirs(extract_dir, exist_ok=True)\n",
79
+ "with zipfile.ZipFile(zip_path, 'r') as zip_ref:\n",
80
+ " zip_ref.extractall(extract_dir)\n",
81
+ "print(\"Pipeline ZIP extracted successfully\")\n",
82
+ "\n",
83
+ "print(\"Step 3: Finding and downloading a video from folder\")\n",
84
+ "FOLDER_ID = \"1T6v7Iqc90-NA-F3I-HeHDSvEaIyFibKd\"\n",
85
+ "query = f\"'{FOLDER_ID}' in parents and (mimeType='video/mp4' or mimeType='video/avi' or mimeType='video/quicktime')\"\n",
86
+ "response = drive_service.files().list(q=query, fields=\"files(id, name)\", pageSize=1).execute()\n",
87
+ "files = response.get('files', [])\n",
88
+ "\n",
89
+ "if not files:\n",
90
+ " print(f\"Error: No video files found in folder {FOLDER_ID}\")\n",
91
+ " raise SystemExit\n",
92
+ "\n",
93
+ "video_file = files[0]\n",
94
+ "video_id = video_file['id']\n",
95
+ "video_name = video_file['name']\n",
96
+ "video_url = f\"https://drive.google.com/uc?id={video_id}\"\n",
97
+ "print(f\"Found video: {video_name} (ID: {video_id})\")\n",
98
+ "\n",
99
+ "response = requests.get(video_url)\n",
100
+ "if response.status_code != 200:\n",
101
+ " print(f\"Error downloading video: {response.status_code}\")\n",
102
+ " raise SystemExit\n",
103
+ "video_path = os.path.join(extract_dir, \"input_video.mp4\")\n",
104
+ "with open(video_path, 'wb') as f:\n",
105
+ " f.write(response.content)\n",
106
+ "print(f\"Video downloaded to {video_path}, size: {os.path.getsize(video_path)} bytes\")\n",
107
+ "\n",
108
+ "print(\"Step 4: Verifying video with OpenCV\")\n",
109
+ "import cv2\n",
110
+ "cap = cv2.VideoCapture(video_path)\n",
111
+ "if not cap.isOpened():\n",
112
+ " print(f\"Error: OpenCV cannot open {video_path}\")\n",
113
+ " print(f\"File exists: {os.path.exists(video_path)}\")\n",
114
+ " print(f\"File size: {os.path.getsize(video_path) if os.path.exists(video_path) else 'N/A'} bytes\")\n",
115
+ " raise SystemExit\n",
116
+ "print(f\"Video verified: {video_path}, frames: {int(cap.get(cv2.CAP_PROP_FRAME_COUNT))}\")\n",
117
+ "cap.release()\n",
118
+ "\n",
119
+ "print(\"Step 5: Running pipeline\")\n",
120
+ "os.chdir(extract_dir)\n",
121
+ "import subprocess\n",
122
+ "cmd = ['python', 'pipeline.py', '-v', video_path]\n",
123
+ "process = subprocess.run(cmd, capture_output=True, text=True)\n",
124
+ "print(\"pipeline.py output:\", process.stdout)\n",
125
+ "if process.stderr:\n",
126
+ " print(\"pipeline.py errors:\", process.stderr)\n",
127
+ "if process.returncode != 0:\n",
128
+ " print(f\"Error running pipeline.py (return code: {process.returncode})\")\n",
129
+ " raise SystemExit\n",
130
+ "print(\"Pipeline executed successfully\")\n",
131
+ "\n",
132
+ "print(\"Step 6: Uploading BVH\")\n",
133
+ "bvh_path = os.path.join(extract_dir, \"outputs\", \"bvh\", \"output.bvh\")\n",
134
+ "if os.path.exists(bvh_path):\n",
135
+ " file_metadata = {'name': 'output.bvh', 'parents': ['1T6v7Iqc90-NA-F3I-HeHDSvEaIyFibKd']}\n",
136
+ " media = MediaFileUpload(bvh_path, resumable=True)\n",
137
+ " file = drive_service.files().create(body=file_metadata, media_body=media, fields='id').execute()\n",
138
+ " drive_service.permissions().create(fileId=file['id'], body={'type': 'anyone', 'role': 'reader'}).execute()\n",
139
+ " bvh_url = f\"https://drive.google.com/uc?id={file['id']}\"\n",
140
+ " print(f\"BVH URL: {bvh_url}\")\n",
141
+ "else:\n",
142
+ " print(\"Error: BVH file not generated\")\n",
143
+ " raise SystemExit"
144
+ ]
145
+ }
146
+ ],
147
+ "metadata": {
148
+ "kaggle": {
149
+ "accelerator": "gpu",
150
+ "dataSources": [],
151
+ "dockerImageVersionId": 30919,
152
+ "isGpuEnabled": true,
153
+ "isInternetEnabled": true,
154
+ "language": "python",
155
+ "sourceType": "notebook"
156
+ },
157
+ "kernelspec": {
158
+ "display_name": "Python 3",
159
+ "language": "python",
160
+ "name": "python3"
161
+ },
162
+ "language_info": {
163
+ "codemirror_mode": {
164
+ "name": "ipython",
165
+ "version": 3
166
+ },
167
+ "file_extension": ".py",
168
+ "mimetype": "text/x-python",
169
+ "name": "python",
170
+ "nbconvert_exporter": "python",
171
+ "pygments_lexer": "ipython3",
172
+ "version": "3.10.12"
173
+ },
174
+ "papermill": {
175
+ "default_parameters": {},
176
+ "duration": 65.17859,
177
+ "end_time": "2025-03-14T05:13:19.233309",
178
+ "environment_variables": {},
179
+ "exception": null,
180
+ "input_path": "__notebook__.ipynb",
181
+ "output_path": "__notebook__.ipynb",
182
+ "parameters": {},
183
+ "start_time": "2025-03-14T05:12:14.054719",
184
+ "version": "2.6.0"
185
+ }
186
+ },
187
+ "nbformat": 4,
188
+ "nbformat_minor": 5
189
+ }