C# 使用FFmpeg為視頻添加水印的完整指南
作者:iamrick
視頻水印是保護版權、標識視頻來源的重要技術。本文將詳細介紹如何使用C#和FFmpeg為視頻添加水印,并提供多種實現方式。
視頻水印是保護版權、標識視頻來源的重要技術。本文將詳細介紹如何使用C#和FFmpeg為視頻添加水印,并提供多種實現方式。
準備工作
環境依賴
- .NET Framework 4.7.2 或更高版本
- FFmpeg(需要下載并配置系統環境變量)
- NuGet包:Xabe.FFmpeg
安裝NuGet包
使用Package Manager Console安裝:
Install-Package Xabe.FFmpeg
基本水印實現
文字水印
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;
}
}
}
}
static async Task Main(string[] args)
{
VideoWatermarker watermarker = new VideoWatermarker();
await watermarker.AddTextWatermarkAsync("D:\\Video\\1.mp4", "d:\\output.mp4", "IDIOSOFT");
}
圖片水印
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: 水印高度
高級水印技巧
動態水印位置
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;
}
}
}
}
圖片
// 創建轉換配置
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秒內分配四個不同的位置
透明度控制
// 創建轉換配置
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,我們可以靈活地為視頻添加各種類型的水印,保護內容并增加版權標識。
責任編輯:武曉燕
來源:
技術老小子