New Return to work safely with Swiftlane Health Check

Learn more
Photo

Generating MP4's Using opencv-python With the AVC1 Codec

This article is about a rabbit-hole I recently went down, no there will not be any Mad-Hatters or talking cats just video codecs and build flags. The task I was trying to complete seemed simple enough: Use OpenCV to generate a working MP4 video by concatenating frames. Originally I attempted the following and got the error below:

>>> import cv2
>>>
>>> fourcc = cv2.VideoWriter_fourcc(*"avc1")
>>> video_writer = cv2.VideoWriter("movie.mp4", fourcc, 5, (5,5))
Could not find encoder for codec id 27: Encoder not found
-

For licensing reasons ,opencv-python does not ship with some of the more common video codecs. The first solution I tried initially was to change the codec to mp4v with the following change.

fourcc = cv2.VideoWriter_fourcc(*"mp4v")

Problem solved! Let's go out for some drinks, right? Not so fast. Unfortunately, MP4V is not supported by most browsers, a fact I learned when I tried to embed one of these videos in a web application. After going down the rabbit hole for a while, I realized that the solution would involve compiling some of the sources manually. I could not find a comprehensive step-by-step solution, so I had to combine instructions from different sources. Below is the Dockerfile for my working image. Before you use it here are some things to know:

  • opencv-python is already installed on this image, if you re-install opencv-python using pip, it will break.
  • I have gotten the avc1 codec working for MP4 files, in order to use x264 or h264 I had to change the file extension to .mkv (If you know how to fix this let me know in the comments).
FROM ubuntu:18.04

WORKDIR /root

ENV OPENCV_VERSION=4.3.0 \
    PYTHON_VERSION=3.6 \
    PYTHON_VERSION_SHORT=36

RUN apt-get update
RUN apt-get remove -y ffmpeg x264 libx264-dev

RUN apt-get install -y \
    build-essential \
    cmake \
    libjack-jackd2-dev \
    libmp3lame-dev \
    libopencore-amrnb-dev \
    libopencore-amrwb-dev \
    libsdl1.2-dev \
    libtheora-dev \
    libva-dev \
    libvdpau-dev \
    libvorbis-dev \
    libx11-dev \
    libxfixes-dev \
    libxvidcore-dev \
    texi2html \
    zlib1g-dev \
    wget \
    unzip \
    yasm \
    pkg-config \
    libswscale-dev \
    libtbb2 \
    libtbb-dev \
    libjpeg-dev \
    libpng-dev \
    libtiff-dev \
    libavformat-dev \
    python${PYTHON_VERSION} \
    python3-pip \
    libpq-dev

RUN apt-get remove -y x264 ffmpeg libx264-dev && \
    apt-get install -y x264 libx264-dev && \
    apt-get install -y ffmpeg && \
    pip3 install numpy

RUN wget https://github.com/opencv/opencv/archive/${OPENCV_VERSION}.zip && \
    unzip ${OPENCV_VERSION}.zip && \
    mkdir opencv-${OPENCV_VERSION}/build

WORKDIR /root/opencv-${OPENCV_VERSION}/build

RUN cmake \
  -DBUILD_TIFF=ON \
  -DBUILD_opencv_java=OFF \
  -DWITH_CUDA=OFF \
  -DWITH_OPENGL=ON \
  -DWITH_OPENCL=ON \
  -DWITH_IPP=ON \
  -DWITH_TBB=ON \
  -DWITH_EIGEN=ON \
  -DWITH_V4L=ON \
  -DBUILD_TESTS=OFF \
  -DBUILD_PERF_TESTS=OFF \
  -DCMAKE_BUILD_TYPE=RELEASE \
  -DCMAKE_INSTALL_PREFIX=$(python${PYTHON_VERSION} -c "import sys; print(sys.prefix)") \
  -DPYTHON_EXECUTABLE=$(which python${PYTHON_VERSION}) \
  -DPYTHON_INCLUDE_DIR=$(python${PYTHON_VERSION} -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())") \
  -DPYTHON_PACKAGES_PATH=$(python${PYTHON_VERSION} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())") \
  -DPYTHON_DEFAULT_EXECUTABLE=$(which python${PYTHON_VERSION}) \
  -DBUILD_NEW_PYTHON_SUPPORT=ON \
  -DBUILD_opencv_python3=ON \
  -DHAVE_opencv_python3=ON \
  -DBUILD_opencv_gapi=OFF \
  -DPYTHON3_NUMPY_INCLUDE_DIRS=/usr/local/lib/python${PYTHON_VERSION}/dist-packages/numpy/core/include \
  .. \
 && make install

RUN mv \
  /root/opencv-${OPENCV_VERSION}/build/lib/python3/cv2.cpython-${PYTHON_VERSION_SHORT}m-x86_64-linux-gnu.so \
  /usr/local/lib/python${PYTHON_VERSION}/dist-packages/cv2.so

RUN unlink /usr/bin/python && ln -s /usr/bin/python3 /usr/bin/python

WORKDIR /root

RUN apt clean && \
    rm -rf /var/lib/apt/lists/* && \
    rm -rf /root/opencv-${OPENCV_VERSION}