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

fix: transcoding issue

Browse files
Files changed (3) hide show
  1. Dockerfile +1 -0
  2. requirements.txt +1 -1
  3. utils/video.py +41 -13
Dockerfile CHANGED
@@ -9,6 +9,7 @@ COPY requirements.txt ./
9
  RUN apt-get update && apt-get install -y --no-install-recommends \
10
  libgl1 \
11
  libglib2.0-0 \
 
12
  && rm -rf /var/lib/apt/lists/* \
13
  && pip install --no-cache-dir --upgrade pip \
14
  && pip install --no-cache-dir -r requirements.txt
 
9
  RUN apt-get update && apt-get install -y --no-install-recommends \
10
  libgl1 \
11
  libglib2.0-0 \
12
+ ffmpeg \
13
  && rm -rf /var/lib/apt/lists/* \
14
  && pip install --no-cache-dir --upgrade pip \
15
  && pip install --no-cache-dir -r requirements.txt
requirements.txt CHANGED
@@ -2,7 +2,7 @@ fastapi
2
  uvicorn
3
  torch
4
  transformers
5
- opencv-python
6
  python-multipart
7
  accelerate
8
  pillow
 
2
  uvicorn
3
  torch
4
  transformers
5
+ opencv-python-headless
6
  python-multipart
7
  accelerate
8
  pillow
utils/video.py CHANGED
@@ -1,4 +1,8 @@
1
  import logging
 
 
 
 
2
  from typing import List, Tuple
3
 
4
  import cv2
@@ -28,24 +32,48 @@ def extract_frames(video_path: str) -> Tuple[List[np.ndarray], float, int, int]:
28
  return frames, fps, width, height
29
 
30
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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)
50
 
51
  writer.release()
 
 
 
 
 
 
 
 
 
 
 
1
  import logging
2
+ import os
3
+ import shutil
4
+ import subprocess
5
+ import tempfile
6
  from typing import List, Tuple
7
 
8
  import cv2
 
32
  return frames, fps, width, height
33
 
34
 
35
+ def _transcode_with_ffmpeg(src_path: str, dst_path: str) -> None:
36
+ cmd = [
37
+ "ffmpeg",
38
+ "-y",
39
+ "-i",
40
+ src_path,
41
+ "-c:v",
42
+ "libx264",
43
+ "-preset",
44
+ "veryfast",
45
+ "-pix_fmt",
46
+ "yuv420p",
47
+ "-movflags",
48
+ "+faststart",
49
+ dst_path,
50
+ ]
51
+ process = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False)
52
+ if process.returncode != 0:
53
+ raise RuntimeError(process.stderr.decode("utf-8", errors="ignore"))
54
+
55
+
56
  def write_video(frames: List[np.ndarray], output_path: str, fps: float, width: int, height: int) -> None:
57
  if not frames:
58
  raise ValueError("No frames available for writing.")
59
+ temp_fd, temp_path = tempfile.mkstemp(prefix="raw_", suffix=".mp4")
60
+ os.close(temp_fd)
61
+ writer = cv2.VideoWriter(temp_path, cv2.VideoWriter_fourcc(*"mp4v"), fps or 1.0, (width, height))
62
+ if not writer.isOpened():
63
+ os.remove(temp_path)
64
+ raise ValueError("Failed to open VideoWriter.")
 
 
 
 
 
 
 
65
 
66
  for frame in frames:
67
  writer.write(frame)
68
 
69
  writer.release()
70
+ try:
71
+ _transcode_with_ffmpeg(temp_path, output_path)
72
+ logging.debug("Transcoded video to H.264 for browser compatibility.")
73
+ os.remove(temp_path)
74
+ except FileNotFoundError:
75
+ logging.warning("ffmpeg not found; serving fallback MP4V output.")
76
+ shutil.move(temp_path, output_path)
77
+ except RuntimeError as exc:
78
+ logging.warning("ffmpeg transcode failed (%s); serving fallback MP4V output.", exc)
79
+ shutil.move(temp_path, output_path)