[BUG] CRF setting ignored for 2-pass VP9 encoding #2008

Closed
opened 2026-02-05 04:43:50 +03:00 by OVERLORD · 1 comment
Owner

Originally created by @heikomat on GitHub (Jan 18, 2024).

Originally assigned to: @mertalev on GitHub.

The bug

According to the two-pass-encoding description, ffmpegs VP9-Encoding-Guide and my own testing, i should be able to use 2-pass encoding with the crf setting, if i set the codec to vp9 and the max bitrate to 0 (to disable it):
Screenshot 2024-01-18 at 10 31 59

When choosing these settings, the CRF-Parameter is not used. This can be observed in htop, but it also seems to be in line with what i found in the code for the VP9-Config:
68f52818ae/server/src/domain/media/media.util.ts (L357-L368)

According to this snippet, if it is eligible for 2-pass (which is most likely true with this config), then the return value contains no crf-setting.

This doesn't break encoding, because ffmpeg (according to my local testing) will print a warning and fall back to a default crf value of 31 (if i remember correctly)

The OS that Immich Server is running on

Ubuntu 22.04

Version of Immich Server

v1.92.1

Version of Immich Mobile App

v1.92.1 build.117

Platform with the issue

  • Server
  • Web
  • Mobile

Your docker-compose.yml content

version: "3.8"

services:
  server:
    image: ghcr.io/immich-app/immich-server:release
    command: ["start.sh", "immich"]
    volumes:
      - ${UPLOAD_LOCATION}:/usr/src/app/upload
      - /etc/localtime:/etc/localtime:ro
      # upload libraries
      - /quick-vault/main-storage/Bilder/smartphone-camera-roll:/usr/src/app/upload/library/<some-person>
      - /quick-vault/main-storage/Backups/<some-other-person>/smartphone/camera-roll:/usr/src/app/upload/library/<some-other-person>
      # external libraries
      - /quick-vault/main-storage/Bilder/<some-folder-with-location-name>:/mnt/media/<some-person>/old-pics-til-2018:ro
      - /quick-vault/main-storage/Bilder/seit_2017:/mnt/media/<some-person>/albums-since-2017:ro
      - /fat-vault/Media/Backups/<some-other-person>/<some-folder-with-persons-name>:/mnt/media/<some-other-person>/old-hdd:ro

    env_file:
      - .env
    depends_on:
      - redis
      - database
    restart: always
    networks:
      - default
      - traefik
    labels:
      - traefik.enable=true
      - traefik.http.routers.immich.rule=Host(`<my-immich-domain>`)
      - homepage.group=Media
      - homepage.name=immich
      - homepage.icon=immich.png
      - homepage.href=https://<my-immich-domain>
      - homepage.widget.type=immich
      - homepage.widget.url=https://<my-immich-domain>
      - homepage.widget.key=<my-immich-api-key>
      - homepage.widget.fields=["photos", "videos"]

  microservices:
    image: ghcr.io/immich-app/immich-server:release
    command: ["start.sh", "microservices"]
    volumes:
      - ${UPLOAD_LOCATION}:/usr/src/app/upload
      # upload libraries
      - /quick-vault/main-storage/Bilder/smartphone-camera-roll:/usr/src/app/upload/library/<some-person>
      - /quick-vault/main-storage/Backups/<some-other-person>/smartphone/camera-roll:/usr/src/app/upload/library/<some-other-person>
      # external libraries
      - /quick-vault/main-storage/Bilder/<some-folder-with-location-name>:/mnt/media/<some-person>/old-pics-til-2018:ro
      - /quick-vault/main-storage/Bilder/seit_2017:/mnt/media/<some-person>/albums-since-2017:ro
      - /fat-vault/Media/Backups/<some-person>/<some-folder-with-persons-name>:/mnt/media/<some-person>/old-hdd:ro
    env_file:
      - .env
    depends_on:
      - redis
      - database
    restart: always

  machine-learning:
    image: ghcr.io/immich-app/immich-machine-learning:release
    volumes:
      - ./immich-data/model-cache:/cache
    env_file:
      - .env
    restart: always

  redis:
    image: redis:6.2-alpine
    volumes:
      - ./immich-data/redis:/data
    restart: always

  database:
    image: tensorchord/pgvecto-rs:pg14-v0.1.11
    env_file:
      - .env
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_DB: ${DB_DATABASE_NAME}
    volumes:
      - ./immich-data/pgdata:/var/lib/postgresql/data
    restart: always

