• C#进程调用FFmpeg操作音视频


    开发背景

    因为公司需要对音视频做一些操作,比如说对系统用户的发音和背景视频进行合成,以及对多个音视频之间进行合成,还有就是在指定的源背景音频中按照对应的规则在视频的多少秒钟内插入一段客户发音等一些复杂的音视频操作。本篇文章主要讲解的是使用C#进程(Process)调用FFmpeg.exe进行视频合并、音频合并、音频与视频合并成视频这几个简单的音视频操作。

    FFmpeg介绍

    FFmpeg是一个开源、功能强大、跨平台、灵活且广泛应用的多媒体处理工具,可用于录制、转换和流式传输音频和视频。它提供了一组强大的工具和库,可以处理各种多媒体格式,包括视频(如MPEG、AVI、WMV、MOV等)和音频(如MP3、WAV、AAC等),以及图像文件。

    FFmpeg相关教程

    开始之初你首先要了解FFmpeg是什么,有哪些常用的命令和实用的功能。

    下载FFmpeg.exe安装包

    首先把下载下来的FFmpeg.exe放在你指定的目录文件夹中,方便C#进程调用。

    FFmpeg.exe安装包:https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip

    FFmpeg部分命令说明

    命令命令说明
    -ss 表示搜索到指定的时间
    -i 表示输入的文件
    -y 表示覆盖输出
    -f 表示强制使用的格式
    -c 用于指定编解码器
    -b:v 用于设置视频比特率
    -b:a 用于设置音频比特率
    -r 用于设置视频的帧率

    C#进程调用FFmpeg.exe

            /// 
            /// 执行命令
            /// C# Process进程调用 https://learn.microsoft.com/zh-cn/dotnet/api/system.diagnostics.process?view=net-8.0
            /// 

            /// 执行命令
            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);
                }
            }

    视频合并

            static void Main(string[] args)
            {
                var physicalPath = "E:\\FFmpegAudioAndVideoMerge\\FFmpegAudioAndVideoMerge\\files\\";

                //视频合并
                VideoCombine(physicalPath + "video1.mp4", physicalPath + "video2.mp4", physicalPath + "merageVideoyy.mp4");
            }

            #region 视频合并
            /// 
            /// 视频合并
            /// 

            /// 合并视频1
            /// 合并视频2
            /// 保存文件名
            /// 
            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

    音频合并

            static void Main(string[] args)
            {
                var physicalPath = "E:\\FFmpegAudioAndVideoMerge\\FFmpegAudioAndVideoMerge\\files\\";

                //音频合并
                var audioMergeList = new List();
                audioMergeList.Add(physicalPath + "music1.mp3");
                audioMergeList.Add(physicalPath + "music2.mp3");
                audioMergeList.Add(physicalPath + "music3.mp3");
                AudioMerge(physicalPath, audioMergeList);
            }

            #region 音频合并
            /// 
            /// 音频合并
            /// 

            public static void AudioMerge(string physicalPath, List 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

    音频与视频合并成视频

            static void Main(string[] args)
            {
                var physicalPath = "E:\\FFmpegAudioAndVideoMerge\\FFmpegAudioAndVideoMerge\\files\\";

                //音频与视频合并成视频
                AudioAndVideoMerge(physicalPath);
            }

            #region 音频与视频合并成视频
            /// 
            /// 音频与视频合并成视频
            /// 

            /// 物理路径
            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

    DotNetGuide技术社区交流群

    • DotNetGuide技术社区是一个面向.NET开发者的开源技术社区,旨在为开发者们提供全面的C#/.NET/.NET Core相关学习资料、技术分享和咨询、项目框架推荐、求职和招聘资讯、以及解决问题的平台。
    • 在DotNetGuide技术社区中,开发者们可以分享自己的技术文章、项目经验、学习心得、遇到的疑难技术问题以及解决方案,并且还有机会结识志同道合的开发者。
    • 我们致力于构建一个积极向上、和谐友善的.NET技术交流平台。无论您是初学者还是有丰富经验的开发者,我们都希望能为您提供更多的价值和成长机会。

    欢迎加入DotNetGuide技术社区微信交流群👪

  • 相关阅读:
    施磊老师 C++ 课程笔记--自己记录用
    智云通CRM:客户说“手头紧”,如何应对才能让他下定决心购买?
    使用CompletionService进行多个文件打包为zip下载
    Dubbo 原理和机制详解 (非常全面)
    《IEEE Transactions on Robotics》发表!北京大学研究团队推出具有多种运动模态的软体两栖机器人
    【算法基础】帕累托最优解
    Transformer模型 | Transformer模型描述
    Go-Excelize API源码阅读(二十四)——SetColVisible、SetRowHeight
    居民健康监测小程序|基于微信小程序的居民健康监测小程序设计与实现(源码+数据库+文档)
    Activiti工作流引擎中责任链模式的建立与应用原理
  • 原文地址:https://www.cnblogs.com/Can-daydayup/p/18248812