diff --git a/docker/production/.gitlab-ci.yml b/docker/production/.gitlab-ci.yml
index 2a8c05e78493aaeddf05ed419a087bdb85cf55e6..d99889d0efe84513b664c43d729c11fb906e2419 100644
--- a/docker/production/.gitlab-ci.yml
+++ b/docker/production/.gitlab-ci.yml
@@ -12,6 +12,7 @@ docker-build-rolling:
     - cp ${DOCKER_HUB_CONFIG} /kaniko/.docker/config.json
     - /kaniko/executor --context . --dockerfile docker/production/web-server/Dockerfile --destination ${DOCKER_IMAGE_WEB_SERVER}:${TAG}
     - /kaniko/executor --context . --dockerfile docker/production/app/Dockerfile --destination ${DOCKER_IMAGE_APP}:${TAG}
+    - /kaniko/executor --context . --dockerfile docker/production/video-clipper/Dockerfile --destination ${DOCKER_IMAGE_VIDEO_CLIPPER}:${TAG}
   needs:
     - pipeline: $PARENT_PIPELINE_ID
       job: bundle
@@ -29,6 +30,7 @@ docker-build-main-release:
     - export CP_VERSION=$(cat CP_VERSION.env)
     - /kaniko/executor --context . --dockerfile docker/production/web-server/Dockerfile --destination ${DOCKER_IMAGE_WEB_SERVER}:${CP_VERSION} --destination ${DOCKER_IMAGE_WEB_SERVER}:latest
     - /kaniko/executor --context . --dockerfile docker/production/app/Dockerfile --destination ${DOCKER_IMAGE_APP}:${CP_VERSION} --destination ${DOCKER_IMAGE_APP}:latest
+    - /kaniko/executor --context . --dockerfile docker/production/video-clipper/Dockerfile --destination ${DOCKER_IMAGE_VIDEO_CLIPPER}:${CP_VERSION} --destination ${DOCKER_IMAGE_VIDEO_CLIPPER}:latest
   needs:
     - pipeline: $PARENT_PIPELINE_ID
       job: release
@@ -48,6 +50,7 @@ docker-build-alpha-beta-release:
     - export CP_VERSION=$(cat CP_VERSION.env)
     - /kaniko/executor --context . --dockerfile docker/production/web-server/Dockerfile --destination ${DOCKER_IMAGE_WEB_SERVER}:${CP_VERSION} --destination ${DOCKER_IMAGE_WEB_SERVER}:${TAG}
     - /kaniko/executor --context . --dockerfile docker/production/app/Dockerfile --destination ${DOCKER_IMAGE_APP}:${CP_VERSION} --destination ${DOCKER_IMAGE_APP}:${TAG}
+    - /kaniko/executor --context . --dockerfile docker/production/video-clipper/Dockerfile --destination ${DOCKER_IMAGE_VIDEO_CLIPPER}:${CP_VERSION} --destination ${DOCKER_IMAGE_VIDEO_CLIPPER}:${TAG}
   needs:
     - pipeline: $PARENT_PIPELINE_ID
       job: release
diff --git a/docker/production/app/Dockerfile b/docker/production/app/Dockerfile
index bf281d0519c3cc5c27cd8336646e410844d763fe..2fc667d8abdf8c67bcc920782a7c34d027f49a29 100644
--- a/docker/production/app/Dockerfile
+++ b/docker/production/app/Dockerfile
@@ -1,10 +1,3 @@
-FROM docker.io/alpine:3.16 AS ffmpeg-downloader
-
-RUN apk add --no-cache curl && \
-    curl https://johnvansickle.com/ffmpeg/releases/ffmpeg-5.1.1-amd64-static.tar.xz -o ffmpeg.tar.xz && \
-    mkdir ffmpeg && \
-    tar -xJf ffmpeg.tar.xz -C ffmpeg --strip-components 1
-
 FROM docker.io/php:8.1-fpm-alpine3.16
 
 COPY docker/production/app/entrypoint.sh /entrypoint.sh
