ffmpeg.exe是大名鼎鼎的视频处理软件,以命令行参数形式运行。网上也有很多关于ffmpeg的资料介绍。但是在用C#做实际开发时,却遇到了几个问题及注意事项,比如如何无损处理视频?如何在转换格式的同时添加水印,以提升处理效率?,ffmpeg的版本应该选择什么版本?。今天史林峰将用实战的方式来探索C#操作ffmpeg的奥秘。

关于ffmpeg的使用及其参数命令,这里就不做过多介绍了。主要以项目实战中为主。

因工作需要,笔者手头有近300部短视频需要处理,在网上找了不少工具,虽然能用,但是用起来却有一种Hold不住的感觉。要么是处理后有软件水印或片花,要么是不能直接批量一次性处理完,视频要一个一个地去设置。

这里主要需求是给现有的视频做格式转换,如果视频格式已经满足要求,就直接在指定位置加水印(png图片),在处理完之后,为了解决磁盘空间,在视频处理完成之后要删除原视频。笔者对C#语言是最熟知的,因此选用C# Winform做一个简易的视频批处理软件。

先上一张完工的项目截图:

在指定目录中读取视频,然后一件处理即可(中间的截取秒数的参数,属于视频剪切,暂时没有这块功能)

现有的视频均为flv格式的,通过C#调用ffmpeg,转换为mp4格式,并添加水印

C#调用ffmpeg的方法封装如下:

 /// <summary>
/// 视频处理器ffmpeg.exe的位置
/// </summary>
public string FFmpegPath { get; set; }
 
/// <summary>
/// 调用ffmpeg.exe 执行命令
/// </summary>
/// <param name="Parameters">命令参数</param>
/// <returns>返回执行结果</returns>
private string RunProcess(string Parameters)
{
//创建一个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;
}

转换格式的命令参数:-i orignal.flv -y -b 1024k -acodec copy -f mp4 newFile.mp4

添加水印的命令参数:-i orignal.flv -i water.png -filter_complex \"overlay=10:10\" newFile.flv

参数简要说明和细节提示:

orignal.flv : 要处理的原始视频文件(最好是绝对路径)
-y : 覆盖已有文件(注意,加水印不可覆盖原始文件,否则只能生成1秒的视频)
-b:视频的码率 这里设置1024k 基本可满足无损处理 如不设置-b参数则默认为200k 视频会非常模糊
-acodec copy : 保持音频质量不变
-f mp4 : 表示转换的视频格式
 
-i water.png : 水印图片路径
overlay=10:10 : 水印距离视频的左上角坐标
其他位置参数:
右上角:main_w-overlay_w-10:10
左下角:10:main_h-overlay_h-10
右下角:main_w-overlay_w-10:main_h-overlay_h-10
 
newFile.mp4  要保存的文件路径

上面这个方法就是核心处理。笔者在实际执行的过程中,发现了以下问题:

  在使用cmd窗口执行以上命令时(cmd中参数前面要加 ffmpeg 注意文件位置),可以成功处理,但在运行Winform测试的时候,发现只有一个大小为0kb的新文件生成,但迟迟不见处理。给人一种假死的现象。而当笔者关掉调试的Winform程序时,过几秒钟,貌似ffmpeg.exe 又起作用了,文件处理成功了。这个不得其解。(在调用处理程序时,新开了一个线程执行的)

排查情况:

  可能是ffmpeg的版本问题,于是下载了2.8.2版本(应该是最新的),测试,没有任何变化

  检查程序的调用流程,将调用过程cmd窗口显示出来。结果一片空白,什么也没有,依然是没有效果。

最后在经过各种资料的查找之后,在不经意间看到有人说 proc.WaitForExit(); 这句执行会造成程序一直处于等待状态。是的,没错,以前做类似程序调用也是这样做的,也没出现过这种问题。于是,抱着试试看的态度,注释了这一句。当然,程序不再等待执行完毕,proc.Close(); 这一句也要注释一下。测试结果成功!!(懂得底层原理的大牛,望告知一二)

问题解决了,但是还有一个处理效率的问题:如何更快的处理?

笔者尝试了各种命令的组合,发现对于不同版本的ffmpeg,有的参数是不能使用的,就笔者使用的2.8.2版本最终 找了一个比较好的解决方案:

可以选择使用以下命令参数:

-i orignal.flv -i water.png -filter_complex \"overlay=10:10\" -y -b 1024k -acodec copy -f mp4

-i orignal.flv -i water.png -filter_complex \"overlay=10:10\" -b 1024k -acodec copy

上面一个适合同时转换格式和加水印

下面一个适合只加水印,不做格式转换

这些核心问题解决了,剩下的就是文件的读取,保存,判断等等细节了。

总结:

  1. C#调用ffmpeg时 不要使用proc.WaitForExit();方法,否则会假死

  2. ffmpeg的版本最好使用最新版本,并参考命令参数说明

  3. 无损转换,无损加水印 要注意保证视频的码率 和音频的参数(直接copy,视频不能这样写-avcodec copy  会报错,只能用-b设置视频码率)

  4. 一步到位的处理方法(转换的同时加水印,参考上面的命令参数)

程序开发好之后,笔者不用再苦逼地一个一个去设置,处理了,电脑开着,显示器关闭,只听见主机嗷嗷叫的处理,等吃完饭,所有事情均已搞定。。。

