diff --git a/Dockerfile b/Dockerfile index f60e9e4c..1f7f505a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # multi stage to build tube archivist -# first stage to build python wheel, copy into final image +# build python wheel, download and extract ffmpeg, copy into final image # First stage to build python wheel @@ -13,6 +13,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY ./tubearchivist/requirements.txt /requirements.txt RUN pip install --user -r requirements.txt +# build ffmpeg +FROM python:3.11.3-slim-bullseye as ffmpeg-builder +COPY docker_assets/ffmpeg_download.py ffmpeg_download.py +RUN python ffmpeg_download.py $TARGETPLATFORM + # build final image FROM python:3.11.3-slim-bullseye as tubearchivist @@ -25,30 +30,15 @@ ENV PYTHONUNBUFFERED 1 COPY --from=builder /root/.local /root/.local ENV PATH=/root/.local/bin:$PATH +# copy ffmpeg +COPY --from=ffmpeg-builder ./ffmpeg/ffmpeg /usr/bin/ffmpeg +COPY --from=ffmpeg-builder ./ffprobe/ffprobe /usr/bin/ffprobe + # install distro packages needed RUN apt-get clean && apt-get -y update && apt-get -y install --no-install-recommends \ nginx \ atomicparsley \ - curl \ - xz-utils && rm -rf /var/lib/apt/lists/* - -# install patched ffmpeg build, default to linux64 -RUN if [ "$TARGETPLATFORM" = "linux/arm64" ] ; then \ - curl -s https://api.github.com/repos/yt-dlp/FFmpeg-Builds/releases/latest \ - | grep browser_download_url \ - | grep ".*master.*linuxarm64.*tar.xz" \ - | cut -d '"' -f 4 \ - | xargs curl -L --output ffmpeg.tar.xz ; \ - else \ - curl -s https://api.github.com/repos/yt-dlp/FFmpeg-Builds/releases/latest \ - | grep browser_download_url \ - | grep ".*master.*linux64.*tar.xz" \ - | cut -d '"' -f 4 \ - | xargs curl -L --output ffmpeg.tar.xz ; \ - fi && \ - tar -xf ffmpeg.tar.xz --strip-components=2 --no-anchored -C /usr/bin/ "ffmpeg" && \ - tar -xf ffmpeg.tar.xz --strip-components=2 --no-anchored -C /usr/bin/ "ffprobe" && \ - rm ffmpeg.tar.xz + curl && rm -rf /var/lib/apt/lists/* # install debug tools for testing environment RUN if [ "$INSTALL_DEBUG" ] ; then \ diff --git a/docker_assets/ffmpeg_download.py b/docker_assets/ffmpeg_download.py new file mode 100644 index 00000000..9ab7f82c --- /dev/null +++ b/docker_assets/ffmpeg_download.py @@ -0,0 +1,71 @@ +""" +ffmpeg link builder +copied as into build step in Dockerfile +""" + +import json +import os +import sys +import tarfile +import urllib.request +from enum import Enum + +API_URL = "https://api.github.com/repos/yt-dlp/FFmpeg-Builds/releases/latest" +BINARIES = ["ffmpeg", "ffprobe"] + + +class PlatformFilter(Enum): + """options""" + + ARM64 = "linuxarm64" + AMD64 = "linux64" + + +def get_assets(): + """get all available assets from latest build""" + with urllib.request.urlopen(API_URL) as f: + all_links = json.loads(f.read().decode("utf-8")) + + return all_links + + +def pick_url(all_links, platform): + """pick url for platform""" + filter_by = PlatformFilter[platform.split("/")[1].upper()].value + options = [i for i in all_links["assets"] if filter_by in i["name"]] + if not options: + raise ValueError(f"no valid asset found for filter {filter_by}") + + url_pick = options[0]["browser_download_url"] + + return url_pick + + +def download_extract(url): + """download and extract binaries""" + print("download file") + filename, _ = urllib.request.urlretrieve(url) + print("extract file") + with tarfile.open(filename, "r:xz") as tar: + for member in tar.getmembers(): + member.name = os.path.basename(member.name) + if member.name in BINARIES: + print(f"extract {member.name}") + tar.extract(member, member.name) + + +def main(): + """entry point""" + args = sys.argv + if len(args) == 1: + platform = "linux/amd64" + else: + platform = args[1] + + all_links = get_assets() + url = pick_url(all_links, platform) + download_extract(url) + + +if __name__ == "__main__": + main()