@@ -12,9 +5,9 @@ COPY docker/production/app/entrypoint.sh /entrypoint.sh
 COPY docker/production/app/uploads.ini /usr/local/etc/php/conf.d/uploads.ini
 
 RUN echo "* * * * * /usr/local/bin/php /opt/castopod/public/index.php scheduled-activities" > /crontab.txt && \
-    echo "* * * * 10 /usr/local/bin/php /opt/castopod/public/index.php scheduled-video-clips" >> /crontab.txt && \
     echo "* * * * * /usr/local/bin/php /opt/castopod/public/index.php scheduled-websub-publish" >> /crontab.txt
 
+# TODO: remove freetype (package and gd support) and ffmpeg
 RUN apk add --no-cache libpng icu-libs freetype libwebp libjpeg-turbo libxpm ffmpeg && \
     apk add --no-cache --virtual .php-ext-build-dep freetype-dev libpng-dev libjpeg-turbo-dev libwebp-dev zlib-dev libxpm-dev icu-dev && \
     docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp --with-xpm && \
@@ -23,7 +16,6 @@ RUN apk add --no-cache libpng icu-libs freetype libwebp libjpeg-turbo libxpm ffm
     apk del .php-ext-build-dep
 
 COPY castopod /opt/castopod
-COPY --from=ffmpeg-downloader /ffmpeg/ffmpeg /ffmpeg/ffprobe /ffmpeg/qt-faststart /usr/local/bin/
 
 RUN chmod 544 /entrypoint.sh && \
     chmod 444 /crontab.txt && \
diff --git a/docker/production/video-clipper/Dockerfile b/docker/production/video-clipper/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..d01ee0764c30f0a51b9334fb070f9786f24c15b0
--- /dev/null
+++ b/docker/production/video-clipper/Dockerfile
@@ -0,0 +1,32 @@
+FROM docker.io/php:8.1-bullseye
+
+ENV SUPERCRONIC_VERSION=v0.2.1
+
+COPY docker/production/video-clipper/entrypoint.sh /entrypoint.sh
+
+RUN echo "*/2 * * * * /usr/local/bin/php /opt/castopod/public/index.php scheduled-video-clips" >> /crontab.txt
+
+RUN apt update && \
+    apt install -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev libwebp-dev libxpm-dev libicu-dev && \
+    docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp --with-xpm && \
+    docker-php-ext-install mysqli gd intl && \
+    docker-php-ext-enable mysqli gd intl
+
+RUN apt update && \
+    apt install -y ffmpeg curl && \
+    curl -OL https://github.com/aptible/supercronic/releases/download/$SUPERCRONIC_VERSION/supercronic-linux-amd64 && \
+    mv supercronic-linux-amd64 /usr/local/bin/supercronic && \
+    chmod +x /usr/local/bin/supercronic
+
+COPY castopod /opt/castopod
+
+RUN chmod 544 /entrypoint.sh && \
+    chmod 444 /crontab.txt
+
+WORKDIR /opt/castopod
+
+VOLUME /opt/castopod/public/media
+
+ENTRYPOINT [ "sh", "-c" ]
+
+CMD [ "/entrypoint.sh" ]
diff --git a/docker/production/video-clipper/entrypoint.sh b/docker/production/video-clipper/entrypoint.sh
new file mode 100644
index 0000000000000000000000000000000000000000..638e3dfcbe29fc0becc705e4cfa59e32a25d8920
--- /dev/null
+++ b/docker/production/video-clipper/entrypoint.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+
+if [ -z "${CP_DATABASE_HOSTNAME}" ]
+then
+	echo "CP_DATABASE_HOSTNAME is empty, using default"
+	CP_DATABASE_HOSTNAME="mariadb"
+fi
+
+if [ -z "${CP_DATABASE_PREFIX}" ]
+then
+	echo "CP_DATABASE_PREFIX is empty, using default"
+	CP_DATABASE_PREFIX="cp_"
+fi
+
+if [ -z "${CP_DATABASE_NAME}" ]
+then
+	if [ -z "${MYSQL_DATABASE}" ]
+	then
+		echo "When CP_DATABASE_NAME is empty, MYSQL_DATABASE must be set"
+		exit 1
+	fi
+
+	echo "CP_DATABASE_NAME is empty, using mysql variable"
+	CP_DATABASE_NAME="${MYSQL_DATABASE}"
+fi
+
+if [ -z "${CP_DATABASE_USERNAME}" ]
+then
+	if [ -z "${MYSQL_USER}" ]
+	then
+		echo "When CP_DATABASE_USERNAME is empty, MYSQL_USER must be set"
+		exit 1
+	fi
+
+	echo "CP_DATABASE_USERNAME is empty, using mysql variable"
+	CP_DATABASE_USERNAME="${MYSQL_USER}"
+fi
+
+if [ -z "${CP_DATABASE_PASSWORD}" ]
+then
+	if [ -z "${MYSQL_PASSWORD}" ]
+	then
+		echo "When CP_DATABASE_PASSWORD is empty, MYSQL_PASSWORD must be set"
+		exit 1
+	fi
+
+	echo "CP_DATABASE_PASSWORD is empty, using mysql variable"
+	CP_DATABASE_PASSWORD="${MYSQL_PASSWORD}"
+fi
+
+cat << EOF >> /opt/castopod/.env
+database.default.hostname="${CP_DATABASE_HOSTNAME}"
+database.default.database="${CP_DATABASE_NAME}"
+database.default.username="${CP_DATABASE_USERNAME}"
+database.default.password="${CP_DATABASE_PASSWORD}"
+database.default.DBPrefix="${CP_DATABASE_PREFIX}"
+EOF
+
+echo "Using config:"
+cat /opt/castopod/.env
+
+supercronic /crontab.txt
diff --git a/docs/src/getting-started/docker.md b/docs/src/getting-started/docker.md
index e75dd1c9074ab72e4061ad22643d4bacd718144b..b2ef420ff87a8821cf944791b31f5915d91b8baa 100644
--- a/docs/src/getting-started/docker.md
+++ b/docs/src/getting-started/docker.md
@@ -5,13 +5,15 @@ sidebarDepth: 3
 
 # Official Docker images
 
