欢迎使用CSDN-markdown编辑器

c# 读取mov视频中图片,及宽高

public class FormatConverter
{
//FFmpeg配置信息
private string ffmpegpath = “FFmpeg\ffmpeg.exe”;//FFmpeg的服务器路径
private string imgsize = “400*300”; //视频截图大小
private string videosize = “480*360”; //视频大小
#region 也可将信息添加到配置文件中
//public static string ffmpegpath = ConfigurationManager.AppSettings[“ffmpeg”];
//public static string imgsize = ConfigurationManager.AppSettings[“imgsize”];
//public static string videosize = ConfigurationManager.AppSettings[“videoize”];
#endregion

    private string destVideo = "";

    /// <summary>
    /// 视频路径
    /// </summary>
    public string DestVideo
    {
        get { return destVideo; }
        set { destVideo = value; }
    }
    private string destImage = "";

    /// <summary>
    /// 图片路径
    /// </summary>
    public string DestImage
    {
        get { return destImage; }
        set { destImage = value; }
    }

    /// <summary>
    /// 视频长度
    /// </summary>
    public string VideoLength { get; set; }

    //文件类型
    public enum VideoType
    {
        [Description(".avi")]
        AVI,
        [Description(".mov")]
        MOV,
        [Description(".mpg")]
        MPG,
        [Description(".mp4")]
        MP4,
        [Description(".flv")]
        FLV
    }

