FFmpegUtil工具类
ffmpeg命令参数
输入输出选项
-
- -i: 指定输入文件。
- -c: 指定编码器。
- -c:v: 指定视频编码器。
- -c:a: 指定音频编码器。
- -f: 指定输出格式。
- -y: 覆盖输出文件而不询问。
- -n: 不要覆盖输出文件。
格式转换
-
- -t: 指定输出文件的持续时间。
- -ss: 从输入文件开始转换的时间点。
视频选项
-
- -r: 设置帧率。
- -s: 设置分辨率。
- -aspect: 设置视频宽高比。
- -vframes: 设置输出的视频帧数。
音频选项
-
- -ar: 设置音频采样率。
- -ac: 设置音频通道数。
- -ab: 设置音频比特率。
滤镜和图像处理(过滤器)
-
- -vf: 应用视频滤镜。
- -af: 应用音频滤镜。
- -filter_complex: 应用复杂的滤镜。
编码选项
-
- -b: 设置比特率。
- -q: 设置质量。
- -crf: 设置恒定速率因子(用于x264编码)。
字幕和文字水印
-
- -subtitles: 添加字幕文件。
- -vf "drawtext=": 添加文字水印。(drawtext: 用于在视频上绘制文本水印。可以设置文本内容、字体、大小、颜色和位置等。)
输出文件控制
-
- -map: 选择输入流的特定流。
- -map_metadata: 复制流元数据。
- -metadata: 设置输出文件的元数据。
高级选项
-
- -threads: 设置线程数(用于多线程编码)。
- -strict: 严格模式,限制一些非标准的编码特性。
- -pix_fmt: 设置像素格式。
日志和调试
-
- -loglevel: 设置日志级别。
- -report: 在发生错误时生成报告。
给视频添加水印
总结以下给视频添加水印的流程就是先开启另一个进程,然后进行命令行操作
-
下载ffmpeg.exe
文件资源:Builds - CODEX FFMPEG @ gyan.dev
(一般建议下载最新的)
-
安装ffmpeg
首先下载ffmpeg的windows版本https://ffmpeg.zeranoe.com/builds/
解压下载的压缩包得到
进入bin目录并获取路径
在此电脑界面下右击选择属性
选择高级系统设置
选择环境变量
在用户环境变量双击path
选择新建(注意不要更改其他环境变量)
将刚才的bin路径粘贴进去
记得点下方的确定,再关闭当前窗口再点确定以保存
到这里,ffmpeg的配置就差不多了,调用命令行(windows+R输入cmd)输入“ffmpeg –version”,如果出现如下说明配置成功
参考博客Windows安装配置ffmpeg_wondows ffmpeg-CSDN博客
-
代码实现
添加文字水印
public static void Run(string cmd)
{
try
{
string ffmpeg = Option.MyOption.Option.WwwRootPath + Utility.Option.MyOption.Option.LiveProcessFileName;//FFmpeg可执行文件的完整路径
ProcessStartInfo startInfo = new ProcessStartInfo(ffmpeg);//用于指定启动进程时的信息,如进程的启动程序和启动参数.将FFmpeg可执行文件的路径作为启动程序
startInfo.UseShellExecute = false;//表示不使用操作系统 shell 来启动进程
startInfo.CreateNoWindow = true;//启动进程时不会创建窗口
startInfo.WindowStyle = ProcessWindowStyle.Hidden;//如果进程确实创建了窗口,那么这个窗口会被隐藏
startInfo.Arguments = cmd;//设置启动进程时传递给进程的参数
Process process = Process.Start(startInfo);//开始进程
process.WaitForExit(3000);//等待进程在指定的毫秒数(在这种情况下是3000毫秒,即3秒)内正常退出。如果在超时时间内进程没有退出,程序将继续执行
process.Kill();//强制结束进程
}
catch { }
}
/// <summary>
/// 添加文字水印
/// </summary>
/// <param name="videoPath">视频路径</param>
/// <param name="outPath">输出路径</param>
/// <param name="textMark">水印属性</param>
/// <param name="text">水印属性</param>
public static void AddTextMark(string videoPath, string outPath, string text)
{
if (!File.Exists(videoPath))
{
throw new E.FailException("视频不存在");
}
TextMark textMark = new TextMark
{
Text = text,
FontColor = Color.Red,
FontFile = "simsun.ttc",
FontSize = 30,
X = 20,
Y = 500
};
Run(string.Format(" -i {0} -vf \"drawtext=fontfile={1}: text='{2}':x={3}:y={4}:fontsize={5}:fontcolor={6}\" {7}", videoPath, textMark.FontFile, textMark.Text, textMark.X, textMark.Y, textMark.FontSize, textMark.FontColor.Name.ToLower(), outPath));
//@"%{localtime\:%Y\-%m\-%d %H-%M-%S}"
}
public class TextMark
{
public string Text { get; set; }
public Color FontColor { get; set; }
public string FontFile { get; set; }
public int FontSize { get; set; }
public int X { get; set; }
public int Y { get; set; }
}
原视频
添加水印后
解释一下命令:
Run(string.Format(" -i {0} -vf "drawtext=fontfile={1}: text='{2}':x={3}:y={4}:fontsize={5}:fontcolor={6}" {7}", videoPath, textMark.FontFile, textMark.Text, textMark.X, textMark.Y, textMark.FontSize, textMark.FontColor.Name.ToLower(), outPath));
- -i {0}:
- -i:FFmpeg命令行参数,用于指定输入视频文件。
- {0}:占位符,将被videoPath变量的值替换。videoPath是我们要处理的视频文件的路径。
- -vf "drawtext=fontfile={1}:text='{2}':x={3}:y={4}:fontsize={5}:fontcolor={6}":
- -vf:FFmpeg命令行参数,用于添加视频滤镜。
- drawtext:视频滤镜的名称,用于在视频上绘制文本水印。
- fontfile={1}:指定字体文件。{1}是占位符,将被textMark.FontFile变量的值替换。textMark.FontFile应该是字体文件的路径。
- text='{2}':指定要绘制的文本。{2}是占位符,将被textMark.Text变量的值替换。textMark.Text是要显示为水印的文本。
- x={3}:指定文本在视频中的水平位置。{3}是占位符,将被textMark.X变量的值替换。textMark.X是文本的X坐标。
- y={4}:指定文本在视频中的垂直位置。{4}是占位符,将被textMark.Y变量的值替换。textMark.Y是文本的Y坐标。
- fontsize={5}:指定字体大小。{5}是占位符,将被textMark.FontSize变量的值替换。textMark.FontSize是字体的大小。
- fontcolor={6}:指定字体颜色。{6}是占位符,将被textMark.FontColor.Name.ToLower()变量的值替换。textMark.FontColor是字体颜色,Name.ToLower()将其转换为大写。
- {7}:输出文件的路径。{7}是占位符,将被outPath变量的值替换。outPath应该是处理后的视频文件的保存路径。
(下面我是用cmd的方式来验证了代码的可行性的,伙伴们可以参考一下)
在ffmpeg可执行目录下运行cmd,注意在命令行中使用ffmpeg命令是需要在前面加“ffmpeg”的。
添加图片水印
public static void Run(string cmd)
{
try
{
string ffmpeg = Option.MyOption.Option.WwwRootPath + Utility.Option.MyOption.Option.LiveProcessFileName;//FFmpeg可执行文件的完整路径
ProcessStartInfo startInfo = new ProcessStartInfo(ffmpeg);//用于指定启动进程时的信息,如进程的启动程序和启动参数.将FFmpeg可执行文件的路径作为启动程序
startInfo.UseShellExecute = false;//表示不使用操作系统 shell 来启动进程
startInfo.CreateNoWindow = true;//启动进程时不会创建窗口
startInfo.WindowStyle = ProcessWindowStyle.Hidden;//如果进程确实创建了窗口,那么这个窗口会被隐藏
startInfo.Arguments = cmd;//设置启动进程时传递给进程的参数
Process process = Process.Start(startInfo);//开始进程
process.WaitForExit(3000);//等待进程在指定的毫秒数(在这种情况下是3000毫秒,即3秒)内正常退出。如果在超时时间内进程没有退出,程序将继续执行
process.Kill();//强制结束进程
}
catch { }
}
/// <summary>
/// 添加图片水印
/// </summary>
/// <param name="videoPath"></param>
/// <param name="outPath"></param>
/// <param name="listImg"></param>
public static void AddImageMark(string videoPath, string outPath)
{
if (!File.Exists(videoPath))
throw new E.FailException("未选择视频");
ImgMark img = new ImgMark()
{
ImgPath = @"D:\Darlin\file\123.png",
Postion = new Point(60, 60)
};
Run(string.Format("-i {0} -i {1} -filter_complex \" overlay={2}:{3}\" {4}", videoPath, img.ImgPath, img.Postion, outPath));
}
/// <summary>
/// 批量添加图片水印
/// </summary>
/// <param name="videoPath"></param>
/// <param name="outPath"></param>
/// <param name="listImg"></param>
public static void AddImageListMark(string videoPath, string outPath)
{
if (!File.Exists(videoPath))
throw new E.FailException("未选择视频");
List<ImgMark> listImg = new List<ImgMark>
{
new ImgMark
{
ImgPath=@"C:\Users\Zero\Desktop\a\\1.png",
Postion=new Point(60,60)
},
new ImgMark
{
ImgPath=@"C:\Users\Zero\Desktop\a\\1.png",
Postion=new Point(60,200)
}
//......
};
string imgs = "", postions = "";
foreach (ImgMark mark in listImg)
{
imgs += " -i " + mark.ImgPath;
postions += "overlay=" + mark.Postion.X + ":" + mark.Postion.Y + ",";
}
postions = postions.Remove(postions.Length - 1);
Run(string.Format("-i {0}{1} -filter_complex \"{2}\" {3}", videoPath, imgs, postions, outPath));
}
public class ImgMark
{
public string ImgPath { get; set; }
public Point Postion { get; set; }
public string FontFile { get; set; }
public int FontSize { get; set; }
}
原视频
添加水印后
解释一下命令:
Run(string.Format("-i {0} -i {1} -filter_complex " overlay={2}:{3}" {4}", videoPath, img.ImgPath, img.Postion, outPath));
- -i {0} -i {1}:
- -i:FFmpeg命令行参数,用于指定输入视频文件。
- {0}:占位符,将被videoPath变量的值替换。videoPath应该是你要处理的视频文件的路径。
- {1}:占位符,将被img.ImgPath变量的值替换。img.ImgPath应该是你要用作水印的图像文件的路径。
- -filter_complex \" overlay={2}:{3}\":
- -filter_complex:FFmpeg命令行参数,用于添加一个复杂的过滤器链。
- overlay:FFmpeg过滤器,用于在视频上叠加图像。
- {2}:占位符,将被img.Postion变量的值替换。img.Postion应该是图像水印在视频中的位置,格式为X:Y,其中X是水平位置,Y是垂直位置。
- {3}:占位符,将被outPath变量的值替换。outPath应该是处理后的视频文件的保存路径。
- {4}:输出文件的路径。{4}是占位符,将被outPath变量的值替换。outPath应该是处理后的视频文件的保存路径。
以下是用流实现的,也可看一下(实话说是我偷偷抄来的)
原文链接:C# 视频添加水印_c# 视频加水印-CSDN博客
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
//string fileName = "E:\\BaiduNetdiskDownload\\下午06-图标字体回顾.web_recv.avi";
string imgFile = "E:\\BaiduNetdiskDownload\\true.png";
//string outputFile = "E:\\BaiduNetdiskDownload\\outputFile.avi";
//int a=WaterMark(fileName, imgFile, outputFile);
//Console.WriteLine(a);
//Console.ReadKey();
string outputFile = "E:\\BaiduNetdiskDownload\\b.mp4";
string fileName = "E:\\BaiduNetdiskDownload\\a.mp4";
//string mingling = "-i "+fileName+" -y -b 1024k -acodec copy -f mp4 "+ outputFile;
string mingling = "-i "+ fileName + " -i "+imgFile+" -filter_complex \"overlay=10:10\" "+outputFile;
string b = RunProcess(mingling);
Console.WriteLine(b);
Console.ReadKey();
}
public static int WaterMark(string fileName, string imgFile, string outputFile)
{
//取得ffmpeg.exe的路径,路径配置在Web.Config中,如:<add key="ffmpeg" value="E:\aspx1\ffmpeg.exe" />
fileName = "E:\\BaiduNetdiskDownload\\下午06-图标字体回顾.web_recv.avi";
imgFile = "E:\\BaiduNetdiskDownload\\true.png";
outputFile = "E:\\BaiduNetdiskDownload\\outputFile.avi";
string ffmpeg = "C:\\Users\\Administrator\\Downloads\\ffmpeg-2021-04-25-git-d98884be41-full_build\\ffmpeg-2021-04-25-git-d98884be41-full_build\\bin\\ffmpeg.exe";
if ((!System.IO.File.Exists(ffmpeg)) || (!System.IO.File.Exists(fileName)))
{
return 0;
}
//建立ffmpeg进程
System.Diagnostics.ProcessStartInfo WaterMarkstartInfo = new System.Diagnostics.ProcessStartInfo(ffmpeg);
//后台运行
WaterMarkstartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
//运行参数
string config = " -i " + fileName + " -vf \"movie=" + imgFile + " [watermark]; [in][watermark] overlay=0:0 [out]\" " + outputFile;
WaterMarkstartInfo.Arguments = config;
try
{
//开始加水印
System.Diagnostics.Process.Start(WaterMarkstartInfo);
}
catch
{
return 0;
}
return 1;
}
//添加水印,fileName视频地址,imgFile水印图片地址,outputFile输出地址
/// <summary>
/// 视频处理器ffmpeg.exe的位置
/// </summary>
public string FFmpegPath { get; set; }
/// <summary>
/// 调用ffmpeg.exe 执行命令
/// </summary>
/// <param name="Parameters">命令参数</param>
/// <returns>返回执行结果</returns>
private static string RunProcess(string Parameters)
{
string FFmpegPath = "C:\\Users\\Administrator\\Downloads\\ffmpeg-2021-04-25-git-d98884be41-full_build\\ffmpeg-2021-04-25-git-d98884be41-full_build\\bin\\ffmpeg.exe";
//创建一个ProcessStartInfo对象 并设置相关属性
var oInfo = new ProcessStartInfo(FFmpegPath, Parameters);
oInfo.UseShellExecute = false;
oInfo.CreateNoWindow = true;
oInfo.RedirectStandardOutput = true;
oInfo.RedirectStandardError = true;
oInfo.RedirectStandardInput = true;
//创建一个字符串和StreamReader 用来获取处理结果
string output = null;
StreamReader srOutput = null;
try
{
//调用ffmpeg开始处理命令
var proc = Process.Start(oInfo);
proc.WaitForExit();
//获取输出流
srOutput = proc.StandardError;
//转换成string
output = srOutput.ReadToEnd();
//关闭处理程序
proc.Close();
}
catch (Exception)
{
output = string.Empty;
}
finally
{
//释放资源
if (srOutput != null)
{
srOutput.Close();
srOutput.Dispose();
}
}
return output;
}
}
}
原视频
水印图
效果图
完结