视频图像处理系列索引 || Arcgis/Engine/Server开发索引 || Web Map Gis开发索引 || jquery表格组件 JQGrid索引
WPF MVVM模式开发实现简明教程索引 || ArcGIS Runtime WPF(.net C#)开发简明教程索引

使用FFMPEG进行一些视频处理(C#)视频合并、转码、获取时长

FFMPEG的强大无需多说,举几个用到的功能,直接贴代码了

 

还有更多命令用到时搜索即可

 

视频转码

public static string DecodeMp4ToFlv(string mp4, string format = ".flv", int timeout = 0)
        {
            var args = "-y -i {0} -vcodec copy {1}".Formatting("\"{0}\"".Formatting(mp4), "\"{0}\"".Formatting(strFlvPath));
            string output, error;
            if (timeout <= 0)
                timeout = 5*60*1000; // 超时时间 = 5 分钟
            ProcessHelper.Process(strFFMPEGPath, args, timeout, out output, out error);
            if (!error.IsNullOrEmpty())
            {
                Logger.Error("{0}{1} : {2}{0}".Formatting(Environment.NewLine, "FFmpeg", error));
            }

            return flv;
        }

 

 

视频合并

public static string ConcatMp4(string mp41, string mp42)
        {

var args = " -i \"concat:" + mp41 + "|" + mp42 + "|\" -c copy -bsf:a aac_adtstoasc -movflags +faststart " + outputpath; string output, error; int timeout = 2 * 60 * 1000; // 超时时间 = 2 分钟 ProcessHelper.Process(strFFMPEGPath, args, timeout, out output, out error); if (!error.IsNullOrEmpty()) { Logger.Error("{0}{1} : {2}{0}".Formatting(Environment.NewLine, "FFmpeg", error)); } return outputpath;
 }

 

 

获取视频时长

private static int GetVideoDuration(string ffmpegfile, string sourceFile)
        {
            try
            {
                using (System.Diagnostics.Process ffmpeg = new System.Diagnostics.Process())
                {
                    String duration;  // soon will hold our video's duration in the form "HH:MM:SS.UU"  
                    String result;  // temp variable holding a string representation of our video's duration  
                    StreamReader errorreader;  // StringWriter to hold output from ffmpeg  

                    // we want to execute the process without opening a shell  
                    ffmpeg.StartInfo.UseShellExecute = false;
                    //ffmpeg.StartInfo.ErrorDialog = false;  
                    ffmpeg.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                    // redirect StandardError so we can parse it  
                    // for some reason the output comes through over StandardError  
                    ffmpeg.StartInfo.RedirectStandardError = true;
                    // set the file name of our process, including the full path  
                    // (as well as quotes, as if you were calling it from the command-line)  
                    ffmpeg.StartInfo.FileName = ffmpegfile;

                    // set the command-line arguments of our process, including full paths of any files  
                    // (as well as quotes, as if you were passing these arguments on the command-line)  
                    ffmpeg.StartInfo.Arguments = "-i " + sourceFile;

                    // start the process  
                    ffmpeg.Start();

                    // now that the process is started, we can redirect output to the StreamReader we defined  
                    errorreader = ffmpeg.StandardError;

                    // wait until ffmpeg comes back  
                    ffmpeg.WaitForExit();

                    // read the output from ffmpeg, which for some reason is found in Process.StandardError  
                    result = errorreader.ReadToEnd();

                    // a little convoluded, this string manipulation...  
                    // working from the inside out, it:  
                    // takes a substring of result, starting from the end of the "Duration: " label contained within,  
                    // (execute "ffmpeg.exe -i somevideofile" on the command-line to verify for yourself that it is there)  
                    // and going the full length of the timestamp  

                    duration = result.Substring(result.IndexOf("Duration: ") + ("Duration: ").Length, ("00:00:00").Length);

                    string[] ss = duration.Split(':');
                    int h = int.Parse(ss[0]);
                    int m = int.Parse(ss[1]);
                    int s = int.Parse(ss[2]);
                    return h * 3600 + m * 60 + s;
                }
            }
            catch (System.Exception ex)
            {
                return 60;
            }
        }  

Process处理类如下,也可以自己写个
public static void Process(string startFile, string args, int timeout, out string standardOutput,
            out string standardError)
        {
            using (var process = new ProcessExecutor(startFile, args, timeout))
            {
                process.Execute(out standardOutput, out standardError);
            }
        }
internal class ProcessExecutor : IDisposable
    {
        private readonly StringBuilder error;
        private readonly AutoResetEvent errorWaitHandle;
        private readonly StringBuilder output;
        private readonly int timeout;
        private AutoResetEvent outputWaitHandle;
        private Process process;

        public ProcessExecutor(string startFile, string args, int timeout = 0)
        {
            process = new Process();
            //设置进程启动信息属性StartInfo,这是ProcessStartInfo类
            process.StartInfo.FileName = Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(startFile));
            process.StartInfo.Arguments = Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(args));

            process.StartInfo.UseShellExecute = false;
            //提供的标准输出流只有2k,超过大小会卡住;如果有大量输出,就读出来
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardError = true;
            process.StartInfo.CreateNoWindow = true;

            output = new StringBuilder();
            error = new StringBuilder();

            outputWaitHandle = new AutoResetEvent(false);
            errorWaitHandle = new AutoResetEvent(false);

            this.timeout = timeout;

            RegisterToEvents();
        }

        public void Dispose()
        {
            UnregisterFromEvents();

            if (process != null)
            {
                process.Dispose();
                process = null;
            }
            if (errorWaitHandle != null)
            {
                errorWaitHandle.Close();
                outputWaitHandle = null;
            }
            if (outputWaitHandle != null)
            {
                outputWaitHandle.Close();
                outputWaitHandle = null;
            }
        }

        public void Execute(out string standardOutput, out string standardError)
        {
            process.Start();

            process.BeginOutputReadLine();
            process.BeginErrorReadLine();

            if (process.WaitForExit(timeout) &&
                outputWaitHandle.WaitOne(timeout) &&
                errorWaitHandle.WaitOne(timeout))
            {

            }
            else
            {
                // if timeout then kill the procee
                process.Kill();
            }

            standardOutput = output.ToString();
            standardError = error.ToString();
        }

        private void RegisterToEvents()
        {
            process.OutputDataReceived += process_OutputDataReceived;
            process.ErrorDataReceived += process_ErrorDataReceived;
        }

        private void UnregisterFromEvents()
        {
            process.OutputDataReceived -= process_OutputDataReceived;
            process.ErrorDataReceived -= process_ErrorDataReceived;
        }

        private void process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (e.Data == null)
            {
                errorWaitHandle.Set();
            }
            else
            {
                error.AppendLine(e.Data);
            }
        }

        private void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (e.Data == null)
            {
                outputWaitHandle.Set();
            }
            else
            {
                output.AppendLine(e.Data);
            }
        }
    }

 

posted @ 2017-08-23 11:02  jhlong  阅读(5520)  评论(7编辑  收藏  举报
海龙的博客 jhlong@cnblogs 版权所有© 转载请注明链接.有用请推荐一下
代码全部经过本人测试,但不保证复制粘贴就正常运行,更不保证能解决你的问题,请结合前后代码及描述理解后修改和使用