deepinsight/insightface · error · ValueError

Video writer could not be opened.

Error message

Video writer could not be opened.

What it means

cv2.VideoWriter failed to open the output MP4 (writer.isOpened() False) — the mp4v codec could not be initialized for the given path/fps/size combination, so the swapped video cannot be written.

Source

Thrown at python-package/insightface/gui/pages/face_swap_page.py:251

        except Exception as exc:
            raise ValueError(f"OpenCV is required for video face swap: {exc}") from exc

        cap = cv2.VideoCapture(target_path)
        if not cap.isOpened():
            raise ValueError("Video could not be opened.")
        fps = cap.get(cv2.CAP_PROP_FPS) or 25.0
        width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH) or 0)
        height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT) or 0)
        frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT) or 0)
        if width <= 0 or height <= 0:
            cap.release()
            raise ValueError("Video dimensions could not be read.")
        output_path = Path(self.context.config.export_dir) / f"face_swap_video_{timestamp_for_filename()}.mp4"
        output_path.parent.mkdir(parents=True, exist_ok=True)
        writer = cv2.VideoWriter(str(output_path), cv2.VideoWriter_fourcc(*"mp4v"), fps, (width, height))
        if not writer.isOpened():
            cap.release()
            raise ValueError("Video writer could not be opened.")

        preview = None
        swapped = 0
        processed = 0
        try:
            while True:
                if is_cancelled and is_cancelled():
                    break
                ok, frame = cap.read()
                if not ok:
                    break
                output_frame = frame
                target_face = self.context.engine.detect_best_face(frame, source_path=target_path)
                if target_face is not None and target_face.kps is not None:
                    target_native = SimpleNamespace(kps=np.asarray(target_face.kps, dtype=np.float32))
                    output_frame = swapper.swap(frame, target_native, source_native)
                    swapped += 1
                    if preview is None:

View on GitHub (pinned to 7fadd420c2)

Solutions

  1. Check export_dir exists, is writable, and the disk has free space
  2. Try 'avc1' or 'XVID' (.avi) fourcc instead of 'mp4v'
  3. Sanitize fps: clamp to a sane range (e.g. 1–120) before constructing the writer
  4. If the encoder is missing, install full opencv-python or write frames with imageio/ffmpeg instead

Example fix

# before
writer = cv2.VideoWriter(str(out), cv2.VideoWriter_fourcc(*"mp4v"), fps, (w, h))
# after
fps = min(max(fps, 1.0), 120.0)
fourcc = cv2.VideoWriter_fourcc(*"avc1")
writer = cv2.VideoWriter(str(out), fourcc, fps, (w, h))
if not writer.isOpened():
    writer = cv2.VideoWriter(str(out.with_suffix(".avi")), cv2.VideoWriter_fourcc(*"XVID"), fps, (w, h))
Defensive patterns

Strategy: fallback

Validate before calling

fps = float(fps or 25.0); fps = min(max(fps, 1.0), 120.0
if width > 0 and height > 0 and os.access(out_dir, os.W_OK):
    writer = cv2.VideoWriter(...)

Try / catch

try:
    return self._swap_video(...)
except ValueError as e:
    if 'writer' in str(e): write_avi_xvid_fallback()

Prevention

When it happens

Trigger: The export directory is unwritable, disk is full, or the OpenCV build lacks the mp4v (MPEG-4 part 2) encoder; also occurs with unusual fps values like 0 or inf, or zero dimensions passed through.

Common situations: Headless Docker images with opencv-python-headless lacking encoder support, read-only export_dir config, extremely high fps reported by broken streams, or paths containing characters the backend rejects.

Related errors


AI-assisted analysis of deepinsight/insightface@7fadd420c2 (2026-08-28). Data as JSON: /api/errors/9f9693437b708769. Report an issue: GitHub.