-Castopod pushes 2 Docker images to the Docker Hub during its automated build
+Castopod pushes 3 Docker images to the Docker Hub during its automated build
 process:
 
 - [**`castopod/app`**](https://hub.docker.com/r/castopod/app): the app bundle
   with all of Castopod dependencies
 - [**`castopod/web-server`**](https://hub.docker.com/r/castopod/web-server): an
   Nginx configuration for Castopod
+- [**`castopod/video-clipper`**](https://hub.docker.com/r/castopod/video-clipper):
+  an optional image building videoclips thanks to ffmpeg
 
 Additionally, Castopod requires a MySQL-compatible database. A Redis database
 can be added as a cache handler.
@@ -85,6 +87,21 @@ can be added as a cache handler.
         networks:
           - castopod-app
 
+      # this container is optional
+      # add this if you want to use the videoclips feature
+      ffmpeg:
+        image: castopod/video-clipper:latest
+        container_name: "castopod-video-clipper"
+        volumes:
+          - castopod-media:/opt/castopod/public/media
+        environment:
+          MYSQL_DATABASE: castopod
+          MYSQL_USER: castopod
+          MYSQL_PASSWORD: changeme
+        networks:
+          - castopod-db
+        restart: unless-stopped
+
     volumes:
       castopod-media:
       castopod-db:
@@ -117,6 +134,16 @@ can be added as a cache handler.
 
 ## Environment Variables
 
+- **castopod/video-clipper**
+
+  | Variable name              | Type (`default`) | Default          |
+  | -------------------------- | ---------------- | ---------------- |
+  | **`CP_DATABASE_HOSTNAME`** | ?string          | `"mariadb"`      |
+  | **`CP_DATABASE_NAME`**     | ?string          | `MYSQL_DATABASE` |
+  | **`CP_DATABASE_USERNAME`** | ?string          | `MYSQL_USER`     |
+  | **`CP_DATABASE_PASSWORD`** | ?string          | `MYSQL_PASSWORD` |
+  | **`CP_DATABASE_PREFIX`**   | ?string          | `"cp_"`          |
+
 - **castopod/app**
 
   | Variable name                | Type (`default`)        | Default          |