networks:
  traefik:
    external: true

Your .env content

DB_HOSTNAME=database
DB_USERNAME=<redacted>
DB_PASSWORD=<redacted>
DB_DATABASE_NAME=immich

REDIS_HOSTNAME=redis

UPLOAD_LOCATION=/docker/immich/immich-data

TYPESENSE_API_KEY=<redacted>

PUBLIC_LOGIN_PAGE_MESSAGE=

IMMICH_WEB_URL=http://web:3000
IMMICH_SERVER_URL=http://server:3001
IMMICH_MACHINE_LEARNING_URL=http://machine-learning:3003

IMMICH_API_URL_EXTERNAL=https://<redacted>, http://<local-ip-of-immich-host>:2283, http://proxy:8080

Reproduction steps

In the Video Transcoding settings:
1. Choose a crf value 
2. Set the video codec to vp9
3. Enable two-pass-encoding
4. In the Jobs-Menu start transcoding videos
5. Observe the CRF value being ignored, for example by looking at the ffmpeg command in htop

Additional information

No response

Originally created by @heikomat on GitHub (Jan 18, 2024). Originally assigned to: @mertalev on GitHub. ### The bug According to the [two-pass-encoding description](https://github.com/immich-app/immich/blob/68f52818ae640fcd02d3a69c6c584f663668d02d/web/src/lib/components/admin-page/settings/ffmpeg/ffmpeg-settings.svelte#L197), ffmpegs [VP9-Encoding-Guide](https://trac.ffmpeg.org/wiki/Encode/VP9#twopass) and my own testing, i should be able to use 2-pass encoding with the crf setting, if i set the codec to vp9 and the max bitrate to 0 (to disable it): ![Screenshot 2024-01-18 at 10 31 59](https://github.com/immich-app/immich/assets/20770029/00d80471-d8a1-44a9-b41e-23550808f993) When choosing these settings, the CRF-Parameter is not used. This can be observed in htop, but it also seems to be in line with what i found in the code for the VP9-Config: https://github.com/immich-app/immich/blob/68f52818ae640fcd02d3a69c6c584f663668d02d/server/src/domain/media/media.util.ts#L357-L368 According to this snippet, if it is eligible for 2-pass (which is most likely `true` with this config), then the return value contains no crf-setting. This doesn't break encoding, because ffmpeg (according to my local testing) will print a warning and fall back to a default crf value of 31 (if i remember correctly) ### The OS that Immich Server is running on Ubuntu 22.04 ### Version of Immich Server v1.92.1 ### Version of Immich Mobile App v1.92.1 build.117 ### Platform with the issue - [X] Server - [ ] Web - [ ] Mobile ### Your docker-compose.yml content ```YAML version: "3.8" services: server: image: ghcr.io/immich-app/immich-server:release command: ["start.sh", "immich"] volumes: - ${UPLOAD_LOCATION}:/usr/src/app/upload - /etc/localtime:/etc/localtime:ro # upload libraries - /quick-vault/main-storage/Bilder/smartphone-camera-roll:/usr/src/app/upload/library/<some-person> - /quick-vault/main-storage/Backups/<some-other-person>/smartphone/camera-roll:/usr/src/app/upload/library/<some-other-person> # external libraries - /quick-vault/main-storage/Bilder/<some-folder-with-location-name>:/mnt/media/<some-person>/old-pics-til-2018:ro - /quick-vault/main-storage/Bilder/seit_2017:/mnt/media/<some-person>/albums-since-2017:ro - /fat-vault/Media/Backups/<some-other-person>/<some-folder-with-persons-name>:/mnt/media/<some-other-person>/old-hdd:ro env_file: - .env depends_on: - redis - database restart: always networks: - default - traefik labels: - traefik.enable=true - traefik.http.routers.immich.rule=Host(`<my-immich-domain>`) - homepage.group=Media - homepage.name=immich - homepage.icon=immich.png - homepage.href=https://<my-immich-domain> - homepage.widget.type=immich - homepage.widget.url=https://<my-immich-domain> - homepage.widget.key=<my-immich-api-key> - homepage.widget.fields=["photos", "videos"] microservices: image: ghcr.io/immich-app/immich-server:release command: ["start.sh", "microservices"] volumes: - ${UPLOAD_LOCATION}:/usr/src/app/upload # upload libraries - /quick-vault/main-storage/Bilder/smartphone-camera-roll:/usr/src/app/upload/library/<some-person> - /quick-vault/main-storage/Backups/<some-other-person>/smartphone/camera-roll:/usr/src/app/upload/library/<some-other-person> # external libraries - /quick-vault/main-storage/Bilder/<some-folder-with-location-name>:/mnt/media/<some-person>/old-pics-til-2018:ro - /quick-vault/main-storage/Bilder/seit_2017:/mnt/media/<some-person>/albums-since-2017:ro - /fat-vault/Media/Backups/<some-person>/<some-folder-with-persons-name>:/mnt/media/<some-person>/old-hdd:ro env_file: - .env depends_on: - redis - database restart: always machine-learning: image: ghcr.io/immich-app/immich-machine-learning:release volumes: - ./immich-data/model-cache:/cache env_file: - .env restart: always redis: image: redis:6.2-alpine volumes: - ./immich-data/redis:/data restart: always database: image: tensorchord/pgvecto-rs:pg14-v0.1.11 env_file: - .env environment: POSTGRES_PASSWORD: ${DB_PASSWORD} POSTGRES_USER: ${DB_USERNAME} POSTGRES_DB: ${DB_DATABASE_NAME} volumes: - ./immich-data/pgdata:/var/lib/postgresql/data restart: always networks: traefik: external: true ``` ### Your .env content ```Shell DB_HOSTNAME=database DB_USERNAME=<redacted> DB_PASSWORD=<redacted> DB_DATABASE_NAME=immich REDIS_HOSTNAME=redis UPLOAD_LOCATION=/docker/immich/immich-data TYPESENSE_API_KEY=<redacted> PUBLIC_LOGIN_PAGE_MESSAGE= IMMICH_WEB_URL=http://web:3000 IMMICH_SERVER_URL=http://server:3001 IMMICH_MACHINE_LEARNING_URL=http://machine-learning:3003 IMMICH_API_URL_EXTERNAL=https://<redacted>, http://<local-ip-of-immich-host>:2283, http://proxy:8080 ``` ### Reproduction steps ```bash In the Video Transcoding settings: 1. Choose a crf value 2. Set the video codec to vp9 3. Enable two-pass-encoding 4. In the Jobs-Menu start transcoding videos 5. Observe the CRF value being ignored, for example by looking at the ffmpeg command in htop ``` ### Additional information _No response_
Author
Owner

@mertalev commented on GitHub (Jan 18, 2024):

Thanks for catching this. The check here should be to check if it's bitrate-constrained and in two-pass mode. For VP9, eligibleForTwoPassEncoding only checks for the latter, so two-pass mode won't ever use CRF.

@mertalev commented on GitHub (Jan 18, 2024): Thanks for catching this. The check here should be to check if it's bitrate-constrained and in two-pass mode. For VP9, `eligibleForTwoPassEncoding` only checks for the latter, so two-pass mode won't ever use CRF.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: immich-app/immich#2008