Skip to content

Commit 7710064

Browse files
Pre-build PyAV wheel in base image to speed up release builds (#2682)
1 parent 2179fd7 commit 7710064

3 files changed

Lines changed: 40 additions & 21 deletions

File tree

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ on:
3434
env:
3535
PYTHON_VERSION: "3.12"
3636
BASE_IMAGE_VERSION_STABLE: "1.3.1"
37-
BASE_IMAGE_VERSION_BETA: "1.4.8"
38-
BASE_IMAGE_VERSION_NIGHTLY: "1.4.8"
37+
BASE_IMAGE_VERSION_BETA: "1.4.9"
38+
BASE_IMAGE_VERSION_NIGHTLY: "1.4.9"
3939

4040
jobs:
4141
preflight-checks:

Dockerfile

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,6 @@ COPY requirements_all.txt .
1111
# ensure UV is installed
1212
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
1313

14-
# Install build tools for PyAV compilation (for aioresonate)
15-
RUN apt-get update && apt-get install -y --no-install-recommends \
16-
gcc \
17-
g++ \
18-
python3-dev \
19-
&& rm -rf /var/lib/apt/lists/*
20-
2114
# create venv which will be copied to the final image
2215
ENV VIRTUAL_ENV=/app/venv
2316
RUN uv venv $VIRTUAL_ENV
@@ -28,10 +21,16 @@ RUN uv venv $VIRTUAL_ENV
2821
RUN uv pip install \
2922
-r requirements_all.txt
3023

31-
# Reinstall PyAV from source to use system FFmpeg instead of bundled FFmpeg
32-
# Use the version already resolved by requirements_all.txt to ensure compatibility
33-
RUN uv pip install --no-binary av --force-reinstall --no-deps \
34-
"av==$($VIRTUAL_ENV/bin/python -c 'import importlib.metadata; print(importlib.metadata.version("av"))')"
24+
# Install PyAV from pre-built wheel (built against system FFmpeg in base image)
25+
# First verify the wheel version matches what pip resolved to avoid version mismatch
26+
RUN REQUIRED_VERSION=$($VIRTUAL_ENV/bin/python -c "import importlib.metadata; print(importlib.metadata.version('av'))") && \
27+
WHEEL_VERSION=$(ls /usr/local/share/pyav-wheels/av*.whl | grep -oP 'av-\K[0-9.]+') && \
28+
if [ "$REQUIRED_VERSION" != "$WHEEL_VERSION" ]; then \
29+
echo "ERROR: PyAV version mismatch! Requirements need $REQUIRED_VERSION but base image has $WHEEL_VERSION" && \
30+
echo "Please rebuild the base image with the correct PyAV version." && \
31+
exit 1; \
32+
fi && \
33+
uv pip install --force-reinstall --no-deps /usr/local/share/pyav-wheels/av*.whl
3534

3635
# Install Music Assistant from prebuilt wheel
3736
ARG MASS_VERSION

Dockerfile.base

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,32 @@ RUN set -x \
101101

102102
##################################################################################################
103103

104+
# PyAV wheel builder - builds PyAV against the custom FFmpeg
105+
FROM python:3.13-slim-bookworm AS pyav-builder
106+
107+
RUN apt-get update && apt-get install -y --no-install-recommends \
108+
gcc g++ python3-dev pkg-config && rm -rf /var/lib/apt/lists/*
109+
110+
COPY --from=ffmpeg-builder /usr/local/lib/libav*.so* /usr/local/lib/
111+
COPY --from=ffmpeg-builder /usr/local/lib/libsw*.so* /usr/local/lib/
112+
COPY --from=ffmpeg-builder /usr/local/lib/libpostproc.so* /usr/local/lib/
113+
COPY --from=ffmpeg-builder /usr/local/include/ /usr/local/include/
114+
COPY --from=ffmpeg-builder /usr/local/lib/pkgconfig/ /usr/local/lib/pkgconfig/
115+
116+
RUN ldconfig
117+
ENV PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
118+
119+
# Resolve PyAV version from aioresonate's dependencies and build wheel
120+
RUN PYAV_VERSION=$(pip install --dry-run aioresonate 2>&1 | grep -oP 'av-\K[0-9.]+' | head -1) && \
121+
if [ -z "$PYAV_VERSION" ]; then \
122+
echo "ERROR: Failed to detect PyAV version from aioresonate dependencies" >&2; \
123+
exit 1; \
124+
fi && \
125+
echo "Building PyAV version: ${PYAV_VERSION}" && \
126+
pip wheel --no-binary av av==${PYAV_VERSION} -w /wheels/
127+
128+
##################################################################################################
129+
104130
FROM python:3.13-slim-bookworm
105131

106132
# Enable non-free and contrib repositories for codec libraries
@@ -169,8 +195,6 @@ RUN set -x \
169195
# AirPlay receiver dependencies (shairport-sync)
170196
libconfig9 \
171197
libpopt0 \
172-
# pkg-config needed for PyAV (for aioresonate) to find system FFmpeg
173-
pkg-config \
174198
&& apt-get clean \
175199
&& rm -rf /var/lib/apt/lists/*
176200

@@ -195,12 +219,8 @@ COPY --from=ffmpeg-builder /usr/local/lib/libav*.so* /usr/local/lib/
195219
COPY --from=ffmpeg-builder /usr/local/lib/libsw*.so* /usr/local/lib/
196220
COPY --from=ffmpeg-builder /usr/local/lib/libpostproc.so* /usr/local/lib/
197221

198-
# Copy FFmpeg headers and pkg-config files needed for PyAV compilation (adds around 2 MB)
199-
COPY --from=ffmpeg-builder /usr/local/include/ /usr/local/include/
200-
COPY --from=ffmpeg-builder /usr/local/lib/pkgconfig/ /usr/local/lib/pkgconfig/
201-
202-
# Set PKG_CONFIG_PATH so pkg-config can find FFmpeg
203-
ENV PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
222+
# Copy pre-built PyAV wheel for use by downstream images
223+
COPY --from=pyav-builder /wheels/ /usr/local/share/pyav-wheels/
204224

205225
# Update shared library cache and verify FFmpeg
206226
RUN ldconfig && ffmpeg -version && ffprobe -version

0 commit comments

Comments
 (0)