C#实现为视频添加水印
作者:Csharp小记 发布时间:2022-02-16 05:30:07
标签:C#,视频,水印
文章描述
以下主要还是使用到了ffmpeg命令,分别实现了给视频添加图片水印以及文字水印。
开发环境
.NET Framework版本:4.5
开发工具
Visual Studio 2013
实现代码
public static void Run(string cmd)
{
try
{
string ffmpeg = AppDomain.CurrentDomain.BaseDirectory + "ffmpeg.exe";
ProcessStartInfo startInfo = new ProcessStartInfo(ffmpeg);
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = cmd;
Process process = Process.Start(startInfo);
process.WaitForExit(3000);
process.Kill();
}
catch { }
}
/// <summary>
/// 按时间获取某帧图片
/// </summary>
/// <param name="videoPath">视频路径</param>
/// <param name="outPath">输出路径</param>
/// <param name="frameTime">时间(格式:00:00:01)</param>
public static void GetFrame(string videoPath, string outPath, string frameTime)
{
Run(string.Format("-ss 00:00:01 -i {1} {2}", frameTime, videoPath, outPath));
}
/// <summary>
/// 批量添加图片水印
/// </summary>
/// <param name="videoPath"></param>
/// <param name="outPath"></param>
/// <param name="listImg"></param>
public static void AddImageMark(string videoPath, string outPath, List<ImgMark> listImg)
{
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));
}
/// <summary>
/// 添加文字水印
/// </summary>
/// <param name="videoPath">视频路径</param>
/// <param name="outPath">输出路径</param>
/// <param name="textMark">水印属性</param>
public static void AddTextMark(string videoPath, string outPath, TextMark textMark)
{
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}"
}
private void btn_select_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "视频|*.mp4;*.avi";
ofd.Title = "请选择视频文件";
ofd.InitialDirectory = Application.StartupPath;
if (ofd.ShowDialog() == DialogResult.OK)
{
axWindowsMediaPlayer1.URL = ofd.FileName;
}
}
private void btn_text_Click(object sender, EventArgs e)
{
if (!File.Exists(axWindowsMediaPlayer1.URL))
{
MessageBox.Show("未选择视频");
return;
}
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "视频|*.mp4";
sfd.AddExtension = true;
if (sfd.ShowDialog() == DialogResult.OK)
{
TextMark mark = new TextMark
{
Text = "这里是水印",
FontColor = Color.Red,
FontFile = "simsun.ttc",
FontSize = 100,
X = 80,
Y = 60
};
FFmpegUtil.AddTextMark(axWindowsMediaPlayer1.URL, sfd.FileName, mark);
axWindowsMediaPlayer2.URL = sfd.FileName;
}
}
private void btn_img_Click(object sender, EventArgs e)
{
if (!File.Exists(axWindowsMediaPlayer1.URL))
{
MessageBox.Show("未选择视频");
return;
}
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "视频|*.mp4";
sfd.AddExtension = true;
if (sfd.ShowDialog() == DialogResult.OK)
{
FFmpegUtil.AddImageMark(axWindowsMediaPlayer1.URL, sfd.FileName, 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)}});
axWindowsMediaPlayer2.URL = sfd.FileName;
}
}
实现效果
代码解析:着重介绍下添加文字水印的,由于很多时候我们需要添加的是中文,所以需要将字体包先放入到ffmepg的同级目录,然后指定该字体。
来源:https://mp.weixin.qq.com/s/g6Rx7mnIK4rhJxmZS3gX5A


猜你喜欢
- 前提:你的电脑是AMD处理器,想使用Android studio,自己的电脑系统是win10家庭版,在百度找到勾选hyper-v就能用,然后
- 一、身份证结构和形式在通用的身份证号码有15位的和18位的;15位身份证号码各位的含义:1、1-2位省、自治区、直辖市代码;2、3-4位地级
- 目录常用APIgeoaddgeoposgeodistgeoradiusbymembergeohash在外卖软件中的附近的美食店铺、外卖小哥的
- 前言在数据库连接池分析的代码实例中,看到其中使用Enumeration来遍历Vector集合。后来就找了一些资料查看都有哪些方法可以遍历集合
- 这篇文章主要介绍了springboot2.0如何通过fastdfs实现文件分布式上传,文中通过示例代码介绍的非常详细,对大家的学习或者工作具
- 1. 原因最近学习spring data JPA 时候要用到分页功能,但是发现网上所有教程都是通过new PageRequest()方法解决
- IO感觉上和多线程并没有多大关系,但是NIO改变了线程在应用层面使用的方式,也解决了一些实际的困难。而AIO是异步IO和前面的系列也有点关系
- 前言:本文主要讲解以c语言编写猜数字游戏,目的是介绍C语言中的循环和分支的具体用法。一:猜数字游戏基本介绍&对程序预期.猜数字游戏,
- 概述在 Linux 平台下使用搜狗输入法在 IDEA 中输入中文时,输入法候选框总是静止在 IDEA 的左下角,而不能跟随光标进行移动。虽然
- 一、饿汉式(静态常量)public class Face { private stat
- 首先描述一下问题,spring boot 使用的是内嵌的tomcat, 所以不清楚文件上传到哪里去了, 而且spring boot 把静态的
- SpringBoot集成Freemarker主要特征:静态页面,无接 * 互数据实时性不高且体量小的网站可采用生成静态html的形式数据提前渲
- 不记得从哪找的了,修改了部分代码,修复在Android平台下使用时,时区时间格式异常的问题。package cn.aikongmeng.de
- 1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,
- String password = RandomUtil.generateString(10);源码如下:package com.javan
- 本文以实例形式讲述了基于Java的图的广度优先遍历算法实现方法,具体方法如下:用邻接矩阵存储图方法:1.确定图的顶点个数和边的个数2.输入顶
- thinking in java3中的多态People are often confused by other, non-object-or
- 本文实例讲述了Java后台线程操作。分享给大家供大家参考,具体如下:一 点睛有一种线程,它是后面运行的,它的任务是为其他线程提供服务,这种线
- 1.最近的项目中,有一个Activity用到Fragment+ViewPager,其中一个fragment中实现了视频播放的功能,包含有Su
- 为什么要使用路由在之前我们的代码中,页面跳转使用的代码如下所示:Navigator.of(context).push( Mate