客户端ffmpeg c# 压缩视频 显示进度条

946 阅读5分钟

在这里插入图片描述类似这样的客户端, 第一个框是输入压缩视频的路径的,可以多选, 第二个框是输出压缩视频路径的,只可以选一个 第三个框是进度条 最后一个框是点击立即压缩

首先 限制文件格式 ,只允许是视频格式的可以被选择

private void create_video_list()
        {
            video_list.Add(".MP4");
            video_list.Add(".mp4");
            video_list.Add(".MOV");
            video_list.Add(".mov");
            video_list.Add(".AVI");
            video_list.Add(".avi");
            video_list.Add(".MPEG");
            video_list.Add(".mpeg");
            video_list.Add(".WMV");
            video_list.Add(".wmv");
            video_list.Add(".3GP");
            video_list.Add(".3gp");
        }
        通过video_list.Contains(Path.GetExtension(path)) 判断是否是视频的格式
另外 由于太小的文件没有压缩的必要,所以直接忽略掉,设置20M以下的文件不允许被选中
通过函数
public static long FileSize(string filePath)//判断文件大小
        {
            //定义一个FileInfo对象,是指与filePath所指向的文件相关联,以获取其大小
            FileInfo fileInfo = new FileInfo(filePath);
            return fileInfo.Length;
        }
来判断文件大小
然后可以通过拖动文件来加入文件路径
private void Form1_DragEnter(object sender, DragEventArgs e)//拖拽加入文件
        {
            string allIntputPath = "";
            //获取拖放数据
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                string[] content = (string[])e.Data.GetData(DataFormats.FileDrop);
                for (int i = 0; i < content.Length; i++)
                {
                    //这是全路径
                    if (is_videos(content[i].ToString())) {
                        allIntputPath = content[i].ToString() + "\r\n";
                        inputList.Add(content[i].ToString() + "\r\n");
                    }
                }
                changeText(allIntputPath);
            }
        }


通过点击按钮来选择压迫压缩的文件路径
private void SelectFolder_Click(object sender, EventArgs e)//点击选择视频获取路径
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Multiselect = true;//该值确定是否可以选择多个文件
            dialog.Title = "请选择文件夹";
            dialog.Filter = "所有文件(*.*)|*.*";
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string allIntputPath = "";
                string[] strNames = dialog.FileNames;
                for (int i = 0; i < strNames.Length; i++)
                {
                    if (is_videos(strNames[i].ToString()))
                    {
                        allIntputPath = strNames[i].ToString() + "\r\n";
                        inputList.Add(strNames[i].ToString() + "\r\n");
                    }
                }
                changeText(allIntputPath);
            }
        }


然后使用线程来进行执行压缩动作
Thread t = new Thread(ZipVideos);
                t.IsBackground = true;//把前台线程,设置为后台线程,随着应用程序,不必等线程结束即会被终止。
                t.Start();

public void ZipVideos()
        {
            successCount = 0;
            if (isVideoIsEmpty)
            {
                string[] striparr = this.skinTextBox1.Text.Split(new string[] { "\r\n" }, StringSplitOptions.None);
                foreach (String ph in striparr)
                {
                    if (ph.Length > 1)
                    {
                        zippath = System.IO.Path.GetFileName(ph);
                        try
                        {
                            this.SelectFolder.Enabled = false;
                            this.SaveFolderPath.Enabled = false;
                            this.MakeVideo.Enabled = false;
                            ConvertVideo(ph);
                        }
                        catch (System.Exception ex)
                        {
                            LogHelper.WriteLog(ex.ToString());
                        }
                    }
                    Thread.Sleep(1000);
                }
            }
        }

然后通过
public void ConvertVideo(String inputpath)//压缩视频
        {
            now_path = inputpath;
            isVideoIsEmpty = false;
            string filename = System.IO.Path.GetFileName(inputpath);
            string outputpath = VideoOutPath + "\\zip" + filename;
            string sPath = Environment.GetEnvironmentVariable("ffmpeg");
            string new_fps = "25";
            string ffmpegpath = @"ffmpeg.exe";
            LogHelper.WriteLog(ffmpegpath);
            altime=GetVideoDuration(ffmpegpath, inputpath);
            int intbitr = 0;
            int.TryParse(allbitrate, out intbitr);
            string bitcount = (intbitr / 3).ToString() + "k";
            LogHelper.WriteLog(altime+"@"+bitcount + "@" + allbitrate);
            string cmd1 = "";
            if (new_resolution.Length < 1)
            {
                cmd1 = "-i " + inputpath + " -r " + new_fps + " -threads 2" + " -y " + outputpath + "";
            }
            if (allbitrate.Length < 1)
            {
                cmd1 = "-i " + inputpath + " -r " + new_fps + " -threads 2" + " -y " + outputpath + "";
            }
            if (allbitrate.Length > 2 && new_resolution.Length > 2)
            {
                cmd1 = "-i " + inputpath + " -b " + bitcount + " -s " + new_resolution + " -r " + new_fps + " -threads 2" + " -y " + outputpath + "";
            }
            LogHelper.WriteLog("@---------------");
            LogHelper.WriteLog(cmd1);
            LogHelper.WriteLog("@---------------");
            Process p = new Process();//建立外部调用线程
            p.StartInfo.FileName = ffmpegpath;//要调用外部程序的绝对路径
            p.StartInfo.Arguments = cmd1;//参数(这里就是FFMPEG的参数了)
            p.StartInfo.UseShellExecute = false;//不使用操作系统外壳程序启动线程(一定为FALSE,详细的请看MSDN)
            p.StartInfo.RedirectStandardError = true;//把外部程序错误输出写到StandardError流中(这个一定要注意,FFMPEG的所有输出信息,都为错误输出流,用StandardOutput是捕获不到任何消息的...这是我耗费了2个多月得出来的经验...mencoder就是用standardOutput来捕获的)
            p.StartInfo.CreateNoWindow = true;//不创建进程窗口
            p.ErrorDataReceived += new DataReceivedEventHandler(Output);//外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
            p.Start();//启动线程
            p.BeginErrorReadLine();//开始异步读取
            p.WaitForExit();//阻塞等待进程结束
            p.Close();//关闭进程
            p.Dispose();//释放资源
        }
来进行压缩视频 

全部代码如下

