Immich Thumbnail Jellyfin MJPEG bug #7663

Open
opened 2026-02-20 05:05:39 -05:00 by deekerman · 8 comments
Owner

Originally created by @jd445 on GitHub (Dec 24, 2025).

I have searched the existing issues, both open and closed, to make sure this is not a duplicate report.

  • Yes

The bug

Immich fails to generate thumbnails for some DJI MP4 videos (e.g., DJI OsmoAction6) that contain an extra MJPEG “attached picture / cover art” video stream (attached pic). During thumbnail generation (AssetGenerateThumbnails), Immich/ffmpeg appears to pick the MJPEG attached-pic stream instead of the real video stream (HEVC), then applies the hevc_metadata bitstream filter to it, which fails with:

Codec 'mjpeg' is not supported by the bitstream filter 'hevc_metadata'. Supported codecs are: hevc

ffmpeg exits with code 234

Immich job handler fails: Unable to run job handler (AssetGenerateThumbnails)

This blocks thumbnail generation for affected assets unless I manually remux each file to remove the attached picture stream.

The OS that Immich Server is running on

Ubuntu 22.04

Version of Immich Server

2.2.1

Version of Immich Mobile App

2.2.1

Platform with the issue

  • Server
  • Web
  • Mobile

Device make and model

No response

Your docker-compose.yml content

name: immich

services:
  immich-server:
    container_name: immich_server
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    extends:
      file: hwaccel.transcoding.yml
      service: quicksync # Intel Quick Sync (QSV)

    # extends:
    #   file: hwaccel.transcoding.yml
    #   service: nvenc # nvenc
    volumes:
      - ${UPLOAD_LOCATION}:/usr/src/app/upload
      - /etc/localtime:/etc/localtime:ro
    env_file:
      - .env
    ports:
      - '2283:2283'
    depends_on:
      - redis
      - database
    restart: always
    healthcheck:
      disable: false

  immich-machine-learning:
    container_name: immich_machine_learning
    image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
    volumes:
      - model-cache:/cache
    env_file:
      - .env
    restart: always
    healthcheck:
      disable: false
    deploy:
      resources:
        limits:
          cpus: '4'  # 分配4核CPU
          memory: 1G  # 分配2GB内存(避免CPU加载模型时内存不足)
  # immich-machine-learning:
  #   container_name: immich_machine_learning
  #   image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}-cuda
  #   extends:
  #     file: hwaccel.ml.yml
  #     service: cuda # cuda
  #   volumes:
  #     - model-cache:/cache
  #   env_file:
  #     - .env
  #   restart: always
  #   healthcheck:
  #     disable: false

  redis:
    container_name: immich_redis
    image: docker.io/redis:6.2-alpine@sha256:148bb5411c184abd288d9aaed139c98123eeb8824c5d3fce03cf721db58066d8
    healthcheck:
      test: redis-cli ping || exit 1
    restart: always

  database:
    container_name: immich_postgres
    image: docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:739cdd626151ff1f796dc95a6591b55a714f341c737e27f045019ceabf8e8c52
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_DB: ${DB_DATABASE_NAME}
      POSTGRES_INITDB_ARGS: '--data-checksums'
    volumes:
      - ${DB_DATA_LOCATION}:/var/lib/postgresql/data
    healthcheck:
      test: >-
        pg_isready --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" || exit 1;
        Chksum="$$(psql --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" --tuples-only --no-align
        --command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')";
        echo "checksum failure count is $$Chksum";
        [ "$$Chksum" = '0' ] || exit 1
      interval: 5m
      start_interval: 30s
      start_period: 5m
    command: >-
      postgres
      -c shared_preload_libraries=vectors.so
      -c 'search_path="$$user", public, vectors'
      -c logging_collector=on
      -c max_wal_size=2GB
      -c shared_buffers=512MB
      -c wal_compression=on
    restart: always

volumes:
  model-cache:

