I have a hard requirement of python3.7 for certain libraries (aeneas & afaligner). I've been using the regular opencv-python and ffmpeg libraries in my program and they've been working find.
Recently I wanted to adjust my program to use h264 instead of mpeg4 and ran down a licensing rabbit hole of how opencv-python uses a build of ffmpeg with opengl codecs off to avoid licensing issues. x264 is apparently opengl, and is disabled in the opencv-python library.
In order to solve this issue, I built a custom build of opencv using another custom build of ffmpeg both with opengl enabled. This allowed me to use the x264 encoder with the VideoWriter in my python program.
Here's the dockerfile of how I've been running it:
FROM python:3.7-slim
# Set optimization flags and number of cores globally
ENV CFLAGS="-O3 -march=native -ffast-math -flto -fno-fat-lto-objects -ffunction-sections -fdata-sections" \
CXXFLAGS="-O3 -march=native -ffast-math -flto -fno-fat-lto-objects -ffunction-sections -fdata-sections" \
LDFLAGS="-flto -fno-fat-lto-objects -Wl,--gc-sections" \
MAKEFLAGS="-j\$(nproc)"
# Combine all system dependencies in a single layer
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
cmake \
git \
wget \
unzip \
yasm \
pkg-config \
libsm6 \
libxext6 \
libxrender-dev \
libglib2.0-0 \
libavcodec-dev \
libavformat-dev \
libswscale-dev \
libavutil-dev \
libswresample-dev \
nasm \
mercurial \
libnuma-dev \
espeak \
libespeak-dev \
libtiff5-dev \
libjpeg62-turbo-dev \
libopenjp2-7-dev \
zlib1g-dev \
libfreetype6-dev \
liblcms2-dev \
libwebp-dev \
tcl8.6-dev \
tk8.6-dev \
python3-tk \
libharfbuzz-dev \
libfribidi-dev \
libxcb1-dev \
python3-dev \
python3-setuptools \
libsndfile1 \
libavdevice-dev \
libavfilter-dev \
libpostproc-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Build x264 with optimizations
RUN cd /tmp && \
wget .tar.bz2 && \
tar xjf x264-master.tar.bz2 && \
cd x264-master && \
./configure \
--enable-shared \
--enable-pic \
--enable-asm \
--enable-lto \
--enable-strip \
--enable-optimizations \
--bit-depth=8 \
--disable-avs \
--disable-swscale \
--disable-lavf \
--disable-ffms \
--disable-gpac \
--disable-lsmash \
--extra-cflags="-O3 -march=native -ffast-math -fomit-frame-pointer -flto -fno-fat-lto-objects" \
--extra-ldflags="-O3 -flto -fno-fat-lto-objects" && \
make && \
make install && \
cd /tmp && \
# Build FFmpeg with optimizations
wget .1.tar.bz2 && \
tar xjf ffmpeg-7.1.tar.bz2 && \
cd ffmpeg-7.1 && \
./configure \
--enable-gpl \
--enable-libx264 \
--enable-shared \
--enable-nonfree \
--enable-pic \
--enable-asm \
--enable-optimizations \
--enable-lto \
--enable-pthreads \
--disable-debug \
--disable-static \
--disable-doc \
--disable-ffplay \
--disable-ffprobe \
--disable-filters \
--disable-programs \
--disable-postproc \
--extra-cflags="-O3 -march=native -ffast-math -fomit-frame-pointer -flto -fno-fat-lto-objects -ffunction-sections -fdata-sections" \
--extra-ldflags="-O3 -flto -fno-fat-lto-objects -Wl,--gc-sections" \
--prefix=/usr/local && \
make && \
make install && \
ldconfig && \
rm -rf /tmp/*
# Install Python dependencies first
RUN pip install --no-cache-dir --upgrade pip setuptools wheel && \
pip install --no-cache-dir numpy py-spy
# Build OpenCV with optimized configuration
RUN cd /tmp && \
# Download specific OpenCV version archives
wget -O opencv.zip .8.0.zip && \
wget -O opencv_contrib.zip .8.0.zip && \
unzip opencv.zip && \
unzip opencv_contrib.zip && \
mv opencv-4.8.0 opencv && \
mv opencv_contrib-4.8.0 opencv_contrib && \
rm opencv.zip opencv_contrib.zip && \
cd opencv && \
mkdir build && cd build && \
cmake \
-D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_C_FLAGS="-O3 -march=native -ffast-math -flto -fno-fat-lto-objects -ffunction-sections -fdata-sections" \
-D CMAKE_CXX_FLAGS="-O3 -march=native -ffast-math -flto -fno-fat-lto-objects -ffunction-sections -fdata-sections -Wno-deprecated" \
-D CMAKE_EXE_LINKER_FLAGS="-flto -fno-fat-lto-objects -Wl,--gc-sections" \
-D CMAKE_SHARED_LINKER_FLAGS="-flto -fno-fat-lto-objects -Wl,--gc-sections" \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D ENABLE_FAST_MATH=ON \
-D CPU_BASELINE_DETECT=ON \
-D CPU_BASELINE=SSE3 \
-D CPU_DISPATCH=SSE4_1,SSE4_2,AVX,AVX2,AVX512_SKX,FP16 \
-D WITH_OPENMP=ON \
-D OPENCV_ENABLE_NONFREE=ON \
-D WITH_FFMPEG=ON \
-D FFMPEG_ROOT=/usr/local \
-D OPENCV_EXTRA_MODULES_PATH=/tmp/opencv_contrib/modules \
-D PYTHON_EXECUTABLE=/usr/local/bin/python3.7 \
-D PYTHON3_EXECUTABLE=/usr/local/bin/python3.7 \
-D PYTHON3_INCLUDE_DIR=/usr/local/include/python3.7m \
-D PYTHON3_LIBRARY=/usr/local/lib/libpython3.7m.so \
-D PYTHON3_PACKAGES_PATH=/usr/local/lib/python3.7/site-packages \
-D PYTHON3_NUMPY_INCLUDE_DIRS=/usr/local/lib/python3.7/site-packages/numpy/core/include \
-D BUILD_opencv_python3=ON \
-D INSTALL_PYTHON_EXAMPLES=OFF \
-D BUILD_TESTS=OFF \
-D BUILD_PERF_TESTS=OFF \
-D BUILD_EXAMPLES=OFF \
-D BUILD_DOCS=OFF \
-D BUILD_opencv_apps=OFF \
-D WITH_OPENCL=OFF \
-D WITH_CUDA=OFF \
-D WITH_IPP=OFF \
-D WITH_TBB=OFF \
-D WITH_V4L=OFF \
-D WITH_QT=OFF \
-D WITH_GTK=OFF \
-D BUILD_LIST=core,imgproc,imgcodecs,videoio,python3 \
.. && \
make && \
make install && \
ldconfig && \
rm -rf /tmp/*
# Set working directory and copy application code
WORKDIR /app
COPY requirements.txt .
RUN apt-get update && apt-get install -y --no-install-recommends ffmpeg
RUN pip install --no-cache-dir aeneas afaligner && \
pip install --no-cache-dir -r requirements.txt
COPY . .
# Make entrypoint executable
RUN chmod +x entrypoint.sh
ENTRYPOINT ["./entrypoint.sh"]
My trouble now, is I've been considering running parts of my program on my GPU, it's creating graphics for a video after all. I have no idea how to edit my Dockerfile to make the opencv build run with CUDA enabled, every combination I try leads to issues.
How can I tell which version of CUDA, opencv and ffmpeg are compatible with python 3.7?