如何使用 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()
此解决方案有效,但存在问题:
- 最后它降低了原始渐变图片的亮度,我根本不想要
- 它看起来不太优雅(因为色度键控解决方案)
是否可以用 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()
示例输出:
我想实现这个结果(在视频顶部放置带有渐变的文本或任何图片填充):
这是带有 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()
此解决方案有效,但存在问题:
- 最后它降低了原始渐变图片的亮度,我根本不想要
- 它看起来不太优雅(因为色度键控解决方案)
是否可以用 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()
示例输出: