I'd like to achieve this result (to place a text with gradint or whatever picture-fill on top of a video):
So I decided to make a picture of gradient:
and then with chroma-key technique transform it to this (with transparent background):
and then place it over the video.
Here is the code with ffmpeg-python
:
font_path = 'fonts/my_font.ttf'
input_video = ffmpeg.input('vid01.mp4')
split = input_video.filter_multi_output('split')
split_main = split[0]
split_txt_bg = split[1]
text_bg_black = ffmpeg.filter(text_bg, 'eq', brightness=-1000, saturation=0) # generate black bg from video input
text_mask = ffmpeg.filter(text_bg_black, 'drawtext', text='some text', fontcolor='0xFFFFFF', fontsize=85, x='(w-text_w)/2', y='68-(text_h/2)', fontfile=font_path) #draw text
text_mask_transparent = ffmpeg.filter(text_mask, 'colorkey', color='0xFFFFFF', similarity=0.45, blend=0.1)
text_on_bg = ffmpeg.filter([fill_gradient_gold, text_mask_transparent], 'overlay', x='(W-w)/2', y='(H-h)/2')
text = ffmpeg.filter(text_on_bg, 'colorkey', color='0x000000', similarity=0.45, blend=0.01)
comp1 = ffmpeg.filter([split_main, text], 'overlay', x='(W-w)/2', y='(H-h)/2')
comp.output('vid01_comp1.mp4').overwrite_output().run()
This solution works, BUT with problems:
Is it possible to make a alpha-mask with drawtext
and then use it to cut the gradient?
It would be better if you provide the answer in ffmpeg-python
cuz I'm a newbie and it's very hard for me to convert command-line ffmpeg
to ffmpeg-python
, thank you!
I also can't get how to mix resulting video comp1
with music file, help pls.
We may draw the text on black background, and use alphamerge
for creating transparent background with colored gradient text.
Then we can overlay the gradient (with the transparent background) on the input video.
I don't know if my suggested solution is the most elegant, but it is not lower the brightness of the gradient picture.
The suggested solution applies the following stages:
Start by creating synthetic yellow video file (with sine audio) for testing:
# Build first synthetic video, for testing:
(
ffmpeg
.output(ffmpeg.input('sine=frequency=500', f='lavfi'),
ffmpeg.input('color=yellow:size=1920x1080:rate=1', f='lavfi'),
'in.mp4', vcodec='libx264', crf=17, pix_fmt='yuv444p', acodec='aac', ar=22050, t=10)
.overwrite_output()
.run()
)
Solution code sample:
import ffmpeg
# Example using FFmpeg CLI:
# ffmpeg -y -i text_bg.png -f lavfi -i color=0x505050:size=1920x1080:rate=1:duration=1 -filter_complex "color=black[blk];[blk][0:v]scale2ref[b][v0];[b]drawtext=text='some text':fontcolor='0xFFFFFF':fontsize=300:x='(w-text_w)/2':y='(h-text_h)/2',format=gray[a];[v0][a]alphamerge[txt];[1:v][txt]overlay=format=yuv444" -frames:v 1 overlayed_text.png
input = ffmpeg.input('in.mp4')
input_video = input.video
input_audio = input.audio
bg = ffmpeg.input('text_bg.png').video # Gradient image
blk = ffmpeg.input('color=black:size=1920x1080:rate=1:duration=1', f='lavfi').video # Black background
# White text on black background - used as alpha channel
txt = blk.filter('drawtext', text='some text', fontcolor='0xFFFFFF', fontsize=400, x='(w-text_w)/2', y='(h-text_h)/2').filter('format', pix_fmts='gray')
# Add txt as alpha channel to bg - only the white text is opaque, the black background is transparent.
txt_on_bg = ffmpeg.filter([bg, txt], 'alphamerge')
# Overlay txt_on_bg on input_video
comp1 = ffmpeg.filter([input_video, txt_on_bg], 'overlay', x='(W-w)/2', y='(H-h)/2', format='yuv444')
ffmpeg.output(comp1, input_audio, 'vid01_comp1.mp4', vcodec='libx264', crf=17, pix_fmt='yuv444p', acodec='copy').overwrite_output().run()