using CCWin;
using log4net;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CompaessVideo
{
    public partial class ZipVideo : CCSkinMain
    {
        public ZipVideo()
        {
            InitializeComponent();
        }
        readonly static object _locker = new object();
        string VideoInutPath = "";
        string VideoOutPath = "";
        string new_resolution = "";
        string allbitrate = "";
        Boolean isVideoIsEmpty = true;
        Queue<string> videoQueue = new Queue<string>();
        string zippath = "";
        int successCount = 0;
        ArrayList inputList = new ArrayList();
        ArrayList video_list = new ArrayList();
        int altime = 0;
        string now_path = "";

        private void ZipVideo_Load(object sender, EventArgs e)//进来项目的初始化函数
        {
            LogHelper.WriteLog("记录日志");
            this.AllowDrop = true;
            this.skinTextBox1.SkinTxt.Leave += skinLabel1Change;
            create_video_list();
        }
        private void skinLabel1Change(object sender, EventArgs e) {//再输入框输入路径的时候
            inputList.Clear();
            string[] striparr = this.skinTextBox1.Text.Split(new string[] { "\r\n" }, StringSplitOptions.None);
            System.Text.RegularExpressions.Regex regex =new System.Text.RegularExpressions.Regex(@"^[a-zA-Z]:((\\+[^\/:*?""<>|]+)+)\s*$");
            foreach (String ph in striparr)
            {
                if (System.IO.File.Exists(ph)) {
                    if (is_videos(ph))
                    {
                        inputList.Add(ph + "\r\n");
                    }
                }
            }
        }
        private void create_video_list()
        {
            video_list.Add(".MP4");
            video_list.Add(".mp4");
            video_list.Add(".MOV");
            video_list.Add(".mov");
            video_list.Add(".AVI");
            video_list.Add(".avi");
            video_list.Add(".MPEG");
            video_list.Add(".mpeg");
            video_list.Add(".WMV");
            video_list.Add(".wmv");
            video_list.Add(".3GP");
            video_list.Add(".3gp");
        }
        private Boolean is_videos(string filePath) { //判断是否是视频文件 以及判断是否大于20m
            string path = filePath.Replace("\r\n", "");
            long filesize = FileSize(filePath);
            long sizem=filesize / 1048576;
            if (path.Length > 1)
            {
                //Path.GetExtension(filePath).ToString()
                if (video_list.Contains(Path.GetExtension(path)))
                {
                    if (sizem > 20)
                    {
                        return true;
                    }
                    else {
                        MessageBox.Show("请勿添加小于20M视频");
                        return false;
                    }
                }
                else
                {
                    MessageBox.Show("请勿添加非视频文件");
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
        public static long FileSize(string filePath)//判断文件大小
        {
            //定义一个FileInfo对象,是指与filePath所指向的文件相关联,以获取其大小
            FileInfo fileInfo = new FileInfo(filePath);
            return fileInfo.Length;
        }
        private void Form1_DragEnter(object sender, DragEventArgs e)//拖拽加入文件
        {
            string allIntputPath = "";
            //获取拖放数据
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                string[] content = (string[])e.Data.GetData(DataFormats.FileDrop);
                for (int i = 0; i < content.Length; i++)
                {
                    //这是全路径
                    if (is_videos(content[i].ToString())) {
                        allIntputPath = content[i].ToString() + "\r\n";
                        inputList.Add(content[i].ToString() + "\r\n");
                    }
                }
                changeText(allIntputPath);
            }
        }
        private void changeText(String inputDictory)//把文件名称放到框里
        {
            if (inputDictory.Length > 1) {
                this.skinTextBox1.Text = "";
                if (!this.skinTextBox2.Text.Contains("\\"))
                {
                    string folder = System.IO.Path.GetDirectoryName(inputDictory.Replace("\r\n", ""));
                    VideoOutPath = @folder;
                    this.skinTextBox2.Text = VideoOutPath;
                }
                if (inputList.Count > 0)
                {
                    foreach (String pt in inputList)
                    {
                        this.skinTextBox1.Text += pt;
                    }
                }
            }
        }
     
        private void SelectFolder_Click(object sender, EventArgs e)//点击选择视频获取路径
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Multiselect = true;//该值确定是否可以选择多个文件
            dialog.Title = "请选择文件夹";
            dialog.Filter = "所有文件(*.*)|*.*";
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string allIntputPath = "";
                string[] strNames = dialog.FileNames;
                for (int i = 0; i < strNames.Length; i++)
                {
                    if (is_videos(strNames[i].ToString()))
                    {
                        allIntputPath = strNames[i].ToString() + "\r\n";
                        inputList.Add(strNames[i].ToString() + "\r\n");
                    }
                }
                changeText(allIntputPath);
            }
        }
        private void SaveFolderPath_Click(object sender, EventArgs e)//点击选择存储视频路径
        {
            this.skinTextBox2.Text = "";
            string[] paths = new string[0];
            if (String.IsNullOrEmpty(this.skinTextBox1.Text))
            {
                MessageBox.Show("请选择获取视频路径");
                return;
            }
            paths = VideoInutPath.Split('\\');
            string temp = paths[paths.Length - 1];
            System.Windows.Forms.FolderBrowserDialog dialog = new System.Windows.Forms.FolderBrowserDialog();
            dialog.Description = "请选择Txt所在文件夹";
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                if (string.IsNullOrEmpty(dialog.SelectedPath))
                {
                    MessageBox.Show(this, "文件夹路径不能为空", "提示");
                    return;
                }
                else
                {
                    string filename = dialog.SelectedPath;
                    string folder = System.IO.Path.GetFullPath(dialog.SelectedPath);
                    VideoOutPath = @folder;
                    this.skinTextBox2.Text = VideoOutPath;
                }
            }
        }
        private void MakeVideo_Click(object sender, EventArgs e)//点击压缩视频
        {
            CheckForIllegalCrossThreadCalls = false;
            string[] striparr = this.skinTextBox1.Text.Split(new string[] { "\r\n" }, StringSplitOptions.None);
            foreach (String ph in striparr)
            {
                if (ph.Length > 1) {
                    if (!System.IO.File.Exists(ph))
                    {
                        MessageBox.Show("文件格式不正确");
                        return;
                    }
                }
            }
            if (String.IsNullOrEmpty(this.skinTextBox1.Text))
            {
                MessageBox.Show("请选择获取视频路径");
                return;
            }
            if (String.IsNullOrEmpty(this.skinTextBox2.Text))
            {
                MessageBox.Show("请选择保存视频路径");
                return;
            }
            try
            {
                Thread t = new Thread(ZipVideos);
                t.IsBackground = true;//把前台线程,设置为后台线程,随着应用程序,不必等线程结束即会被终止。
                t.Start();
                this.SelectFolder.Enabled = false;
                this.skinTextBox1.Enabled = false;
                this.skinTextBox2.Enabled = false;
                this.SaveFolderPath.Enabled = false;
                this.MakeVideo.Enabled = false;
            }
            catch (System.Exception ex)
            {
                LogHelper.WriteLog(ex.ToString());
            }
        }
        public void ZipVideos()
        {
            successCount = 0;
            if (isVideoIsEmpty)
            {
                string[] striparr = this.skinTextBox1.Text.Split(new string[] { "\r\n" }, StringSplitOptions.None);
                foreach (String ph in striparr)
                {
                    if (ph.Length > 1)
                    {
                        zippath = System.IO.Path.GetFileName(ph);
                        try
                        {
                            this.SelectFolder.Enabled = false;
                            this.SaveFolderPath.Enabled = false;
                            this.MakeVideo.Enabled = false;
                            ConvertVideo(ph);
                        }
                        catch (System.Exception ex)
                        {
                            LogHelper.WriteLog(ex.ToString());
                        }
                    }
                    Thread.Sleep(1000);
                }
            }
        }
        public void ZipVideos1()
        {
            successCount = 0;
            string[] striparr = this.skinTextBox1.Text.Split(new string[] { "\r\n" }, StringSplitOptions.None);
            foreach (String ph in striparr)
            {
                if (ph.Length > 1)
                {
                    videoQueue.Enqueue(ph);
                }
            }
            while (true)
            {
                if (videoQueue.Count != 0)
                {
                    if (isVideoIsEmpty)
                    {
                        lock (_locker)
                        {
                            String path1 = "";
                            String path2 = "";
                            try
                            {
                                path1 = videoQueue.Dequeue();
                            }
                            catch
                            {
                                path1 = "";
                            }
                            try
                            {
                                path2 = videoQueue.Dequeue();
                            }
                            catch
                            {
                                path2 = "";
                            }
                            String zippath1 = System.IO.Path.GetFileName(path1);
                            String zippath2 = System.IO.Path.GetFileName(path2);
                            zippath = zippath1 + "/" + zippath2;
                            try
                            {
                                this.SelectFolder.Enabled = false;
                                this.SaveFolderPath.Enabled = false;
                                this.MakeVideo.Enabled = false;
                                if (path1.Length > 1)
                                {
                                    Task task1 = new Task(() =>
                                    {
                                        ConvertVideo(path1);
                                    });
                                    task1.Start();
                                }
                                if (path2.Length > 1)
                                {
                                    Task task2 = new Task(() =>
                                    {
                                        ConvertVideo(path2);
                                    });
                                    task2.Start();
                                }
                            }
                            catch (System.Exception ex)
                            {
                                LogHelper.WriteLog(ex.ToString());
                            }
                        }
                    }
                }
                else
                {
                    break;
                }
                Thread.Sleep(1000);
            }
        }
        public void ConvertVideo(String inputpath)//压缩视频
        {
            now_path = inputpath;
            isVideoIsEmpty = false;
            string filename = System.IO.Path.GetFileName(inputpath);
            string outputpath = VideoOutPath + "\\zip" + filename;
            string sPath = Environment.GetEnvironmentVariable("ffmpeg");
            string new_fps = "25";
            string ffmpegpath = @"ffmpeg.exe";
            LogHelper.WriteLog(ffmpegpath);
            altime=GetVideoDuration(ffmpegpath, inputpath);
            int intbitr = 0;
            int.TryParse(allbitrate, out intbitr);
            string bitcount = (intbitr / 3).ToString() + "k";
            LogHelper.WriteLog(altime+"@"+bitcount + "@" + allbitrate);
            string cmd1 = "";
            if (new_resolution.Length < 1)
            {
                cmd1 = "-i " + inputpath + " -r " + new_fps + " -threads 2" + " -y " + outputpath + "";
            }
            if (allbitrate.Length < 1)
            {
                cmd1 = "-i " + inputpath + " -r " + new_fps + " -threads 2" + " -y " + outputpath + "";
            }
            if (allbitrate.Length > 2 && new_resolution.Length > 2)
            {
                cmd1 = "-i " + inputpath + " -b " + bitcount + " -s " + new_resolution + " -r " + new_fps + " -threads 2" + " -y " + outputpath + "";
            }
            LogHelper.WriteLog("@---------------");
            LogHelper.WriteLog(cmd1);
            LogHelper.WriteLog("@---------------");
            Process p = new Process();//建立外部调用线程
            p.StartInfo.FileName = ffmpegpath;//要调用外部程序的绝对路径
            p.StartInfo.Arguments = cmd1;//参数(这里就是FFMPEG的参数了)
            p.StartInfo.UseShellExecute = false;//不使用操作系统外壳程序启动线程(一定为FALSE,详细的请看MSDN)
            p.StartInfo.RedirectStandardError = true;//把外部程序错误输出写到StandardError流中(这个一定要注意,FFMPEG的所有输出信息,都为错误输出流,用StandardOutput是捕获不到任何消息的...这是我耗费了2个多月得出来的经验...mencoder就是用standardOutput来捕获的)
            p.StartInfo.CreateNoWindow = true;//不创建进程窗口
            p.ErrorDataReceived += new DataReceivedEventHandler(Output);//外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
            p.Start();//启动线程
            p.BeginErrorReadLine();//开始异步读取
            p.WaitForExit();//阻塞等待进程结束
            p.Close();//关闭进程
            p.Dispose();//释放资源
        }
        private 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  
                    ffmpeg.StartInfo.UseShellExecute = false;
                    ffmpeg.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                    ffmpeg.StartInfo.RedirectStandardError = true;
                    ffmpeg.StartInfo.FileName = ffmpegfile;
                    ffmpeg.StartInfo.Arguments = "-i " + sourceFile;
                    ffmpeg.Start();
                    errorreader = ffmpeg.StandardError;
                    ffmpeg.WaitForExit();
                    result = errorreader.ReadToEnd();
                    LogHelper.WriteLog("---------------");
                    LogHelper.WriteLog(result);
                    LogHelper.WriteLog("---------------");
                    duration = result.Substring(result.IndexOf("Duration: ") + ("Duration: ").Length, ("00:00:00").Length);
                    string allsizes = result.Substring(result.IndexOf("Video: ") + ("Video: ").Length);
                    LogHelper.WriteLog(allsizes);
                    LogHelper.WriteLog(allsizes.Split(',')[0]);
                    string new_fps = allsizes.Split(',')[4].Split(new string[] { "fps" }, StringSplitOptions.None)[0];
                    string sizes = allsizes.Split(',')[2].Split('[')[0];
                    new_resolution = sizes;
                    string[] birts = result.Substring(result.IndexOf("bitrate: ") + ("bitrate: ").Length).Split(new string[] { "Stream" }, StringSplitOptions.None);
                    allbitrate = birts[0].ToString().Split(new string[] { "kb" }, StringSplitOptions.None)[0];
                    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)
            {
                LogHelper.WriteLog(ex.ToString());
                return 60;
            }
        }
        private void Output(object sendProcess, DataReceivedEventArgs output)//打印视频生成过程中详细信息
        {
            if (!String.IsNullOrEmpty(output.Data))
            {
                createFileTime(output);
                if (output.Data.Contains("headers"))
                {
                    successCount += 1;
                    isVideoIsEmpty = true;
                }
                if (output.Data.Contains("No such file"))
                {
                    this.SelectFolder.Enabled = true;
                    this.SaveFolderPath.Enabled = true;
                    this.MakeVideo.Enabled = true;
                    this.skinTextBox1.Text = "";
                    this.skinTextBox2.Text = "";
                    MessageBox.Show("找不到此文件,请修改路径");
                }
                if (inputList.Count == successCount)
                {
                    this.skinTextBox1.Enabled = true;
                    this.skinTextBox2.Enabled = true;
                    this.skinTextBox1.Text = "";
                    this.skinTextBox2.Text = "";
                    this.SelectFolder.Enabled = true;
                    this.SaveFolderPath.Enabled = true;
                    this.MakeVideo.Enabled = true;
                    now_path = "全部文件";
                    inputList.Clear();
                    MessageBox.Show("全部压缩完毕");
                }
            }
        }
        private void createFileTime(DataReceivedEventArgs output) {
            LogHelper.WriteLog("日志内容" + output.Data);
            string outputData = output.Data;
            string[] filetimes = outputData.Split(' ');
            foreach (string filetime in filetimes) {
                if (filetime.Contains("time=")) {
                    string[] fl_time = filetime.Split('=');
                    try
                    {
                        float tm = 0;
                        float.TryParse(fl_time[1], out tm);
                        int program =Convert.ToInt32(((tm/altime)*100));
                        this.skinLabel1.Text = now_path+"压缩进度:";
                        skinProgressBar1.Value = program;
                    }
                    catch(Exception e){
                        LogHelper.WriteLog(e.ToString());
                    }
                }
            }
        }
    }
}