Your .env content

# You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables

# The location where your uploaded files are stored
UPLOAD_LOCATION=/media/ssd1/Junjie/immich
# The location where your database files are stored
DB_DATA_LOCATION=./postgres

# To set a timezone, uncomment the next line and change Etc/UTC to a TZ identifier from this list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
# TZ=Etc/UTC

# The Immich version to use. You can pin this to a specific version like "v1.71.0"
IMMICH_VERSION=release

# Connection secret for postgres. You should change it to a random password
# Please use only the characters `A-Za-z0-9`, without special characters or spaces
DB_PASSWORD=87894412

# The values below this line do not need to be changed
###################################################################################
DB_USERNAME=postgres

HF_ENDPOINT=https://hf-mirror.com
# sudo nano /etc/systemd/system/docker.service.d/proxy.conf

Reproduction steps

Upload a DJI MP4 (example: DJI OsmoAction6) that contains:

Main video stream: HEVC (Main 10)

Audio: AAC

Extra video stream: MJPEG marked as attached picture (attached pic)

Immich runs thumbnail generation job.

Thumbnail generation fails with ffmpeg error and job handler error.

Relevant log output

Immich server logs:

[mov,mp4,m4a,3gp,3g2,mj2 @ 0x564d3edd1980] stream 0, timescale not set
[hevc_metadata @ 0x564d3edf2ac0] Codec 'mjpeg' (7) is not supported by the bitstream filter 'hevc_metadata'. Supported codecs are: hevc (173)
[vist#0:5/mjpeg @ 0x564d3ee2b140] Error initializing bitstream filters: Invalid argument
Error opening input file /usr/src/app/upload/upload/.../9f23abfd-5027-4aa6-bc33-315eab47ae18.mp4.
Error opening input files: Invalid argument

ERROR [Microservices:{"id":"..."}] Unable to run job handler (AssetGenerateThumbnails): Error: ffmpeg exited with code 234
    at ChildProcess.<anonymous> (.../node_modules/fluent-ffmpeg/lib/processor.js:180:22)


ffprobe output of the problematic MP4 (note stream 0:5 is MJPEG attached pic):

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '.../9f23abfd-5027-4aa6-bc33-315eab47ae18.mp4':
  Metadata:
    encoder         : DJI OsmoAction6
  Duration: 00:00:15.98, start: 0.000000, bitrate: 51870 kb/s
  Stream #0:0(und): Video: hevc (Main 10) (hvc1), 1920x1080, 50 fps (default)
  Stream #0:1(und): Audio: aac (LC), 48000 Hz, stereo (default)
  Stream #0:2(und): Data: none (djmd)
  Stream #0:3(und): Data: none (dbgi)
  Stream #0:4(und): Data: none (tmcd)
  Stream #0:5: Video: mjpeg (Baseline), 1280x720, (attached pic)

Workaround

Manually remux affected files to remove the attached picture stream (keep only real video + audio), then rerun thumbnail jobs. Example:

ffmpeg -i input.mp4 -map 0:v:0 -map 0:a? -c copy -movflags +faststart output.mp4


After removing the MJPEG attached pic stream, Immich can generate thumbnails normally.

Additional information

Suggested fix (what I think is going wrong)

Immich’s thumbnail pipeline (or stream selection) seems to:

accidentally select the MJPEG attached_pic stream as the input video stream, or

apply HEVC-specific bitstream filters (e.g., hevc_metadata) without verifying the selected stream codec is HEVC.

Suggested fixes:

Exclude attached picture streams from selection when generating thumbnails / extracting frames.

Use FFmpeg stream selection that ignores attached_pic (cover art) streams.

If hevc_metadata is used, only apply it when the selected stream codec is actually HEVC.

Originally created by @jd445 on GitHub (Dec 24, 2025). ### I have searched the existing issues, both open and closed, to make sure this is not a duplicate report. - [x] Yes ### The bug Immich fails to generate thumbnails for some DJI MP4 videos (e.g., DJI OsmoAction6) that contain an extra MJPEG “attached picture / cover art” video stream (attached pic). During thumbnail generation (AssetGenerateThumbnails), Immich/ffmpeg appears to pick the MJPEG attached-pic stream instead of the real video stream (HEVC), then applies the hevc_metadata bitstream filter to it, which fails with: Codec 'mjpeg' is not supported by the bitstream filter 'hevc_metadata'. Supported codecs are: hevc ffmpeg exits with code 234 Immich job handler fails: Unable to run job handler (AssetGenerateThumbnails) This blocks thumbnail generation for affected assets unless I manually remux each file to remove the attached picture stream. ### The OS that Immich Server is running on Ubuntu 22.04 ### Version of Immich Server 2.2.1 ### Version of Immich Mobile App 2.2.1 ### Platform with the issue - [x] Server - [x] Web - [x] Mobile ### Device make and model _No response_ ### Your docker-compose.yml content ```YAML name: immich services: immich-server: container_name: immich_server image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release} extends: file: hwaccel.transcoding.yml service: quicksync # Intel Quick Sync (QSV) # extends: # file: hwaccel.transcoding.yml # service: nvenc # nvenc volumes: - ${UPLOAD_LOCATION}:/usr/src/app/upload - /etc/localtime:/etc/localtime:ro env_file: - .env ports: - '2283:2283' depends_on: - redis - database restart: always healthcheck: disable: false immich-machine-learning: container_name: immich_machine_learning image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release} volumes: - model-cache:/cache env_file: - .env restart: always healthcheck: disable: false deploy: resources: limits: cpus: '4' # 分配4核CPU memory: 1G # 分配2GB内存(避免CPU加载模型时内存不足) # immich-machine-learning: # container_name: immich_machine_learning # image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}-cuda # extends: # file: hwaccel.ml.yml # service: cuda # cuda # volumes: # - model-cache:/cache # env_file: # - .env # restart: always # healthcheck: # disable: false redis: container_name: immich_redis image: docker.io/redis:6.2-alpine@sha256:148bb5411c184abd288d9aaed139c98123eeb8824c5d3fce03cf721db58066d8 healthcheck: test: redis-cli ping || exit 1 restart: always database: container_name: immich_postgres image: docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:739cdd626151ff1f796dc95a6591b55a714f341c737e27f045019ceabf8e8c52 environment: POSTGRES_PASSWORD: ${DB_PASSWORD} POSTGRES_USER: ${DB_USERNAME} POSTGRES_DB: ${DB_DATABASE_NAME} POSTGRES_INITDB_ARGS: '--data-checksums' volumes: - ${DB_DATA_LOCATION}:/var/lib/postgresql/data healthcheck: test: >- pg_isready --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" || exit 1; Chksum="$$(psql --dbname="$${POSTGRES_DB}" --username="$${POSTGRES_USER}" --tuples-only --no-align --command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')"; echo "checksum failure count is $$Chksum"; [ "$$Chksum" = '0' ] || exit 1 interval: 5m start_interval: 30s start_period: 5m command: >- postgres -c shared_preload_libraries=vectors.so -c 'search_path="$$user", public, vectors' -c logging_collector=on -c max_wal_size=2GB -c shared_buffers=512MB -c wal_compression=on restart: always volumes: model-cache: ``` ### Your .env content ```Shell # You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables # The location where your uploaded files are stored UPLOAD_LOCATION=/media/ssd1/Junjie/immich # The location where your database files are stored DB_DATA_LOCATION=./postgres # To set a timezone, uncomment the next line and change Etc/UTC to a TZ identifier from this list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List # TZ=Etc/UTC # The Immich version to use. You can pin this to a specific version like "v1.71.0" IMMICH_VERSION=release # Connection secret for postgres. You should change it to a random password # Please use only the characters `A-Za-z0-9`, without special characters or spaces DB_PASSWORD=87894412 # The values below this line do not need to be changed ################################################################################### DB_USERNAME=postgres HF_ENDPOINT=https://hf-mirror.com # sudo nano /etc/systemd/system/docker.service.d/proxy.conf ``` ### Reproduction steps Upload a DJI MP4 (example: DJI OsmoAction6) that contains: Main video stream: HEVC (Main 10) Audio: AAC Extra video stream: MJPEG marked as attached picture (attached pic) Immich runs thumbnail generation job. Thumbnail generation fails with ffmpeg error and job handler error. ### Relevant log output ```shell Immich server logs: [mov,mp4,m4a,3gp,3g2,mj2 @ 0x564d3edd1980] stream 0, timescale not set [hevc_metadata @ 0x564d3edf2ac0] Codec 'mjpeg' (7) is not supported by the bitstream filter 'hevc_metadata'. Supported codecs are: hevc (173) [vist#0:5/mjpeg @ 0x564d3ee2b140] Error initializing bitstream filters: Invalid argument Error opening input file /usr/src/app/upload/upload/.../9f23abfd-5027-4aa6-bc33-315eab47ae18.mp4. Error opening input files: Invalid argument ERROR [Microservices:{"id":"..."}] Unable to run job handler (AssetGenerateThumbnails): Error: ffmpeg exited with code 234 at ChildProcess.<anonymous> (.../node_modules/fluent-ffmpeg/lib/processor.js:180:22) ffprobe output of the problematic MP4 (note stream 0:5 is MJPEG attached pic): Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '.../9f23abfd-5027-4aa6-bc33-315eab47ae18.mp4': Metadata: encoder : DJI OsmoAction6 Duration: 00:00:15.98, start: 0.000000, bitrate: 51870 kb/s Stream #0:0(und): Video: hevc (Main 10) (hvc1), 1920x1080, 50 fps (default) Stream #0:1(und): Audio: aac (LC), 48000 Hz, stereo (default) Stream #0:2(und): Data: none (djmd) Stream #0:3(und): Data: none (dbgi) Stream #0:4(und): Data: none (tmcd) Stream #0:5: Video: mjpeg (Baseline), 1280x720, (attached pic) Workaround Manually remux affected files to remove the attached picture stream (keep only real video + audio), then rerun thumbnail jobs. Example: ffmpeg -i input.mp4 -map 0:v:0 -map 0:a? -c copy -movflags +faststart output.mp4 After removing the MJPEG attached pic stream, Immich can generate thumbnails normally. ``` ### Additional information Suggested fix (what I think is going wrong) Immich’s thumbnail pipeline (or stream selection) seems to: accidentally select the MJPEG attached_pic stream as the input video stream, or apply HEVC-specific bitstream filters (e.g., hevc_metadata) without verifying the selected stream codec is HEVC. Suggested fixes: Exclude attached picture streams from selection when generating thumbnails / extracting frames. Use FFmpeg stream selection that ignores attached_pic (cover art) streams. If hevc_metadata is used, only apply it when the selected stream codec is actually HEVC.
Author
Owner

@Tushar-Harsora commented on GitHub (Jan 5, 2026):

Can you attach sample video from your DJI? this would help reproduce your issue.

@Tushar-Harsora commented on GitHub (Jan 5, 2026): Can you attach sample video from your DJI? this would help reproduce your issue.
Author
Owner

@chipmunkbb commented on GitHub (Jan 7, 2026):

I am encountering the same issue with files from my DJI Osmo Action 6. The logs confirm that the Microservices MediaRepository is failing because it attempts to apply the hevc_metadata bitstream filter to the MJPEG "attached picture" stream (Stream #5) rather than the main video stream.

Key details from my logs:

Camera: DJI Osmo Action 6

FFmpeg Version: 7.1.1-Jellyfin

The Error: [hevc_metadata @ ...] Codec 'mjpeg' (7) is not supported by the bitstream filter 'hevc_metadata'. Supported codecs are: hevc (173)

Stream Conflict: [vist#0:5/mjpeg @ ...] Error initializing bitstream filters: Invalid argument

It appears the auto-detection logic is selecting the MJPEG thumbnail stream (Stream #5) for a filter that is only compatible with HEVC.

error_log.txt

Image

https://github.com/user-attachments/assets/26d998c6-fb87-4eaa-aa84-92a5989f7181

@chipmunkbb commented on GitHub (Jan 7, 2026): I am encountering the same issue with files from my DJI Osmo Action 6. The logs confirm that the Microservices MediaRepository is failing because it attempts to apply the hevc_metadata bitstream filter to the MJPEG "attached picture" stream (Stream #5) rather than the main video stream. Key details from my logs: Camera: DJI Osmo Action 6 FFmpeg Version: 7.1.1-Jellyfin The Error: [hevc_metadata @ ...] Codec 'mjpeg' (7) is not supported by the bitstream filter 'hevc_metadata'. Supported codecs are: hevc (173) Stream Conflict: [vist#0:5/mjpeg @ ...] Error initializing bitstream filters: Invalid argument It appears the auto-detection logic is selecting the MJPEG thumbnail stream (Stream #5) for a filter that is only compatible with HEVC. [error_log.txt](https://github.com/user-attachments/files/24486092/error_log.txt) ![Image](https://github.com/user-attachments/assets/cde392fd-daab-4281-873d-2b84e439cc5c) https://github.com/user-attachments/assets/26d998c6-fb87-4eaa-aa84-92a5989f7181
Author
Owner

@cszmzh commented on GitHub (Jan 11, 2026):

I’m experiencing the same issue when Immich generates video thumbnails.
The videos are recorded with a DJI Osmo Action 6.

The thumbnail job fails with the following core ffmpeg error:

Error: ffmpeg exited with code 234
[mov,mp4,m4a,3gp,3g2,mj2] stream 0, timescale not set

This happens during the AssetGenerateThumbnails job.
It seems to be triggered by certain MP4 files recorded by the Osmo Action 6 that have missing or invalid timescale metadata. Re-muxing the video allows thumbnail generation to succeed.

@cszmzh commented on GitHub (Jan 11, 2026): I’m experiencing the same issue when Immich generates video thumbnails. The videos are recorded with a DJI Osmo Action 6. The thumbnail job fails with the following core ffmpeg error: ``` Error: ffmpeg exited with code 234 [mov,mp4,m4a,3gp,3g2,mj2] stream 0, timescale not set ``` This happens during the AssetGenerateThumbnails job. It seems to be triggered by certain MP4 files recorded by the Osmo Action 6 that have missing or invalid timescale metadata. Re-muxing the video allows thumbnail generation to succeed.
Author
Owner

@hubpf commented on GitHub (Jan 12, 2026):

Exact same issue here with Osmo Action 6. The video will process normally only after I edit it and save it. I guess this actually remove the MJPEG.

@hubpf commented on GitHub (Jan 12, 2026): Exact same issue here with Osmo Action 6. The video will process normally only after I edit it and save it. I guess this actually remove the MJPEG.
Author
Owner

@flikzzio commented on GitHub (Jan 22, 2026):

Having the same issue with my Osmo Action 6

@flikzzio commented on GitHub (Jan 22, 2026): Having the same issue with my Osmo Action 6
Author
Owner

@thisisbommy commented on GitHub (Feb 15, 2026):

Confirming same issue here.

@thisisbommy commented on GitHub (Feb 15, 2026): Confirming same issue here.
Author
Owner

@AlexGugoodman commented on GitHub (Feb 18, 2026):

Same problem with Osmo Action 6. No thumbnail generated for video. However, iphone and other platform can proceed normally, so maybe immich should fix it.

@AlexGugoodman commented on GitHub (Feb 18, 2026): Same problem with Osmo Action 6. No thumbnail generated for video. However, iphone and other platform can proceed normally, so maybe immich should fix it.
Author
Owner

@AlexGugoodman commented on GitHub (Feb 19, 2026):

Great gemini has writen a solution to temporaily solve the problem(time zone and thumbnail).

import os
import subprocess
import time
import shutil
from datetime import datetime, timedelta

BASE_DIR = os.path.dirname(os.path.abspath(file))
FFMPEG_BIN = os.path.join(BASE_DIR, "ffmpeg.exe")
EXIFTOOL_BIN = os.path.join(BASE_DIR, "exiftool.exe")
WORKSPACE = os.path.join(BASE_DIR, ".processing_workspace")

def fix_dji_final_v6():
if not os.path.exists(FFMPEG_BIN) or not os.path.exists(EXIFTOOL_BIN):
print("错误: 找不到工具文件")
return

# 1. 获取时区
tz_input = input("请输入时区数字 (中国填 8): ").strip()
tz_num = int(tz_input) if tz_input else 8
tz_offset = f"+{tz_num:02d}:00" if tz_num >= 0 else f"{tz_num:02d}:00"

# 2. 准备工作目录
if not os.path.exists(WORKSPACE):
    os.makedirs(WORKSPACE)

print(f"\n[设定] 时区: {tz_offset} | 模式: 隔离空间处理")

for root, dirs, files in os.walk(BASE_DIR):
    # 跳过工作目录本身
    if WORKSPACE in root: continue

    for file in files:
        # 只处理原始文件,避开之前的残余
        if file.lower().endswith((".mp4", ".mov")) and not file.startswith(("temp_", "work_", "repaired_")):
            file_path = os.path.join(root, file)
            # 将处理过程完全移出原目录
            temp_task_file = os.path.join(WORKSPACE, "task_" + file)

            try:
                # 时间计算
                time_part = file.split('_')[1][:14]
                dt_obj = datetime.strptime(time_part, "%Y%m%d%H%M%S")
                utc_dt_str = (dt_obj - timedelta(hours=tz_num)).strftime("%Y:%m:%d %H:%M:%S")
            except:
                continue

            print(f"-> 正在处理: {file}", end="\r")

            # 步骤 A: FFmpeg 重封装到隔离区
            subprocess.run([
                FFMPEG_BIN, "-i", file_path, "-map", "0:v:0", "-map", "0:a?",
                "-c", "copy", "-video_track_timescale", "90000",
                "-map_metadata", "0", temp_task_file, "-y"
            ], capture_output=True)

            if os.path.exists(temp_task_file):
                # 步骤 B: ExifTool 在隔离区修改元数据
                # 使用 -overwrite_original 杜绝 _original 文件
                subprocess.run([
                    EXIFTOOL_BIN, f"-AllDates={utc_dt_str}",
                    f"-QuickTime:CreationDate={utc_dt_str}{tz_offset}",
                    f"-Keys:CreationDate={utc_dt_str}{tz_offset}",
                    f"-OffsetTime={tz_offset}", "-overwrite_original", temp_task_file
                ], capture_output=True)

                # 步骤 C: 搬运回原处并覆盖
                time.sleep(0.5)  # 确保句柄释放
                try:
                    shutil.move(temp_task_file, file_path)
                    print(f"完成并替换: {file}          ")
                except Exception as e:
                    print(f"搬运失败: {file}, 错误: {e}")

        elif file.lower().endswith((".jpg", ".jpeg")):
            print(f"-> 正在处理图片: {file}", end="\r")
            subprocess.run([
                EXIFTOOL_BIN, "-AllDates<filename",
                f"-OffsetTime={tz_offset}", "-overwrite_original",
                os.path.join(root, file)
            ], capture_output=True)

# 3. 清理工作目录
try:
    shutil.rmtree(WORKSPACE)
except:
    print("\n[提示] 临时工作目录需手动删除")

print("\n所有任务已完成!请在 Immich 中刷新元数据。")

if name == "main":
fix_dji_final_v6()

@AlexGugoodman commented on GitHub (Feb 19, 2026): Great gemini has writen a solution to temporaily solve the problem(time zone and thumbnail). import os import subprocess import time import shutil from datetime import datetime, timedelta BASE_DIR = os.path.dirname(os.path.abspath(__file__)) FFMPEG_BIN = os.path.join(BASE_DIR, "ffmpeg.exe") EXIFTOOL_BIN = os.path.join(BASE_DIR, "exiftool.exe") WORKSPACE = os.path.join(BASE_DIR, ".processing_workspace") def fix_dji_final_v6(): if not os.path.exists(FFMPEG_BIN) or not os.path.exists(EXIFTOOL_BIN): print("错误: 找不到工具文件") return # 1. 获取时区 tz_input = input("请输入时区数字 (中国填 8): ").strip() tz_num = int(tz_input) if tz_input else 8 tz_offset = f"+{tz_num:02d}:00" if tz_num >= 0 else f"{tz_num:02d}:00" # 2. 准备工作目录 if not os.path.exists(WORKSPACE): os.makedirs(WORKSPACE) print(f"\n[设定] 时区: {tz_offset} | 模式: 隔离空间处理") for root, dirs, files in os.walk(BASE_DIR): # 跳过工作目录本身 if WORKSPACE in root: continue for file in files: # 只处理原始文件,避开之前的残余 if file.lower().endswith((".mp4", ".mov")) and not file.startswith(("temp_", "work_", "repaired_")): file_path = os.path.join(root, file) # 将处理过程完全移出原目录 temp_task_file = os.path.join(WORKSPACE, "task_" + file) try: # 时间计算 time_part = file.split('_')[1][:14] dt_obj = datetime.strptime(time_part, "%Y%m%d%H%M%S") utc_dt_str = (dt_obj - timedelta(hours=tz_num)).strftime("%Y:%m:%d %H:%M:%S") except: continue print(f"-> 正在处理: {file}", end="\r") # 步骤 A: FFmpeg 重封装到隔离区 subprocess.run([ FFMPEG_BIN, "-i", file_path, "-map", "0:v:0", "-map", "0:a?", "-c", "copy", "-video_track_timescale", "90000", "-map_metadata", "0", temp_task_file, "-y" ], capture_output=True) if os.path.exists(temp_task_file): # 步骤 B: ExifTool 在隔离区修改元数据 # 使用 -overwrite_original 杜绝 _original 文件 subprocess.run([ EXIFTOOL_BIN, f"-AllDates={utc_dt_str}", f"-QuickTime:CreationDate={utc_dt_str}{tz_offset}", f"-Keys:CreationDate={utc_dt_str}{tz_offset}", f"-OffsetTime={tz_offset}", "-overwrite_original", temp_task_file ], capture_output=True) # 步骤 C: 搬运回原处并覆盖 time.sleep(0.5) # 确保句柄释放 try: shutil.move(temp_task_file, file_path) print(f"完成并替换: {file} ") except Exception as e: print(f"搬运失败: {file}, 错误: {e}") elif file.lower().endswith((".jpg", ".jpeg")): print(f"-> 正在处理图片: {file}", end="\r") subprocess.run([ EXIFTOOL_BIN, "-AllDates<filename", f"-OffsetTime={tz_offset}", "-overwrite_original", os.path.join(root, file) ], capture_output=True) # 3. 清理工作目录 try: shutil.rmtree(WORKSPACE) except: print("\n[提示] 临时工作目录需手动删除") print("\n所有任务已完成!请在 Immich 中刷新元数据。") if __name__ == "__main__": fix_dji_final_v6()
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/immich#7663
No description provided.