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-pythonis already installed on this image, if you re-install opencv-python using pip, it will break.- I have gotten the
avc1codec working for MP4 files, in order to usex264orh264I 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}




