0

I'm working on a video project where I need to overlay an image on a background video. I've managed to achieve the basic overlay using the following FFmpeg command:

ffmpeg -i background.mp4 -i image_video.mp4 -filter_complex "[0][1]overlay=(W-w)/2:(H-h)/2" -c:v libx264 -crf 23 -preset veryfast output.mp4

This command overlays the image on the background video, centered. However, I would like to add an effect similar to a CSS box shadow, where the overlaid image has a shadow that gradually fades out, giving it a sense of depth.

I've tried various combinations of FFmpeg filters, such as boxblur, gblur, and drawbox, but I can't quite achieve the desired effect.

I'm attaching two images to illustrate what I have and what I'm trying to achieve:

The current result of my FFmpeg command : https://i.imgur.com/3uK79jP.png

An example of the desired box shadow effect : https://i.imgur.com/KaIq7VI.png

1 Answer 1

0

if resolution of image.png 312x420, create shadow +10px

ffmpeg -lavfi "
color=black:322x430,format=rgba,
geq=lum='p(X,Y)':a='
if(gt(abs(W/2-X),W/2-20)*gt(abs(H/2-Y),H/2-20),
if(lte(hypot(20-(W/2-abs(W/2-X)),20-(H/2-abs(H/2-Y))),20),
lerp(0,255,(10-hypot(20-(W/2-abs(W/2-X)),20-(H/2-abs(H/2-Y))))/10),0),

if(lt(X,  20)*between(Y,20,H-20),lerp(0,255,   X /10),
if(gt(X,W-20)*between(Y,20,H-20),lerp(0,255,(W-X)/10),
if(lt(Y,  20)*between(X,20,W-20),lerp(0,255,   Y /10),
if(gt(Y,H-20)*between(X,20,W-20),lerp(0,255,(H-Y)/10),
0)))))'
" -frames 1 shadow.png

then overlay shadow (shifted to 3px down) and rounded image by 10px on background video

ffmpeg -i bg.mkv -i shadow.png -i image.png -lavfi "
[2]geq=lum='p(X,Y)':
a='if(gt(abs(W/2-X),W/2-10)*gt(abs(H/2-Y),H/2-10),
if(lte(hypot(10-(W/2-abs(W/2-X)),10-(H/2-abs(H/2-Y))),10),255,0),255)'[p];
[0][1]overlay=(W-w)/2:(H-h)/2+3[v];
[v][p]overlay=(W-w)/2:(H-h)/2
" out.mp4

bash script:

#!/bin/bash

IMG="image.png"
IFS=, read WID HEI <<< $(ffprobe -v 0 -select_streams v:0 -show_entries stream=width,height -of csv=p=0 "$IMG")
echo $WID $HEI
# margin, change it:
LOW=10
(( RAD=2*$LOW ))
(( SHW=$WID+$LOW ))
(( SHH=$HEI+$LOW ))

ffmpeg -i bg.mkv -i "$IMG" -lavfi "
color=black:${SHW}x${SHH}:d=0.01,format=rgba,
geq=lum='p(X,Y)':a='
if(gt(abs(W/2-X),W/2-${RAD})*gt(abs(H/2-Y),H/2-${RAD}),
  if(lte(hypot(${RAD}-(W/2-abs(W/2-X)),${RAD}-(H/2-abs(H/2-Y))),${RAD}),
  lerp(0,255,(${LOW}-hypot(${RAD}-(W/2-abs(W/2-X)),${RAD}-(H/2-abs(H/2-Y))))/${LOW}),0),
if(gt(abs(W/2-X),W/2-${RAD})*between(Y,${RAD},H-${RAD}),lerp(0,255,(W/2-abs(W/2-X))/${LOW}),
if(gt(abs(H/2-Y),H/2-${RAD})*between(X,${RAD},W-${RAD}),lerp(0,255,(H/2-abs(H/2-Y))/${LOW}),
0)))'[s];

[1]geq=lum='p(X,Y)':
a='if(gt(abs(W/2-X),W/2-${LOW})*gt(abs(H/2-Y),H/2-${LOW}),
if(lte(hypot(${LOW}-(W/2-abs(W/2-X)),${LOW}-(H/2-abs(H/2-Y))),${LOW}),255,0),255)'[p];

[0][s]overlay=(W-w)/2:(H-h)/2+${LOW}/3[v];
[v][p]overlay=(W-w)/2:(H-h)/2
" out.mp4

ffplay out.mp4

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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