-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathinstall_dcv_sdk.py
More file actions
283 lines (235 loc) · 11.1 KB
/
Copy pathinstall_dcv_sdk.py
File metadata and controls
283 lines (235 loc) · 11.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
#!/usr/bin/env python3
"""
Automatically download and install Amazon DCV Web Client SDK
"""
import os
import zipfile
import shutil
from pathlib import Path
import urllib.request
from rich.console import Console
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, DownloadColumn, TransferSpeedColumn
console = Console()
DCV_SDK_URL = "https://d1uj6qtbmh3dt5.cloudfront.net/webclientsdk/nice-dcv-web-client-sdk-1.9.100-952.zip"
DCV_SDK_VERSION = "1.9.100-952"
def download_dcv_sdk(download_dir: Path) -> Path:
"""Download DCV SDK zip file."""
zip_path = download_dir / f"dcv-sdk-{DCV_SDK_VERSION}.zip"
if zip_path.exists():
console.print(f"[yellow]⚠️ DCV SDK zip already exists: {zip_path}[/yellow]")
response = console.input("[dim]Re-download? (y/N): [/dim]")
if response.lower() != 'y':
return zip_path
console.print(f"[cyan]📥 Downloading DCV SDK {DCV_SDK_VERSION}...[/cyan]")
console.print(f"[dim]URL: {DCV_SDK_URL}[/dim]")
try:
with Progress(
SpinnerColumn(),
TextColumn("[progress.description]{task.description}"),
BarColumn(),
DownloadColumn(),
TransferSpeedColumn(),
console=console
) as progress:
task = progress.add_task("[cyan]Downloading...", total=None)
def update_progress(block_num, block_size, total_size):
if total_size > 0:
progress.update(task, total=total_size, completed=block_num * block_size)
urllib.request.urlretrieve(DCV_SDK_URL, zip_path, reporthook=update_progress)
console.print(f"[green]✅ Downloaded: {zip_path}[/green]")
return zip_path
except Exception as e:
console.print(f"[red]❌ Failed to download DCV SDK: {e}[/red]")
raise
def extract_dcv_sdk(zip_path: Path, extract_dir: Path) -> Path:
"""Extract DCV SDK zip file."""
console.print(f"[cyan]📦 Extracting DCV SDK...[/cyan]")
extract_dir.mkdir(parents=True, exist_ok=True)
try:
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
# Get total size for progress
total_size = sum(info.file_size for info in zip_ref.infolist())
extracted_size = 0
with Progress(
SpinnerColumn(),
TextColumn("[progress.description]{task.description}"),
BarColumn(),
console=console
) as progress:
task = progress.add_task("[cyan]Extracting...", total=total_size)
for info in zip_ref.infolist():
zip_ref.extract(info, extract_dir)
extracted_size += info.file_size
progress.update(task, completed=extracted_size)
console.print(f"[green]✅ Extracted to: {extract_dir}[/green]")
# Find all candidate directories that contain dcv.js
candidates = [item.parent for item in extract_dir.rglob("dcv.js")]
preferred_dir = None
if candidates:
# Prefer UMD build if available
for candidate in candidates:
lower = str(candidate).lower()
if "dcvjs-umd" in lower or lower.endswith("umd"):
preferred_dir = candidate
break
if not preferred_dir:
preferred_dir = candidates[0]
if preferred_dir:
if preferred_dir not in candidates[:1]:
console.print(f"[cyan]ℹ️ Using preferred DCV UMD build at: {preferred_dir}[/cyan]")
else:
console.print(f"[green]✅ Found dcv.js in: {preferred_dir}[/green]")
return preferred_dir
# Fallback: try common directory names explicitly
possible_dirs = [
extract_dir / "dcvjs-umd",
extract_dir / "dcvjs",
extract_dir / "nice-dcv-web-client-sdk-1.9.100-952" / "dcvjs-umd",
extract_dir / "nice-dcv-web-client-sdk-1.9.100-952" / "dcvjs",
]
for possible_dir in possible_dirs:
if possible_dir.exists() and (possible_dir / "dcv.js").exists():
console.print(f"[green]✅ Found dcv.js in: {possible_dir}[/green]")
return possible_dir
# List extracted contents for debugging
console.print(f"[yellow]⚠️ Could not find dcv.js. Extracted contents:[/yellow]")
for item in extract_dir.iterdir():
if item.is_dir():
console.print(f"[dim] Directory: {item.name}[/dim]")
# List first level subdirectories
try:
for subitem in item.iterdir():
if subitem.is_dir():
console.print(f"[dim] └── {subitem.name}/[/dim]")
elif subitem.name == "dcv.js":
console.print(f"[green] └── {subitem.name} (FOUND!)[/green]")
return subitem.parent
except:
pass
raise FileNotFoundError("dcv.js not found in extracted archive")
except Exception as e:
console.print(f"[red]❌ Failed to extract DCV SDK: {e}[/red]")
raise
def install_dcv_sdk(target_dir: Path, source_dir: Path):
"""Install DCV SDK files to target directory."""
console.print(f"[cyan]📋 Installing DCV SDK to: {target_dir}[/cyan]")
console.print(f"[dim]Source directory: {source_dir}[/dim]")
target_dir.mkdir(parents=True, exist_ok=True)
# Required files and directories
required_files = [
"dcv.js",
"dcv/broadwayh264decoder-worker.js",
"dcv/jsmpegdecoder-worker.js",
"dcv/lz4decoder-worker.js",
"dcv/microphoneprocessor.js"
]
# Copy dcv.js
dcv_js_source = source_dir / "dcv.js"
if not dcv_js_source.exists():
console.print(f"[red]❌ dcv.js not found in {source_dir}[/red]")
console.print(f"[yellow]Listing contents of {source_dir}:[/yellow]")
try:
for item in source_dir.iterdir():
if item.is_file():
console.print(f"[dim] File: {item.name}[/dim]")
elif item.is_dir():
console.print(f"[dim] Directory: {item.name}/[/dim]")
except Exception as e:
console.print(f"[dim] Error listing: {e}[/dim]")
raise FileNotFoundError(f"dcv.js not found in {source_dir}")
shutil.copy2(dcv_js_source, target_dir / "dcv.js")
console.print(f"[green]✅ Copied dcv.js[/green]")
# Copy dcv directory
dcv_dir_source = source_dir / "dcv"
dcv_dir_target = target_dir / "dcv"
if dcv_dir_source.exists():
if dcv_dir_target.exists():
shutil.rmtree(dcv_dir_target)
shutil.copytree(dcv_dir_source, dcv_dir_target)
console.print(f"[green]✅ Copied dcv/ directory[/green]")
else:
console.print(f"[yellow]⚠️ dcv/ directory not found in {source_dir}[/yellow]")
console.print(f"[dim]Checking for dcv directory in subdirectories...[/dim]")
# Try to find dcv directory recursively
found_dcv = False
for item in source_dir.rglob("dcv"):
if item.is_dir() and item.name == "dcv":
console.print(f"[green]✅ Found dcv/ directory at: {item}[/green]")
if dcv_dir_target.exists():
shutil.rmtree(dcv_dir_target)
shutil.copytree(item, dcv_dir_target)
console.print(f"[green]✅ Copied dcv/ directory[/green]")
found_dcv = True
break
if not found_dcv:
console.print(f"[yellow]⚠️ dcv/ directory not found, creating empty directory...[/yellow]")
dcv_dir_target.mkdir(parents=True, exist_ok=True)
# Copy lib directory if it exists
lib_dir_source = source_dir / "lib"
lib_dir_target = target_dir / "lib"
if lib_dir_source.exists():
if lib_dir_target.exists():
shutil.rmtree(lib_dir_target)
shutil.copytree(lib_dir_source, lib_dir_target)
console.print(f"[green]✅ Copied lib/ directory[/green]")
else:
# Try to find lib directory recursively
for item in source_dir.rglob("lib"):
if item.is_dir() and item.name == "lib":
console.print(f"[green]✅ Found lib/ directory at: {item}[/green]")
if lib_dir_target.exists():
shutil.rmtree(lib_dir_target)
shutil.copytree(item, lib_dir_target)
console.print(f"[green]✅ Copied lib/ directory[/green]")
break
# Verify installation
missing_files = []
for file_path in required_files:
full_path = target_dir / file_path
if not full_path.exists():
missing_files.append(file_path)
if missing_files:
console.print(f"[yellow]⚠️ Some files are missing: {', '.join(missing_files)}[/yellow]")
console.print("[dim]The viewer may still work, but some features might not be available.[/dim]")
else:
console.print(f"[green]✅ All required files installed successfully![/green]")
# Check file size
dcv_js_size = (target_dir / "dcv.js").stat().st_size
if dcv_js_size < 10000:
console.print(f"[yellow]⚠️ dcv.js seems too small ({dcv_js_size} bytes)[/yellow]")
console.print("[dim]Expected size > 100KB. Please verify the installation.[/dim]")
else:
console.print(f"[green]✅ dcv.js size: {dcv_js_size:,} bytes[/green]")
def main():
"""Main installation function."""
console.print("\n[bold cyan]Amazon DCV Web Client SDK Installer[/bold cyan]\n")
# Determine target directory (same directory as browser_viewer.py)
script_dir = Path(__file__).parent
target_dir = script_dir / "static" / "dcvjs"
# Create temp directory for download and extraction
temp_dir = script_dir / ".dcv_temp"
temp_dir.mkdir(exist_ok=True)
try:
# Download
zip_path = download_dcv_sdk(temp_dir)
# Extract
extracted_dir = extract_dcv_sdk(zip_path, temp_dir / "extracted")
# Install
install_dcv_sdk(target_dir, extracted_dir)
console.print(f"\n[bold green]🎉 DCV SDK installation complete![/bold green]")
console.print(f"[dim]Installed to: {target_dir}[/dim]\n")
# Cleanup
console.print("[cyan]🧹 Cleaning up temporary files...[/cyan]")
if temp_dir.exists():
shutil.rmtree(temp_dir)
console.print("[green]✅ Cleanup complete[/green]\n")
except Exception as e:
console.print(f"\n[red]❌ Installation failed: {e}[/red]\n")
console.print("[yellow]You can manually download and install DCV SDK:[/yellow]")
console.print(f"[dim]1. Download from: {DCV_SDK_URL}[/dim]")
console.print(f"[dim]2. Extract and copy dcvjs-umd/* to: {target_dir}[/dim]\n")
return 1
return 0
if __name__ == "__main__":
import sys
sys.exit(main())