    /// <summary>
    /// 返回枚举类型的描述信息
    /// </summary>
    /// <param name="myEnum"></param>
    /// <returns></returns>
    private string GetDiscription(System.Enum myEnum)
    {

        System.Reflection.FieldInfo fieldInfo = myEnum.GetType().GetField(myEnum.ToString());
        object[] attrs = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), true);
        if (attrs != null && attrs.Length > 0)
        {
            DescriptionAttribute desc = attrs[0] as DescriptionAttribute;
            if (desc != null)
            {
                return desc.Description.ToLower();
            }
        }
        return myEnum.ToString();
    }
    //将GetDesCription定义为扩展方法,需.net3.5
    //public static string Description(this Enum myEnum)
    //{
    //    return GetDiscription(myEnum);
    //}

    //构造函数
    //创建目录
    public FormatConverter()
    {
    }

    #region 使用FFmpeg进行格式转换

    /// <summary>
    /// 运行格式转换
    /// </summary>
    /// <param name="sourceFile">要转换文件绝对路径</param>
    /// <param name="destPath">转换结果存储的相对路径</param>
    /// <param name="videotype">要转换成的文件类型</param>
    /// <param name="createImage">是否生成截图</param>
    /// <returns>
    /// 执行成功返回空,否则返回错误信息
    /// </returns>
    public string Convert(string sourceFile, string destPath, string uniquename, VideoType videotype, bool createImage, bool getDuration)
    {
        //取得ffmpeg.exe的物理路径

        int width = 0;
        int height = 0;
        GetMovWidthAndHeight(sourceFile, out width, out height);

        string ffmpeg = Application.StartupPath + "\\" + ffmpegpath;
        if (!File.Exists(ffmpeg))
        {
            return "找不到格式转换程序!";
        }
        if (!File.Exists(sourceFile))
        {
            return "找不到源文件!";
        }
        //string uniquename = FileHelper.GetUniqueFileName();
        string filename = uniquename + GetDiscription(videotype);
        string destFile =(destPath + filename);
        //if (Path.GetExtension(sourceFile).ToLower() != GetDiscription(videotype).ToLower())
        //{
        System.Diagnostics.ProcessStartInfo FilestartInfo = new System.Diagnostics.ProcessStartInfo(ffmpeg);
        FilestartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
        /*ffmpeg参数说明
         * -i 1.avi   输入文件
         * -ab/-ac <比特率> 设定声音比特率,前面-ac设为立体声时要以一半比特率来设置,比如192kbps的就设成96,转换 
            均默认比特率都较小,要听到较高品质声音的话建议设到160kbps(80)以上
         * -ar <采样率> 设定声音采样率,PSP只认24000
         * -b <比特率> 指定压缩比特率,似乎ffmpeg是自动VBR的,指定了就大概是平均比特率,比如768,1500这样的   --加了以后转换不正常
         * -r 29.97 桢速率(可以改,确认非标准桢率会导致音画不同步,所以只能设定为15或者29.97)
         * s 320x240 指定分辨率
         * 最后的路径为目标文件
         */
        FilestartInfo.Arguments = " -i " + sourceFile + " -ab 80 -ar 22050 -r 29.97 -s " + videosize + " " + destFile;
        //FilestartInfo.Arguments = "-y -i " + sourceFile + " -s 320x240 -vcodec h264 -qscale 4  -ar 24000 -f psp -muxvb 768 " + destFile;
        try
        {
            //转换
            System.Diagnostics.Process.Start(FilestartInfo);
            destVideo = destPath + filename;
        }
        catch
        {
            return "格式转换失败!";
        }
        //}
        //格式不需要转换则直接复制文件到目录
        //else
        //{
        //    File.Copy(sourceFile, destFile,true);
        //    destVideo = destPath + filename;
        //}
        //提取视频长度
        if (getDuration)
        {
            VideoLength = GetVideoDuration(ffmpeg, sourceFile);
        }
        //提取图片
        if (createImage)
        {
            //定义进程
            System.Diagnostics.ProcessStartInfo ImgstartInfo = new System.Diagnostics.ProcessStartInfo(ffmpeg);

            if (width != 0 && height != 0)
            {
                imgsize = string.Format("{0}*{1}", width, height);
            }
            //截大图
            string imgpath = destPath + uniquename + ".bmp";// FileHelper.GetUniqueFileName(".jpg");
            ConvertImage(sourceFile, imgpath, imgsize, ImgstartInfo);

            //截小图
            imgpath = destPath + uniquename + "_thumb.jpg";
            DestImage = ConvertImage(sourceFile, imgpath, "80*80", ImgstartInfo);

        }
        return "";
    }

    private string ConvertImage(string sourceFile, string imgpath, string imgsize, System.Diagnostics.ProcessStartInfo ImgstartInfo)
    {
        ImgstartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
        /*参数设置
         * -y(覆盖输出文件,即如果生成的文件(flv_img)已经存在的话,不经提示就覆盖掉了)
         * -i 1.avi 输入文件
         * -f image2 指定输出格式
         * -ss 8 后跟的单位为秒,从指定时间点开始转换任务
         * -vframes
         * -s 指定分辨率
         */
        //duration: 00:00:00.00
        string[] time = VideoLength.Split(':');
        int seconds = int.Parse(time[0]) * 60 * 60 + int.Parse(time[1]) * 60 + int.Parse(time[2]);
        int ss = seconds > 5 ? 5 : seconds - 1;
        ImgstartInfo.Arguments = " -i " + sourceFile + " -y -f image2 -ss " + ss.ToString() + " -vframes 1 -s " + imgsize + " " + imgpath;
        try
        {
            System.Diagnostics.Process.Start(ImgstartInfo);
            return imgpath;
        }
        catch
        {
            return "";
        }
    }


    private string GetVideoDuration(string ffmpegfile, string sourceFile)
    {
        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);
            return duration;
        }
    }

    #endregion

    /// <summary>
    /// 执行一条command命令
    /// </summary>
    /// <param name="command">需要执行的Command</param>
    /// <param name="output">输出</param>
    /// <param name="error">错误</param>
    public  void ExecuteCommand(string command, out string output, out string error)
    {
        try
        {
            //创建一个进程
            Process pc = new Process();
            pc.StartInfo.FileName = command;
            pc.StartInfo.UseShellExecute = false;
            pc.StartInfo.RedirectStandardOutput = true;
            pc.StartInfo.RedirectStandardError = true;
            pc.StartInfo.CreateNoWindow = true;
            //启动进程
            pc.Start();
            //准备读出输出流和错误流
            string outputData = string.Empty;
            string errorData = string.Empty;
            pc.BeginOutputReadLine();
            pc.BeginErrorReadLine();

            pc.OutputDataReceived += (ss, ee) =>
            {
                outputData += ee.Data;
            };
            pc.ErrorDataReceived += (ss, ee) =>
            {
                errorData += ee.Data;
            };

            //等待退出
            pc.WaitForExit();
            //关闭进程
            pc.Close();
            //返回流结果
            output = outputData;
            error = errorData;
        }
        catch (Exception)
        {
            output = null;
            error = null;
        }
    }

    /// <summary>
    /// 获取视频的帧宽度和帧高度
    /// </summary>
    /// <param name="videoFilePath">mov文件的路径</param>
    /// <returns>null表示获取宽度或高度失败</returns>
    public  void GetMovWidthAndHeight(string videoFilePath, out int width, out int height)
    {
        try
        {
            //判断文件是否存在
            if (!File.Exists(videoFilePath))
            {
                width = 0;
                height = 0;
            }
            //执行命令获取该文件的一些信息 
            string ffmpeg = Application.StartupPath + "\\" + ffmpegpath; 
            string output;
            string error;
            ExecuteCommand("\"" + ffmpeg + "\"" + " -i " + "\"" + videoFilePath + "\"", out output, out error);
            if (string.IsNullOrEmpty(error))
            {
                width = 0;
                height = 0;
            }
            //通过正则表达式获取信息里面的宽度信息
            Regex regex = new Regex("(\\d{2,4})x(\\d{2,4})", RegexOptions.Compiled);
            Match m = regex.Match(error);
            if (m.Success)
            {
                width = int.Parse(m.Groups[1].Value);
                height = int.Parse(m.Groups[2].Value);
            }
            else
            {
                width = 0;
                height = 0;
            }
        }
        catch (Exception)
        {
            width = 0;
            height = 0;
        }
    }
}
发布了5 篇原创文章 · 获赞 3 · 访问量 2万+
展开阅读全文
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览