Skip to content

Instantly share code, notes, and snippets.

@LenweSaralonde
Last active April 27, 2026 08:03
Show Gist options
  • Select an option

  • Save LenweSaralonde/7e017168b0ef01682f55d852b408dac4 to your computer and use it in GitHub Desktop.

Select an option

Save LenweSaralonde/7e017168b0ef01682f55d852b408dac4 to your computer and use it in GitHub Desktop.
Fix thumbnail generation on Synology DSM and File Station for HEIC photos and HVEC videos

Fix thumbnail generation on Synology DSM and File Station for HEIC photos and HVEC videos

Synology DiskStation DSM update 7.2.2 broke support for HEIC and video thumbnails such as HVEC.

This guide will help you setting up a scheduled task using filebot to generate the missing thumbnails in the background for File Station for the web and DS File on mobile.

Install packages

Log into DSM.

You first need to add third party package sources:

  1. Package Center ► Settings ► Package Sources ► Add ► Name: FileBot and Location: https://get.filebot.net/syno/
  2. Package Center ► Settings ► Package Sources ► Add ► Name: SynoCommunity and Location: https://packages.synocommunity.com/

Then, install the following packages:

  1. Package Center ► Community ► Install Java Installer package
  2. Package Center ► Community ► Install FileBot package
  3. Package Center ► Community ► Install FFmpeg 7 package
  4. Package Center ► Community ► Install ImageMagick package

Enable SSH access

For the rest of the process, you'll need to enable SSH access on your Synology NAS:

  1. Control Panel ► Terminal & SNMP ► Terminal tab ► Check Enable SSH service, choose the port number you like (22) then click "Apply".

You can now connect to your Synology NAS using SSH as an administrator using the ssh your_username@synology_ip command on macOS and Linux or using any ssh client such as PuTTY on Windows.

Create the script

  1. Make a scripts folder in your home folder.
  2. Create the generate-photo-thumbnails.sh script file with the following content (replace the value of PHOTO_FOLDER by your photo folder if it's different):
#!/bin/bash

# Change this value with the location of your photo folder
PHOTO_FOLDER='/volume1/photo'

# Use flock to prevent multiple instances
LOCKFILE="/tmp/$(basename $0).lock"
exec 200>"$LOCKFILE"
flock -n 200 || {
    echo "Another instance of the script is already running."
    exit 0
}

# Use the folder provided as argument. Otherwise, use PHOTO_FOLDER.
FOLDER_PATH="${1:-$PHOTO_FOLDER}"

echo "Generating thumbnails for ${FOLDER_PATH}"

# Generate HEIC photos thumbnails
filebot -find "$FOLDER_PATH" --filter 'def i = f.dir / "@eaDir" / f.name / "SYNOFILE_THUMB_M.jpg"; ext ==~ /(?i:HEIC|HEIF)/ && !i.exists() && (i.dir.exists() || i.dir.mkdirs())' \
    -exec /usr/local/bin/magick '{f}' -thumbnail '360x448>' -write '{folder}/@eaDir/{f.name}/SYNOFILE_THUMB_M.jpg' -thumbnail '120x160>' '{folder}/@eaDir/{f.name}/SYNOFILE_THUMB_S.jpg'

# Generate video thumbnails
filebot -find "$FOLDER_PATH" --filter 'def i = f.dir / "@eaDir" / f.name / "SYNOVIDEO_VIDEO_SCREENSHOT.jpg"; f.video && (i.dir.exists() || i.dir.mkdirs()) && !i.exists() && seconds > 0' \
    -exec /usr/local/bin/ffmpeg7 -hide_banner -loglevel error -an -ss '{seconds/5}' -i '{f}' -vframes 1 -vf scale=size=hd480:force_original_aspect_ratio=decrease -f mjpeg -y '{folder}/@eaDir/{f.name}/SYNOVIDEO_VIDEO_SCREENSHOT.jpg'

Run the script

It's better to make sure the script actually works before adding it as a scheduled task.

You can run the script on a specific folder by typing the following command: bash ~/scripts/generate-photo-thumbnails.sh "/volume1/photo/some_pictures_folder"

The process may take several minutes and even hours depending on the amount of files you have to process.

You may also want to run the script on demand right after uploading a new folder.

Please be aware that the script is CPU intensive, it's why it's not possible to run several instances of the script at the same time.

If everything is fine (you should see the thumbnails in the folder in DSM) you proceed to the next step.

Create the scheduled task

  1. Log into your Synology using SSH.
  2. Go to your home folder by typing: cd ~
  3. Get the full path of your home folder by typing pwd (you'll get something such as /var/services/homes/your_username).
  4. Log into DSM.
  5. Control Panel ► Task Scheduler ► Create ► Scheduled Task ► User defined-script.
  6. Under the "General Settings" tab, set "Task" to Generate photo thumbnails and set "User" with your username.
  7. Under the "Schedule" tab, check "Run on the following days" and set "Repeat" to "Daily". Under "Time", select a "Start time" somewhere in the middle of the night (ie 4am).
  8. Under the "Task Settings" tab, set the "User-defined script" to bash /var/services/homes/your_username/scripts/generate-photo-thumbnails.sh (refer to the returned value at step 3).
  9. Click "OK".
@rednoah
Copy link
Copy Markdown

rednoah commented May 26, 2025

If docker is installed then you could make it work without any additional dependencies (other than docker) so that it boils down to copy & pasting some code into the Task Manager like in this example:
https://www.filebot.net/forums/viewtopic.php?t=14245#task-scheduler

On second thought, DSM does require you to be root to run docker and teaching people to blindly copy & paste code and then run it as root might not be such a good idea. Writing your own scripts and understanding the code is always a good idea.

@LenweSaralonde
Copy link
Copy Markdown
Author

If docker is installed then you could make it work without any additional dependencies (other than docker) so that it boils down to copy & pasting some code into the Task Manager like in this example: https://www.filebot.net/forums/viewtopic.php?t=14245#task-scheduler

Docker is more convenient for the end-user but also requires more ressources to run. I wrote this script to run on a DS218 so the focus is on the performance rather than convenience.

DSM does require you to be root to run docker and teaching people to blindly copy & paste code and then run it as root might not be such a good idea. Writing your own scripts and understanding the code is always a good idea.

The script doesn't require root privileges to run, only a user who has write access to the photo folder.

@rednoah
Copy link
Copy Markdown

rednoah commented May 26, 2025

That makes sense. 👍

@vimaljoseph
Copy link
Copy Markdown

In the latest version - 7.2.2 just the SYNOVIDEO_VIDEO_SCREENSHOT.jpg did not work for me. In the @eadir folder there are files like

SYNOPHOTO_THUMB_SM.jpg
SYNOPHOTO_THUMB_XL.jpg
SYNOPHOTO_THUMB_M.fail
SYNOVIDEO_VIDEO_SCREENSHOT.jpg
SYNOPHOTO_THUMB_ORIG.fail

When I manually create SYNOPHOTO_THUMB_SM.jpg etc, and run synoindex on the file, it is showing the thumbnail. Is this the right way? Then I can update the script to create these files like

/usr/local/bin/ffmpeg7 -hide_banner -loglevel error -an -ss 00:00:05 -i "/volume1/photo/Album/demo.mp4" \ -vframes 1 -vf "scale=-2:480:flags=lanczos" -f mjpeg -y "/volume1/photo/Album/@eaDir/demo.mp4/SYNOVIDEO_VIDEO_SCREENSHOT.jpg"

/usr/local/bin/ffmpeg7 -hide_banner -loglevel error -i "/volume1/photo/Album/@eaDir/demo.mp4/SYNOVIDEO_VIDEO_SCREENSHOT.jpg" \ -vf "scale=120:-2:flags=lanczos" -y "/volume1/photo/Album/@eaDir/demo.mp4/SYNOPHOTO_THUMB_S.jpg"
Any one face this?

@LenweSaralonde
Copy link
Copy Markdown
Author

In the latest version - 7.2.2 just the SYNOVIDEO_VIDEO_SCREENSHOT.jpg did not work for me.

@vimaljoseph I found an issue where filebot fails if the video duration can't be determined. The workaround is to just skip the videos with no duration by adding seconds > 0 in the filter. This is a solution I found on Reddit.

The script was updated accordingly, you may want to give it a try as your issue may have the same root cause.

In addition, change your task settings to send the output log when it fails by email, it helps a lot for debugging.

@joelpk2r
Copy link
Copy Markdown

Hi, I wanted to thank you, you helped me a lot. I also wanted to ask if there is a way to do it with .Webp

@rednoah
Copy link
Copy Markdown

rednoah commented Sep 25, 2025

I also wanted to ask if there is a way to do it with .Webp

The problem here is that DSM fundamentally doesn't recognise *.webp as image files, so even if you create the SYNOPHOTO_* thumbnail files, File Station and friends won't request or display thumbnails.

@LenweSaralonde
Copy link
Copy Markdown
Author

I also wanted to ask if there is a way to do it with .Webp

The problem here is that DSM fundamentally doesn't recognise *.webp as image files, so even if you create the SYNOPHOTO_* thumbnail files, File Station and friends won't request or display thumbnails.

I can confirm. The script can be easily modified to include .webp files but the thumbnails remain invisible.

@oloev
Copy link
Copy Markdown

oloev commented Jan 5, 2026

This does not work on DSM 7.2.3 with the latest iOS 26.
Thumbnails for new files are generated correctly with the script in the eaDir folder, but File Station still shows a generic icon instead of the preview.
For older HEIC files from 2024, DSM generates thumbnails properly when the folder is opened in File Station.
I also tried copying the contents of eaDir/old_file_with_correct_thumbnails.HEIC to eaDir/new_file_with_generic_icon.HEIC, but File Station continues to show a blank icon.
It looks like newer HEIC files are somehow not supported (or partially supported) by DSM or File Station.

@LenweSaralonde
Copy link
Copy Markdown
Author

For older HEIC files from 2024, DSM generates thumbnails properly when the folder is opened in File Station.

The thumbnails are generated in JPEG format using Imagemagick. You may need to update the Imagemagick package to the latest version to support iOS 26 HEIC files.

@ivan-leschinsky
Copy link
Copy Markdown

Yes., it's much easier to run with docker, scripts are from the forum:

sudo docker run --rm -e PUID=0 -e PGID=0 -v 'data:/data' -v "/volume1:/volume1" rednoah/filebot \
	-find "/volume1/Media/Movies" --filter 'def i = f.dir / "@eaDir" / f.name / "SYNOVIDEO_VIDEO_SCREENSHOT.jpg"; f.video && !i.exists() && seconds > 0 && (i.dir.exists() || i.dir.mkdirs())' \
	-exec ffmpeg -an -ss '{seconds/5}' -i '{f}' -vframes 1 -vf scale=size=hd480:force_original_aspect_ratio=decrease -f mjpeg -y '{folder}/@eaDir/{f.name}/SYNOVIDEO_VIDEO_SCREENSHOT.jpg'

# or

SHARE='/volume1/Media'

docker run --rm -e PUID=0 -e PGID=0 -v 'data:/data' -v "$SHARE:$SHARE" rednoah/filebot \
	-find "$SHARE" --filter 'def i = f.dir / "@eaDir" / f.name / "SYNOVIDEO_VIDEO_SCREENSHOT.jpg"; f.video && !i.exists() && seconds > 0 && (i.dir.exists() || i.dir.mkdirs())' \
	-exec ffmpeg -an -ss '{seconds/5}' -i '{f}' -vframes 1 -vf scale=size=hd480:force_original_aspect_ratio=decrease -f mjpeg -y '{folder}/@eaDir/{f.name}/SYNOVIDEO_VIDEO_SCREENSHOT.jpg'

and for the photos:

SHARE='/volume1/Media'

docker run --rm -e PUID=0 -e PGID=0 -v 'data:/data' -v "$SHARE:$SHARE" rednoah/filebot \
	-find "$SHARE" --filter 'def i = f.dir / "@eaDir" / f.name / "SYNOFILE_THUMB_S.jpg"; ext ==~ /(?i:HEIC|HEIF)/ && !i.exists() && (i.dir.exists() || i.dir.mkdirs())' \
	-exec convert -verbose '{f}' -thumbnail '1280x1280>' -write '{folder}/@eaDir/{f.name}/SYNOFILE_THUMB_XL.jpg' -thumbnail '360x360>' -write '{folder}/@eaDir/{f.name}/SYNOFILE_THUMB_M.jpg' -thumbnail '120x120>' '{folder}/@eaDir/{f.name}/SYNOFILE_THUMB_S.jpg'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment