Spaces:
Sleeping
Sleeping
fix: transcoding issue
Browse files- Dockerfile +1 -0
- requirements.txt +1 -1
- 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 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 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)
|