史林枫:C#.NET利用ffmpeg操作视频实战(格式转换,加水印 一步到位)的更多相关文章

  1. FFmpeg(10)-利用FFmpeg进行视频像素格式和尺寸的转换(sws_getCachedContext(), sws_scale())

    一.包含头文件和库文件 像素格式的相关函数包含在 libswscale.so 库中,CMakeLists需要做下列改动: # swscale add_library(swscale SHARED IM ...

  2. 史林枫:开源HtmlAgilityPack公共小类库封装 - 网页采集(爬虫)辅助解析利器【附源码+可视化工具推荐】

    做开发的,可能都做过信息采集相关的程序,史林枫也经常做一些数据采集或某些网站的业务办理自动化操作软件. 获取目标网页的信息很简单,使用网络编程,利用HttpWebResponse.HttpWebReq ...

  3. 利用FFmpeg生成视频缩略图 2.1.6

    利用FFmpeg生成视频缩略图 1.下载FFmpeg文件包,解压包里的\bin\下的文件解压到 D:\ffmpeg\ 目录下. 下载地址 http://ffmpeg.zeranoe.com/build ...

  4. C# ffmpeg 视频处理格式转换具体案例

    C# ffmpeg 视频处理格式转换 C# ffmpeg 视频处理格式转换avi到MP4格式 1.代码如下: using System;using System.Diagnostics; namesp ...

  5. C# 利用ffmpeg 对视频转换系类操作 (1) 基本分析

    最近公司做一个项目,开发一个视频站点.项目需求中有很多视频转换的需求,如:格式转换(flv,Mp4),视频水印,视频截图,视频合成,获取视频的基本信息(时间戳,视频大小等).经过网络的收集资料以及自己 ...

  6. 利用FFmpeg生成视频的缩略视频 v8.3

    目前生成视频缩略图的工具大多数是生成静态的图片,为了解决这样的局限性,这 次春节期间搞了个利用 FFMpeg 能生成缩略动态视频的批处理. 把 Make_NxM_videos.bat LED_font ...

  7. 基于C#利用ffmpeg提取视频帧

    利用ffmepg提取视频帧实际上是利用C#调用ffmepg命令行进行处理对应的视频,然后输出出视频帧 GetPicFromVideo("); static public string Get ...

  8. C# ffmpeg 视频处理格式转换和添加水印

    通过C#调用ffmpeg 将flv格式转换为mp4格式,并添加水印 C#调用ffmpeg的方法封装如下: /// <summary>/// 视频处理器ffmpeg.exe的位置/// &l ...

  9. 史林枫:sqlserver数据库中数据日志的压缩及sqlserver占用内存管理设置

    使用sqlserver和IIS开发.net B/S程序时,数据量逐渐增多,用户也逐渐增多,那么服务器的稳定性就需要维护了.数据库如何占用更小内存,无用的日志如何瞬间清空? 今天在给一个客户维护网站的时 ...

随机推荐

  1. 外网访问FTP服务,解决只能以POST模式访问Filezilla的问题

    在内网可以正常使用PASV,但是在外网不行,导致数据传输慢或者根本连接不了,在FlashFXP中通过日志,找到了解决方法解决方法1.在Filezilla——Edit——Settings——Passiv ...

  2. java设计模式——建造者模式

    一. 定义与类型 定义:将一个复杂对象的构建与它的表示分离,使用同样的构建过程可以创建不同的表示 用户只需制定需要建造的类型就可以得到它们,建造过程以及细节不需要知道 类型:创建型 建造者模式与工厂模 ...

  3. Echarts样式

    Echarts设置样式如下 <div id="main" style="width: 250px;height:200px;"></div&g ...

  4. git系列讲解

    1.git是什么呢?维基百科给出的定义: git是一个分布式版本控制软件,最初由(Linus Torvalds)创作 什么是版本控制?项目经理与程序员的恩怨情仇企业真实案例:开发了a功能,之后项目所要 ...

  5. es6中的模版字符串

    目录 字符串拼接 includes() startsWith() endsWith() padStart() es6中的模版字符串替代了原有的字符串拼接功能. 字符串拼接 es5方式 传统的字符串拼接 ...

  6. GNU C中__attribute__

    __attribute__基本介绍: 1. __attribute__ 可以设置函数属性.变量属性和类型属性. 2. __attribute__ 语法格式为:__attribute__ ((attri ...

  7. C/C++程序基础 (二)常用知识点

    使用宏实现max 注意括号在宏内的使用 #define MAX(x, y) ( ( (x) > (y) ) ? (x) : (y) ) 宏参数连接 a##e##b 转化为字符串 #a const ...

  8. 初学python来进行odoo12版本开发

    这是我的第一篇博客.请多多指教! 首先要下载odoo-12的源代码 官方下载路径:          https://github.com/odoo/odoo/archive/12.0.zip 随便新 ...

  9. 4、python中的布尔值和None

    一.布尔值 1.布尔值只有两个:True.Flase,表示python语句的真与假: 2.在python早期的版本,布尔值用1和0表示. 二.None 1.None表示虚无,什么也没有: 2.千万不要 ...

  10. Docker背后的内核知识(一)

    Docker背后的内核知识 当谈论Docker时,常常会聊到Docker的实现方式.很多开发者都知道,Docker容器本质上是宿主机上的进程.Docker通过namespace实现了资源隔离.通过cg ...