编辑
2025-11-22
C#
00

目录

准备工作
环境依赖
安装NuGet包
基本水印实现
文字水印
图片水印
高级水印技巧
动态水印位置
透明度控制
注意事项
结论

视频水印是保护版权、标识视频来源的重要技术。本文将详细介绍如何使用C#和FFmpeg为视频添加水印,并提供多种实现方式。

准备工作

环境依赖

  • .NET Framework 4.7.2 或更高版本
  • FFmpeg(需要下载并配置系统环境变量)
  • NuGet包:Xabe.FFmpeg

安装NuGet包

使用Package Manager Console安装:

PowerShell
Install-Package Xabe.FFmpeg

基本水印实现

文字水印

C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Xabe.FFmpeg; namespace App08 { public class VideoWatermarker { /// <summary> /// 为视频添加文字水印 /// </summary> /// <param name="inputVideo">输入视频路径</param> /// <param name="outputVideo">输出视频路径</param> /// <param name="watermarkText">水印文字内容</param> public async Task AddTextWatermarkAsync( string inputVideo, string outputVideo, string watermarkText) { try { // 确保已设置 FFmpeg 执行文件路径 FFmpeg.SetExecutablesPath("D:\\Software\\ffmpeg-master-latest-win64-gpl-shared\\bin"); // 创建转换 IMediaInfo mediaInfo = await FFmpeg.GetMediaInfo(inputVideo); // 配置转换参数 var conversion = FFmpeg.Conversions.New() .AddStream(mediaInfo.VideoStreams) .AddStream(mediaInfo.AudioStreams) .AddParameter($"-vf \"drawtext=fontfile=msyh.ttc:" + $"text='{watermarkText}':" + "fontcolor=white:" + "fontsize=24:" + "box=1:" + "boxcolor=black@0.5:" + "boxborderw=5:" + "x=(w-text_w)/2:" + "y=(h-text_h)/2\"") .SetOutput(outputVideo); // 执行转换 await conversion.Start(); } catch (Exception ex) { Console.WriteLine($"水印添加失败:{ex.Message}"); throw; } } } }
C#
static async Task Main(string[] args) { VideoWatermarker watermarker = new VideoWatermarker(); await watermarker.AddTextWatermarkAsync("D:\\Video\\1.mp4", "d:\\output.mp4", "IDIOSOFT"); }

图片水印

C#
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Xabe.FFmpeg; namespace App08 { public class ImageWatermarker { public async Task AddImageWatermarkAsync( string inputVideo, string outputVideo, string watermarkImage) { try { // 设置 FFmpeg 路径 FFmpeg.SetExecutablesPath("D:\\Software\\ffmpeg-master-latest-win64-gpl-shared\\bin"); // 创建转换配置 IConversion conversion = FFmpeg.Conversions.New() .AddParameter($"-i \"{inputVideo}\" -i \"{watermarkImage}\" " + $"-filter_complex \"[0:v][1:v] overlay=W-w-10:10\" " + $"-c:a copy") .SetOutput(outputVideo); // 添加进度报告 conversion.OnProgress += (sender, args) => { var percent = args.Percent; Console.WriteLine($"处理进度: {percent:F1}%"); }; // 添加完成处理程序 conversion.OnDataReceived += (sender, args) => { if (!string.IsNullOrEmpty(args.Data)) { Console.WriteLine($"FFmpeg输出: {args.Data}"); } }; // 执行转换 await conversion.Start(); Console.WriteLine("水印添加成功!"); } catch (Exception ex) { Console.WriteLine($"图片水印添加失败:{ex.Message}"); if (ex.InnerException != null) { Console.WriteLine($"内部错误:{ex.InnerException.Message}"); } throw; } } } }

如果需要调整水印位置,可以修改overlay参数:

  • 右上角:overlay=W-w-10:10
  • 左下角:overlay=10:H-h-10
  • 右下角:overlay=W-w-10:H-h-10
  • 居中:overlay=(W-w)/2:(H-h)/2

其中:

  • W: 视频宽度
  • H: 视频高度
  • w: 水印宽度
  • h: 水印高度

高级水印技巧

动态水印位置

C#
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Xabe.FFmpeg; namespace App08 { public class ImageWatermarker { public async Task AddImageWatermarkAsync( string inputVideo, string outputVideo, string watermarkImage) { try { // 设置 FFmpeg 路径 FFmpeg.SetExecutablesPath("D:\\Software\\ffmpeg-master-latest-win64-gpl-shared\\bin"); // 创建转换配置 IConversion conversion = FFmpeg.Conversions.New() .AddParameter($"-i \"{inputVideo}\" -i \"{watermarkImage}\" " + // Added input video parameter "-filter_complex \"" + "[0:v][1:v]overlay='if(gte(t,2),main_w-overlay_w-10,10):" + "if(gte(t,2),main_h-overlay_h-10,10)'" + "\" -codec:a copy") .SetOutput(outputVideo); // 添加进度报告 conversion.OnProgress += (sender, args) => { var percent = args.Percent; Console.WriteLine($"处理进度: {percent:F1}%"); }; // 添加完成处理程序 conversion.OnDataReceived += (sender, args) => { if (!string.IsNullOrEmpty(args.Data)) { Console.WriteLine($"FFmpeg输出: {args.Data}"); } }; // 执行转换 await conversion.Start(); Console.WriteLine("水印添加成功!"); } catch (Exception ex) { Console.WriteLine($"图片水印添加失败:{ex.Message}"); if (ex.InnerException != null) { Console.WriteLine($"内部错误:{ex.InnerException.Message}"); } throw; } } } }

image.png

C#
// 创建转换配置 IConversion conversion = FFmpeg.Conversions.New() .AddParameter($"-i \"{inputVideo}\" -i \"{watermarkImage}\" " + "-filter_complex \"" + "[0:v][1:v]overlay=" + "'if(lt(mod(t,8),2),10," + // 0-2秒:左上角 "if(lt(mod(t,8),4),main_w-overlay_w-10," + // 2-4秒:右上角 "if(lt(mod(t,8),6),10," + // 4-6秒:左下角 "main_w-overlay_w-10))):" + // 6-8秒:右下角 "if(lt(mod(t,8),2),10," + // 0-2秒:左上角 "if(lt(mod(t,8),4),10," + // 2-4秒:右上角 "if(lt(mod(t,8),6),main_h-overlay_h-10," + // 4-6秒:左下角 "main_h-overlay_h-10)))'" + // 6-8秒:右下角 "\" -codec:a copy") .SetOutput(outputVideo);

参数说明:

水印位置循环逻辑:

使用mod(t,8)将时间分成8秒一个循环,然后在这8秒内分配四个不同的位置

透明度控制

C#
// 创建转换配置 IConversion conversion = FFmpeg.Conversions.New() .AddParameter($"-i \"{inputVideo}\" -i {watermarkImage} " + "-filter_complex \"" + "[1:v]format=rgba,colorchannelmixer=aa=0.5[watermark];" + "[0:v][watermark]overlay=10:10" + "\" -codec:a copy") .SetOutput(outputVideo);

注意事项

  • 确保FFmpeg正确安装
  • 处理大视频文件时注意内存占用
  • 水印不应过度遮挡视频内容

结论

通过C#和FFmpeg,我们可以灵活地为视频添加各种类型的水印,保护内容并增加版权标识。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!