How to Create a Cartoon Effect in FFmpeg

Applying a cartoon or cel-shaded effect to a video in FFmpeg is achieved by running two parallel processing chains on the footage: one that flattens colors using an edge-preserving blur, and another that extracts outlines using an edge-detection filter. By inverting the detected edges into dark lines and multiplying them over the flattened color layer, you produce a stylized animation appearance directly from the command line.

The Complete Command

Run the following command to apply the cartoon effect:

ffmpeg -i input.mp4 -filter_complex \
"[0:v]split=2[color_in][edge_in]; \
 [color_in]bilateral=sigmaS=5:sigmaR=0.2[smoothed]; \
 [edge_in]edgedetect=low=0.1:high=0.3,negate[lines]; \
 [smoothed][lines]blend=all_mode=multiply[outv]" \
-map "[outv]" -map 0:a? -c:v libx264 -crf 18 -c:a copy output.mp4

How the Filtergraph Works

  1. split=2[color_in][edge_in]
    Duplicates the primary video stream into two separate paths for simultaneous processing.

  2. bilateral=sigmaS=5:sigmaR=0.2[smoothed]
    The bilateral filter smooths out surface textures and gradients while keeping sharp boundaries intact.

    • sigmaS (Spatial Sigma): Controls the blur radius. Higher values blur larger areas.
    • sigmaR (Range Sigma): Sets the edge-preservation threshold. Lower values preserve more distinct boundaries between contrasting color fields, avoiding muddy colors.
  3. edgedetect=low=0.1:high=0.3,negate[lines]

    • edgedetect applies a Canny edge detector, rendering high-contrast boundaries as white lines over a pure black background. Adjusting low and high thresholds determines how sensitive the filter is to subtle lines.
    • negate inverts the result, transforming the image into black ink lines on a solid white canvas.
  4. [smoothed][lines]blend=all_mode=multiply[outv]
    The blend filter combines the two streams using the multiply mode. Pure white areas from the lines layer leave the underlying smoothed colors unaffected, while black pixels draw solid dark outlines directly over the image.

Fine-Tuning the Results

  • Increase Cel-Shading: If the bilateral filter leaves too much detail, chain an additional posterize or color reduction step by inserting eq=contrast=1.2:saturation=1.4 into the [color_in] chain to make colors vibrant and punchy.

  • Thicker Outlines: Chain a dilation filter immediately after edgedetect (before negate) to expand the line width:

    [edge_in]edgedetect=low=0.1:high=0.3,dilation,negate[lines]
  • Reduce Noise: If the edge detector picks up unwanted background grain, add a mild blur like smartblur=lr=1:ls=-0.5 prior to edgedetect.