如何使用 ffmpeg (ffmpeg-python) 绘制带有颜色渐变填充的文本?然后与音乐混合?

How to drawtext with a color gradient fill with ffmpeg (ffmpeg-python)? and then mix with music?

我想实现这个结果(在视频顶部放置带有渐变的文本或任何图片填充): 所以我决定做一个渐变的图片: 然后使用色度键技术将其转换为(透明背景): 然后将其放在视频上。

这是带有 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()

此解决方案有效,但存在问题:

  1. 最后它降低了原始渐变图片的亮度,我根本不想要
  2. 它看起来不太优雅(因为色度键控解决方案)

是否可以用 drawtext 制作一个 alpha 蒙版,然后用它来切割渐变?

如果你在ffmpeg-python中提供答案会更好,因为我是新手,我很难将命令行ffmpeg转换为ffmpeg-python,谢谢你!

我也不知道如何将生成的视频 comp1 与音乐文件混合,请帮忙。

我们可以在黑色背景上绘制文本,并使用alphamerge创建带有彩色渐变文本的透明背景。
然后我们可以在输入视频上叠加渐变(透明背景)。

不知道我推荐的方案是不是最优雅的,但是不会降低渐变图片的亮度。


建议的解决方案适用于以下阶段:

  • 定义合成黑色视频源(1 帧)。
  • 在黑色视频帧上绘制白色文本。
  • 添加“黑底白字”作为渐变图像的 alpha 通道。
    只有白色文字不透明,黑色背景全透明
  • 将上面的帧叠加在视频上。

首先创建用于测试的合成黄色视频文件(带有正弦音频):

# 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()
)

解决方案代码示例:

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()

示例输出: