Sharpen Blurry Video with FFmpeg Dynamic Unsharp

This guide demonstrates how to fix blurry videos using FFmpeg’s powerful unsharp filter. You will learn how to apply dynamic sharpening strength settings that change over time or based on video frames, allowing for precise control over the clarity and detail of your footage.

The FFmpeg Unsharp Filter Syntax

The basic syntax for the unsharp filter is:

unsharp=luma_msize_x:luma_msize_y:luma_amount:chroma_msize_x:chroma_msize_y:chroma_amount

For most blurry videos, you only need to target the luma channel to avoid color artifacts. A standard static sharpening command looks like this:

ffmpeg -i input.mp4 -vf "unsharp=5:5:1.5:5:5:0.0" output.mp4

Method 1: Dynamic Sharpening Using Blend (Smooth Transitions)

Because the unsharp filter’s strength parameter cannot natively read time-based expressions directly, the most robust way to achieve a dynamic, smoothly changing sharpness is by blending a fully sharpened video stream with the original stream using a time-based expression (t).

This command gradually increases the sharpening strength from 0 to maximum over the first 10 seconds of the video:

ffmpeg -i input.mp4 -filter_complex \
"[0:v]unsharp=5:5:2.5:5:5:0.0[sharp]; \
 [0:v][sharp]blend=all_expr='A*(1-t/10)+B*(t/10)':enable='between(t,0,10)'[out]" \
 -map "[out]" -c:a copy output.mp4

How it works:

  1. [0:v]unsharp=...[sharp]: Creates a heavily sharpened copy of the input video (strength of 2.5).
  2. blend=all_expr='A*(1-t/10)+B*(t/10)': Blends the original video (A) and the sharpened video (B).
  3. At t=0 (0 seconds), the video is 100% original. At t=10 (10 seconds), the video is 100% sharpened.
  4. enable='between(t,0,10)': Restricts this dynamic transition to the first 10 seconds.

Method 2: Dynamic Sharpening Using sendcmd (Step-by-Step Changes)

If you need the sharpening strength to change abruptly at specific timestamps (e.g., during a camera focus shift), you can use the sendcmd filter to pass commands to the unsharp filter during playback.

Step 1: Create a command text file

Create a text file named commands.txt and define the times and the corresponding luma strength:

0.0 unsharp luma_amount 0.5;
5.0 unsharp luma_amount 1.5;
12.5 unsharp luma_amount 3.0;
20.0 unsharp luma_amount 1.0;

Step 2: Run the FFmpeg command

Run FFmpeg and point the sendcmd filter to your text file:

ffmpeg -i input.mp4 -vf "sendcmd=f=commands.txt,unsharp" -c:a copy output.mp4

How it works: