C# 使用FFmpeg為視頻添加水印的完整指南
作者:iamrick
視頻水印是保護(hù)版權(quán)、標(biāo)識視頻來源的重要技術(shù)。本文將詳細(xì)介紹如何使用C#和FFmpeg為視頻添加水印,并提供多種實現(xiàn)方式。
視頻水印是保護(hù)版權(quán)、標(biāo)識視頻來源的重要技術(shù)。本文將詳細(xì)介紹如何使用C#和FFmpeg為視頻添加水印,并提供多種實現(xiàn)方式。
準(zhǔn)備工作
環(huán)境依賴
- .NET Framework 4.7.2 或更高版本
- FFmpeg(需要下載并配置系統(tǒng)環(huán)境變量)
- NuGet包:Xabe.FFmpeg
安裝NuGet包
使用Package Manager Console安裝:
Install-Package Xabe.FFmpeg
基本水印實現(xiàn)
文字水印
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">水印文字內(nèi)容</param>
public async Task AddTextWatermarkAsync(
string inputVideo,
string outputVideo,
string watermarkText)
{
try
{
// 確保已設(shè)置 FFmpeg 執(zhí)行文件路徑
FFmpeg.SetExecutablesPath("D:\\Software\\ffmpeg-master-latest-win64-gpl-shared\\bin");
// 創(chuàng)建轉(zhuǎn)換
IMediaInfo mediaInfo = await FFmpeg.GetMediaInfo(inputVideo);
// 配置轉(zhuǎn)換參數(shù)
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);
// 執(zhí)行轉(zhuǎn)換
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
{
// 設(shè)置 FFmpeg 路徑
FFmpeg.SetExecutablesPath("D:\\Software\\ffmpeg-master-latest-win64-gpl-shared\\bin");
// 創(chuàng)建轉(zhuǎn)換配置
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);
// 添加進(jìn)度報告
conversion.OnProgress += (sender, args) =>
{
var percent = args.Percent;
Console.WriteLine($"處理進(jìn)度: {percent:F1}%");
};
// 添加完成處理程序
conversion.OnDataReceived += (sender, args) =>
{
if (!string.IsNullOrEmpty(args.Data))
{
Console.WriteLine($"FFmpeg輸出: {args.Data}");
}
};
// 執(zhí)行轉(zhuǎn)換
await conversion.Start();
Console.WriteLine("水印添加成功!");
}
catch (Exception ex)
{
Console.WriteLine($"圖片水印添加失?。簕ex.Message}");
if (ex.InnerException != null)
{
Console.WriteLine($"內(nèi)部錯誤:{ex.InnerException.Message}");
}
throw;
}
}
}
}
如果需要調(diào)整水印位置,可以修改overlay參數(shù):
- 右上角: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: 水印高度
高級水印技巧
動態(tài)水印位置
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
{
// 設(shè)置 FFmpeg 路徑
FFmpeg.SetExecutablesPath("D:\\Software\\ffmpeg-master-latest-win64-gpl-shared\\bin");
// 創(chuàng)建轉(zhuǎn)換配置
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);
// 添加進(jìn)度報告
conversion.OnProgress += (sender, args) =>
{
var percent = args.Percent;
Console.WriteLine($"處理進(jìn)度: {percent:F1}%");
};
// 添加完成處理程序
conversion.OnDataReceived += (sender, args) =>
{
if (!string.IsNullOrEmpty(args.Data))
{
Console.WriteLine($"FFmpeg輸出: {args.Data}");
}
};
// 執(zhí)行轉(zhuǎn)換
await conversion.Start();
Console.WriteLine("水印添加成功!");
}
catch (Exception ex)
{
Console.WriteLine($"圖片水印添加失?。簕ex.Message}");
if (ex.InnerException != null)
{
Console.WriteLine($"內(nèi)部錯誤:{ex.InnerException.Message}");
}
throw;
}
}
}
}
圖片
// 創(chuàng)建轉(zhuǎn)換配置
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);
參數(shù)說明:
水印位置循環(huán)邏輯:
使用mod(t,8)將時間分成8秒一個循環(huán),然后在這8秒內(nèi)分配四個不同的位置
透明度控制
// 創(chuàng)建轉(zhuǎn)換配置
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正確安裝
- 處理大視頻文件時注意內(nèi)存占用
- 水印不應(yīng)過度遮擋視頻內(nèi)容
結(jié)論
通過C#和FFmpeg,我們可以靈活地為視頻添加各種類型的水印,保護(hù)內(nèi)容并增加版權(quán)標(biāo)識。
責(zé)任編輯:武曉燕
來源:
技術(shù)老小子