C#调用FFmpeg操作音视频的实现示例
作者:追逐时光者 发布时间:2021-10-08 12:40:00
项目背景
因为公司需要对音视频做一些操作,比如说对系统用户的发音和背景视频进行合成,以及对多个音视频之间进行合成,还有就是在指定的源背景音频中按照对应的规则在视频的多少秒钟内插入一段客户发音等一些复杂的音视频操作。本篇文章主要讲解的是使用C#进程(Process)调用FFmpeg.exe进行视频合并,音频合并,音频与视频合并成视频这几个简单的音视频操作,还有些复杂的音视频操作后续有时间慢慢补上。
FFmpeg介绍
来源百度百科👉
FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多code都是从头开发的。
FFmpeg在Linux平台下开发,但它同样也可以在其它操作系统环境中编译运行,包括Windows、Mac等多平台。这个项目最早由Fabrice Bellard发起,2004年至2015年间由Michael Niedermayer主要负责维护。许多FFmpeg的开发人员都来自MPlayer项目,而且当前FFmpeg也是放在MPlayer项目组的服务器上。项目的名称来自MPEG视频编码标准,前面的"FF"代表"Fast Forward"。 FFmpeg编码库可以使用GPU加速。
FFmpeg相关教程
开始之初你首先要了解FFmpeg是什么,有哪些常用的命令和实用的功能。
FFmpeg官网文档
FFmpeg最全教程
FFmpeg 视频处理入门教程
FFMPEG命令入门到提高,一篇文章就够了
博客示例源码
https://github.com/YSGStudyHards/FFmpegAudioAndVideoMerge
下载FFmpeg.exe安装包
首先把下载下来的FFmpeg.exe放在你指定的目录文件夹中,方便C#进程调用。
ffmpeg.exe 安装包: https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip(74MB)
C#进程调用FFmpeg操作音视频
namespace FFmpegAudioAndVideoMerge
{
class Program
{
static void Main(string[] args)
{
var physicalPath = "E:\\FFmpegAudioAndVideoMerge\\FFmpegAudioAndVideoMerge\\files\\";
//视频合并
VideoCombine(physicalPath + "video1.mp4", physicalPath + "video2.mp4", physicalPath + "merageVideoyy.mp4");
//音频合并
var audioMergeList = new List<string>();
audioMergeList.Add(physicalPath + "music1.mp3");
audioMergeList.Add(physicalPath + "music2.mp3");
audioMergeList.Add(physicalPath + "music3.mp3");
AudioMerge(physicalPath, audioMergeList);
//音频与视频合并成视频
AudioAndVideoMerge(physicalPath);
}
#region 视频合并
/// <summary>
/// 视频合并
/// </summary>
/// <param name="video1">合并视频1</param>
/// <param name="video2">合并视频2</param>
/// <param name="saveFilePath">保存文件名</param>
/// <returns></returns>
public static void VideoCombine(string video1, string video2, string saveFilePath)
{
string strTmp1 = video1 + ".ts";
string strTmp2 = video2 + ".ts";
string strCmd1 = " -i " + video1 + " -c copy -bsf:v h264_mp4toannexb -f mpegts " + strTmp1 + " -y ";
string strCmd2 = " -i " + video2 + " -c copy -bsf:v h264_mp4toannexb -f mpegts " + strTmp2 + " -y ";
string videoMerge = " -i \"concat:" + strTmp1 + "|" +
strTmp2 + "\" -c copy -bsf:a aac_adtstoasc -movflags +faststart " + saveFilePath + " -y ";
//1、转换文件类型,由于不是所有类型的视频文件都支持直接合并,需要先转换格式
CommandManager(strCmd1);
CommandManager(strCmd2);
//2、视频合并
CommandManager(videoMerge);
}
#endregion
#region 音频合并
/// <summary>
/// 音频合并
/// </summary>
public static void AudioMerge(string physicalPath, List<string> mergeFile)
{
//将多个音频混合成一个音频文件输出 http://www.ffmpeg.org/ffmpeg-all.html#amix
//ffmpeg -i INPUT1 -i INPUT2 -i INPUT3 -filter_complex amix=inputs=3:duration=first:dropout_transition=3 OUTPUT
//合并两个音频
//ffmpeg -i input1.mp3 -i input2.mp3 -filter_complex amerge -ac 2 - c:a libmp3lame -q:a 4 output.mp3
//获取视频中的音频
//ffmpeg -i input.mp4 -vn -y -acodec copy output.m4a
//去掉视频中的音频
//ffmpeg -i input.mp4 -an output.mp4
// https://www.cnblogs.com/simadi/p/10649345.html
// ffmpeg -i "concat:123.mp3|124.mp3" -acodec copy output.mp3
// 解释:-i代表输入参数
// contact: 123.mp3 | 124.mp3代表着需要连接到一起的音频文件 -acodec copy output.mp3 重新编码并复制到新文件中
string mergeCommandStr = $"-i \"concat:{string.Join("|", mergeFile.ToArray())}\" -acodec copy {physicalPath}AudioMerge.mp3 -y";
CommandManager(mergeCommandStr);
}
#endregion
#region 音频与视频合并成视频
/// <summary>
/// 音频与视频合并成视频
/// </summary>
/// <param name="physicalPath">物理路径</param>
public static void AudioAndVideoMerge(string physicalPath)
{
//1、视频文件中没有音频。
//ffmpeg -i video.mp4 -i audio.wav -c:v copy -c:a aac -strict experimental output.mp4
//string mergeCommandStr = $"-i {physicalPath}video2.mp4 -i {physicalPath}music1.mp3 -c:v copy -c:a aac -strict experimental {physicalPath}output.mp4 -y";
//video.mp4,audio.wav分别是要合并的视频和音频,output.mp4是合并后输出的音视频文件。
//2、下面的命令是用audio音频替换video中的音频 ffmpeg -i video.mp4 -i audio.wav -c:v copy -c:a aac -strict experimental -map 0:v:0 -map 1:a: 0 output.mp4
string mergeCommandStr = $"-i {physicalPath}video3.mp4 -i {physicalPath}AudioMerge.mp3 -c:v copy -c:a aac -strict experimental -map 0:v:0 -map 1:a:0 {physicalPath}AudioAndVideoMerge.mp4 -y";
//3、c++音频视频合并(视频文件中没有音频的情况下)
//"ffmpeg -i /tmp/mergeMp3/392118469203595327/392118469203595327.aac -i /tmp/mergeMp3/392118469203595327/bg.mp4 -c copy -bsf:a aac_adtstoasc /tmp/mergeMp3/392118469203595327/392118469203595327.mp4 -y"
//string mergeCommandStr3 = $"-i {physicalPath}video5.mp4 -i {physicalPath}AudioMerge.mp3 -c copy -bsf:a aac_adtstoasc {physicalPath}AudioAndVideoMerge1.mp4 -y";
CommandManager(mergeCommandStr);
}
#endregion
/// <summary>
/// 执行
/// C# Process进程调用 https://docs.microsoft.com/zh-cn/dotnet/api/system.diagnostics.process?view=net-5.0
/// </summary>
/// <param name="commandStr">执行命令</param>
public static void CommandManager(string commandStr)
{
try
{
using (Process process = new Process())
{
process.StartInfo.FileName = "D:\\FFmpeg\\bin\\ffmpeg.exe";//要执行的程序名称(属性,获取或设置要启动的应用程序或文档。FileName 属性不需要表示可执行文件。 它可以是其扩展名已经与系统上安装的应用程序关联的任何文件类型。)
process.StartInfo.Arguments = " " + commandStr;//启动该进程时传递的命令行参数
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = false;//可能接受来自调用程序的输入信息
process.StartInfo.RedirectStandardOutput = false;//由调用程序获取输出信息
process.StartInfo.RedirectStandardError = false;//重定向标准错误输出
process.StartInfo.CreateNoWindow = false;//不显示程序窗口
process.Start();//启动程序
process.WaitForExit();//等待程序执行完退出进程(避免进程占用文件或者是合成文件还未生成)*
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
来源:https://www.cnblogs.com/Can-daydayup/p/15780172.html
猜你喜欢
- 介绍了图的最小生成树的概念,然后介绍了求最小生成树的两种算法:Prim算法和Kruskal算法的原理,最后提供了基于邻接矩阵和邻接链表的图对
- Java设计模式访问者模式模式概念访问者模式表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这些元素的
- 实例如下:import java.util.concurrent.CountDownLatch;import java.util.concu
- 也许是本人不才,初识Maven时,被各种不明所以的教程搞得一头雾水,而在后来的使用中,我发现Maven大部分功能没有想象的那么困难。本片文章
- 前言在我们平时使用图形化界面的时候,会发现来建立一个文件夹或者一个文档的时候很简单,只需要在桌面单击鼠标右键就可以了。但是,在我们写项目的时
- Java连接SQLServer 2008数据库的步骤:1.到微软官方下载jdbc 并解压,得到sqljdbc.jar和sqljdbc4.ja
- springboot + docker + jenkins自动化部署项目,jenkins、mysql、redis都是docker运行的,并且
- package org.itat.stax;import java.io.IOException;import java.io.InputS
- 上篇介绍了几种图表的公共组件X、Y轴、背景Board的绘制。这章节介绍柱状图表的绘制,相对其它图表而言简单一些,这里主要介绍图表主体的绘制,
- 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是
- 本文实例为大家分享了unity实现场景跳转的具体代码,供大家参考,具体内容如下话不多说直接开始操作步骤。1.打开我们的unity创建一个工程
- 1. 前言ResultSetMetaData 叫元数据,是数据库 列对象,以列为单位封装为对象。元数据,指的是其包含列名,列值,列类型,列长
- 目前为止我们已经了解了如何通过编程创建 CompletableFuture 对象以及如何获取返回值,虽然看起来这些操作已经比较方便,但还有进
- Spring内置 * 对于 Web 应用来说,ServletContext 对象是唯一的,一个 Web 应用,只有一个ServletCont
- 项目里使用了Feign进行远程调用,有时为了问题排查,需要开启请求和响应日志下面简介一下如何开启Feign日志:注:本文基于spring-b
- 一、lombok简介lombok 提供了使用注解的形式帮助简化消除java代码。在编写Java代码时,通过使用对应的注解,可以简化开发,同时
- 先来一个常见的错误信息:Due to limitations of the com.mongodb.BasicDocument, you c
- 概述在使用maven进行Java项目的开发过程中,难免会有些公共的私有库,这些库是不太方便放到中央仓库的,可以通过Nexus搭建一个私有仓库
- 实现要求1、使用Java图形界面组件设计软件,界面如图所示。2、软件能够满足基本的“加、减、乘、除"等运算要求。3、程序代码清晰,
- 一、项目运行环境配置:Jdk1.8 + Tomcat8.5 + mysql + Eclispe(IntelliJ IDEA,Eclispe,