c#中给视频添加水印(文字水印和图片水印)

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;
        }
    }
    


}

原视频

水印图

效果图

完结

  • 25
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以使用C#的GDI+库来给图片添加水印效果。以下是一个简单的示例代码: ```csharp using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; public static Image AddWatermark(Image image, string watermarkText, Font font, Color color, float opacity, PointF position) { // 创建一个与原图相同大小的Bitmap对象 Bitmap bitmap = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb); // 创建一个Graphics对象,用于绘制水印 using (Graphics graphics = Graphics.FromImage(bitmap)) { // 将Graphics对象的渲染质量设置为高质量 graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.CompositingQuality = CompositingQuality.HighQuality; // 绘制原图 graphics.DrawImage(image, new Rectangle(0, 0, bitmap.Width, bitmap.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel); // 创建一个Brush对象,用于绘制水印文字 Brush brush = new SolidBrush(Color.FromArgb((int)(opacity * 255), color)); // 绘制水印文字 graphics.DrawString(watermarkText, font, brush, position); // 释放Brush对象 brush.Dispose(); } // 返回添加水印后的图片 return bitmap; } ``` 以上代码,`AddWatermark`方法接受以下参数: - `image`:要添加水印图片。 - `watermarkText`:要添加水印文字。 - `font`:水印文字的字体。 - `color`:水印文字的颜色。 - `opacity`:水印文字的不透明度,取值范围为0-1。 - `position`:水印文字的位置。 使用示例: ```csharp Image image = Image.FromFile("sample.jpg"); Font font = new Font("Arial", 24); Color color = Color.White; float opacity = 0.5f; PointF position = new PointF(10, 10); Image newImage = AddWatermark(image, "Sample Watermark", font, color, opacity, position); newImage.Save("sample-with-watermark.jpg", ImageFormat.Jpeg); ``` 以上示例,我们从文件载了一张名为`sample.jpg`的图片,然后使用`AddWatermark`方法添加了一个水印,最后将添加水印后的图片保存为`sample-with-watermark.jpg`。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值