如何用FFmpeg与Python给视频加水印?排查代码无水印问题
问题分析与修复方案
核心错误点
- 水印仅显示一帧:PNG是单帧图片,默认仅在视频第一帧出现,后续帧无水印,需让水印循环匹配视频时长。
- 未设置透明度:缺少实现50%半透明的滤镜逻辑。
- 音频滤镜参数错误:
amix滤镜指定inputs=2,但实际仅传入一个音频输入,会触发FFmpeg报错,可能中断流程。 - 流关联逻辑错误:原代码未正确将处理后的水印流与主视频流绑定,导致水印滤镜未生效。
修复后的代码
audio = f'{PROJECT_PATH}/data/ppt-elements/audio_{file_id}.txt' images = f'{PROJECT_PATH}/data/ppt-elements/images_{file_id}.txt' image_input = ffmpeg.input(images, f='concat', safe=0, t=seconds).video audio_input = ffmpeg.input(audio, f='concat', safe=0, t=seconds).audio additional_parameters = {'c:a': 'aac', 'c:v': 'libx264'} # 若需混合多个音频,需先传入多个音频流再使用amix;单音频则无需此滤镜,注释避免报错 # audio_input = ffmpeg.filter(audio_input, "amix", inputs=2, duration="longest") watermark_file = f"{PROJECT_PATH}/data/logo/logo.png" # 处理水印:循环播放+50%透明度 watermark = ffmpeg.input(watermark_file) # loop=1无限循环,size=-1表示循环至主视频结束 watermark = ffmpeg.filter(watermark, 'loop', loop=1, size=-1) # 确保水印支持透明通道 watermark = ffmpeg.filter(watermark, 'format', pix_fmts='yuva420p') # 设置50%透明度 watermark = ffmpeg.filter(watermark, 'opacity', 0.5) # 将主视频与处理后的水印合并 filtered_video = ffmpeg.filter([image_input, watermark], 'overlay', x=10, y=10) # 输出时传入处理后的视频流与音频流 command = ffmpeg.output(filtered_video, audio_input, f"{PROJECT_PATH}/data/final-{file_id}.mp4", vf="fps=10,format=yuv420p", preset="veryfast", shortest=None, r=10, max_muxing_queue_size=4000, **additional_parameters) command.overwrite_output().run(capture_stdout=True, capture_stderr=True)
关键修复说明
- 水印循环:通过
loop=1, size=-1让单帧PNG持续播放至视频结束。 - 透明度实现:用
opacity=0.5直接设置水印半透明,配合format=yuva420p保证透明通道生效。 - 流绑定修正:将主视频和处理后的水印通过
filter合并为新视频流,替代原输入列表方式,解决流引用错误。 - 音频滤镜修正:移除错误的
amix参数,若需混合多音频,需先传入多个音频流再调用该滤镜。
内容的提问来源于stack exchange,提问作者Mr.Slow
相关产品推荐
相关产品推荐

