How to generate a preview video for web with a few frames only using ffmpeg? Like when you move the mouse over a video and it plays a few frames for preview before loading the actual video?


The batch script bellow does that. Optimized for web it produces a preview video with 10 images taken from the original video. Each image shows up for 1s. The script get image samples accordingly so the preview images are taken from the whole video.

  • Requires ffmpeg only. (and ffprobe which is part of ffmpeg package)

  • Output: mp4/h.264 ~ 120Kb (regardless of the original video size).

  • Fully configurable.

  • Optimized lanczos and sharpen filter.

  • Keeps the original video's aspect ratio by fitting it in a 16:9 (384x216) frame (fill black bars on the sides when necessary).

  • No temporary files used. (on-the-fly pipe from ffmpeg to ffmpeg)

  • HTML5 friendly.

Here are two gif examples for preview only. The actual output is mp4/h.264:

16:9 video source. Output:

16:9 widescreen

4:3 video source. Output:

4:3 sd

Run on Windows but it can be easily converted to bash script (Linux).

The script creates a folder ./preview where it stores all generated previews:

/My videos
    movie1.mp4 ~ any size
    movie2.mp4 ~ any size
        movie1.mp4 ~ 120Kb
        movie2.mp4 ~ 120Kb 

It can be adjusted to run on individual files.


REM ----------------------------------------------
set folder=C:\My videos
set vframes=10
set width=384
set height=216
    rem w = h*16/9
set filetypes=*.mp4
REM ----------------------------------------------
setlocal EnableDelayedExpansion

pushd "%folder%"
if not exist preview md preview
for /f "usebackq delims=" %%f in (`dir /b %filetypes%`) do (
    if not exist "preview\%%~nf.mp4" (  
        for /f %%i in ('ffprobe -v error -show_entries format^=duration "%%f" -of default^=noprint_wrappers^=1:nokey^=1') do set length=%%i
        set /a length=!length!+0
        set /a fps=!length!/%vframes%
        ffmpeg -threads 2 -i "%%f" -an -qscale:v 1 -vf "fps=1/!fps!, scale=iw*min(%width%/iw\,%height%/ih):ih*min(%width%/iw\,%height%/ih):flags=lanczos, pad=%width%:%height%:(%width%-iw*min(%width%/iw\,%height%/ih))/2:(%height%-ih*min(%width%/iw\,%height%/ih))/2, unsharp=5:5:0.5:5:5:0.5" -vframes %vframes% -f image2pipe -vcodec ppm - ^
        | ffmpeg -y -threads 2 -framerate 1 -i pipe:0 -c:v libx264 -profile:v baseline -level 3.0 -tune stillimage -r 30 -pix_fmt yuv420p "preview\%%~nf.mp4"

Update: You can easily control the playback rate in HTML5 <video> as shown here

Why not use gif instead?

  • .gif format have a worst quality (pixelate colors / max 256 colors)

  • .gif file size is at least 2x bigger.

  • You cannot control the playback speed/pause gif animations after it have been built.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.