# mp4decrypt (Bento4) has no Linux package and no published binary release, so it's built from # source here and just the one binary is copied into the real image below. This is what # DRM-protected downloads (Max, Discovery+) decrypt with once given a key. FROM python:3.12-slim AS mp4decrypt-builder RUN apt-get update && apt-get install -y --no-install-recommends git cmake build-essential ca-certificates \ && rm -rf /var/lib/apt/lists/* RUN git clone --depth 1 https://github.com/axiomatic-systems/Bento4.git /tmp/Bento4 \ && cmake -S /tmp/Bento4 -B /tmp/Bento4/build -DCMAKE_BUILD_TYPE=Release \ && cmake --build /tmp/Bento4/build --target mp4decrypt -j"$(nproc)" FROM python:3.12-slim RUN apt-get update && apt-get install -y --no-install-recommends \ ffmpeg firefox-esr xvfb xauth ca-certificates curl \ && rm -rf /var/lib/apt/lists/* COPY --from=mp4decrypt-builder /tmp/Bento4/build/mp4decrypt /usr/local/bin/mp4decrypt RUN pip install --no-cache-dir flask selenium requests yt-dlp # Whisper (speech-to-text) for videos that have no built-in captions. The CPU build of PyTorch # avoids a multi-gigabyte GPU download this container can't use. Models download on first use # into /data/.cache/whisper, which is kept between rebuilds. RUN pip install --no-cache-dir torch --index-url https://download.pytorch.org/whl/cpu \ && pip install --no-cache-dir openai-whisper RUN mkdir -p /data && chown 1000:1000 /data WORKDIR /app COPY app.py save_cookies.py ./ COPY templates ./templates ENV HOME=/data ENV AETV_MEDIA_ROOT=/mnt/storage ENV AETV_LIST_DIR=/lists EXPOSE 5000 CMD ["sh", "-c", "mkdir -p $HOME/.mozilla/firefox && \ (ls -d $HOME/.mozilla/firefox/*.default-release >/dev/null 2>&1 || firefox-esr --headless -CreateProfile default-release) && \ rm -f /tmp/.X99-lock && (Xvfb :99 -screen 0 1280x1024x24 -nolisten tcp &) && sleep 2 && \ export DISPLAY=:99 && exec flask --app app run --host 0.0.0.0 --port 5000"]