zye0616 commited on
Commit
4993eb8
·
1 Parent(s): 51780f2

fix: browser compatibility

Browse files
Files changed (2) hide show
  1. demo.html +25 -0
  2. utils/video.py +14 -4
demo.html CHANGED
@@ -166,11 +166,18 @@ async function executeMission() {
166
  videoForm.append("prompt", mission);
167
  videoForm.append("detector", detector);
168
 
 
169
  const response = await fetch(PROCESS_VIDEO_URL, {
170
  method: "POST",
171
  body: videoForm
172
  });
173
 
 
 
 
 
 
 
174
  if (!response.ok) {
175
  let errorDetail = `Request failed (${response.status})`;
176
  try {
@@ -183,10 +190,21 @@ async function executeMission() {
183
  }
184
 
185
  const videoBlob = await response.blob();
 
186
  const videoUrl = URL.createObjectURL(videoBlob);
187
  const videoEl = document.getElementById("processedVideo");
 
 
 
 
 
 
188
  videoEl.src = videoUrl;
189
  videoEl.load();
 
 
 
 
190
 
191
  statusEl.textContent = "Generating summary...";
192
 
@@ -195,6 +213,7 @@ async function executeMission() {
195
  summaryForm.append("prompt", mission);
196
  summaryForm.append("detector", detector);
197
 
 
198
  const summaryResponse = await fetch(SUMMARY_URL, {
199
  method: "POST",
200
  body: summaryForm
@@ -208,6 +227,12 @@ async function executeMission() {
208
  throw new Error(errorDetail);
209
  }
210
 
 
 
 
 
 
 
211
  const summaryJson = await summaryResponse.json();
212
  const summaryText = summaryJson.mission_summary || "No summary returned.";
213
  summaryEl.textContent = summaryText;
 
166
  videoForm.append("prompt", mission);
167
  videoForm.append("detector", detector);
168
 
169
+ console.log("[process_video] submitting request", { detector, missionLength: mission.length, fileSize: videoFile.size });
170
  const response = await fetch(PROCESS_VIDEO_URL, {
171
  method: "POST",
172
  body: videoForm
173
  });
174
 
175
+ console.log(
176
+ "[process_video] response meta",
177
+ response.status,
178
+ response.statusText,
179
+ { contentLength: response.headers.get("content-length"), contentType: response.headers.get("content-type") }
180
+ );
181
  if (!response.ok) {
182
  let errorDetail = `Request failed (${response.status})`;
183
  try {
 
190
  }
191
 
192
  const videoBlob = await response.blob();
193
+ console.log("[process_video] blob size", videoBlob.size, videoBlob.type);
194
  const videoUrl = URL.createObjectURL(videoBlob);
195
  const videoEl = document.getElementById("processedVideo");
196
+ videoEl.addEventListener("loadeddata", () => {
197
+ console.log("[process_video] video loadeddata event", videoEl.readyState);
198
+ }, { once: true });
199
+ videoEl.addEventListener("error", (event) => {
200
+ console.error("[process_video] video error", videoEl.error, event);
201
+ }, { once: true });
202
  videoEl.src = videoUrl;
203
  videoEl.load();
204
+ console.log("[process_video] video element readyState after load()", videoEl.readyState);
205
+ if (videoEl.error) {
206
+ console.error("[process_video] immediate video error", videoEl.error);
207
+ }
208
 
209
  statusEl.textContent = "Generating summary...";
210
 
 
213
  summaryForm.append("prompt", mission);
214
  summaryForm.append("detector", detector);
215
 
216
+ console.log("[mission_summary] submitting request", { detector, missionLength: mission.length, fileSize: videoFile.size });
217
  const summaryResponse = await fetch(SUMMARY_URL, {
218
  method: "POST",
219
  body: summaryForm
 
227
  throw new Error(errorDetail);
228
  }
229
 
230
+ console.log(
231
+ "[mission_summary] response meta",
232
+ summaryResponse.status,
233
+ summaryResponse.statusText,
234
+ { contentLength: summaryResponse.headers.get("content-length"), contentType: summaryResponse.headers.get("content-type") }
235
+ );
236
  const summaryJson = await summaryResponse.json();
237
  const summaryText = summaryJson.mission_summary || "No summary returned.";
238
  summaryEl.textContent = summaryText;
utils/video.py CHANGED
@@ -1,3 +1,4 @@
 
1
  from typing import List, Tuple
2
 
3
  import cv2
@@ -30,10 +31,19 @@ def extract_frames(video_path: str) -> Tuple[List[np.ndarray], float, int, int]:
30
  def write_video(frames: List[np.ndarray], output_path: str, fps: float, width: int, height: int) -> None:
31
  if not frames:
32
  raise ValueError("No frames available for writing.")
33
- fourcc = cv2.VideoWriter_fourcc(*"mp4v")
34
- writer = cv2.VideoWriter(output_path, fourcc, fps or 1.0, (width, height))
35
- if not writer.isOpened():
36
- raise ValueError("Failed to open VideoWriter.")
 
 
 
 
 
 
 
 
 
37
 
38
  for frame in frames:
39
  writer.write(frame)
 
1
+ import logging
2
  from typing import List, Tuple
3
 
4
  import cv2
 
31
  def write_video(frames: List[np.ndarray], output_path: str, fps: float, width: int, height: int) -> None:
32
  if not frames:
33
  raise ValueError("No frames available for writing.")
34
+ candidates = ("avc1", "mp4v")
35
+ writer = None
36
+ for codec in candidates:
37
+ fourcc = cv2.VideoWriter_fourcc(*codec)
38
+ writer = cv2.VideoWriter(output_path, fourcc, fps or 1.0, (width, height))
39
+ if writer.isOpened():
40
+ if codec != candidates[0]:
41
+ logging.warning("Falling back to %s codec for VideoWriter.", codec)
42
+ break
43
+ writer.release()
44
+ writer = None
45
+ if writer is None or not writer.isOpened():
46
+ raise ValueError("Failed to open VideoWriter with a supported codec.")
47
 
48
  for frame in frames:
49
  writer.write(frame)