利用Mplayer 实现视频连拍

来源:互联网 发布:微信扫号软件 编辑:程序博客网 时间:2024/04/27 15:26

主要利用Mplayer 作视频截图,先前试过ffmpeg 但是截一张指定较长时间的视频很慢如:截取20:00:00等半天才截出图片来,所以换了mplayer 来做,很快就截取了视频图片

因此采用了Mplayer 来做。

主要代码如下:

using System;
using System.IO;
using System.Drawing;
using System.Diagnostics;
using System.Windows.Forms;
using System.Threading;
using System.Text.RegularExpressions;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections.Generic;
namespace CatchVideoImage
{
    /// <summary>
    /// 提供一个视频截图的基类
    /// </summary>
   public abstract class VideoImageExcute
    {
        #region Fields
        public string ExeMplayer = @"C:\Program Files\ScreenShots\MPlayer.exe";
        public string SaveimageFolder = Application.StartupPath + @"\VideoImage";//截图后保存文件夹
        string getLengthArgs = "-nofs -noframedrop -identify -nosound -vo direct3d ";//获取视频长度参数
        ManualResetEvent GetLenNotify = new ManualResetEvent(false);//一个获取长度的等待
        protected ManualResetEvent notifyDrawChild;//一个绘图等待
        protected ManualResetEvent notifySaveImgThumb=new ManualResetEvent(false);//一个绘图等待
        protected int imageCount = 10;//默认图片数
        protected int spitTime;//影片中的时间间隔
        protected string identityImageHander;//递增图片头
        protected int flagNo = 1;//图片增加种子标志
        protected string mediaPath;//影片路径
        int videoLenValue;//影片长度
        Font TimeFont=new Font("宋体",30,FontStyle.Bold);//图片中绘时间字体
        int TempImageCount = 0;//临时存放图片总数
       protected List<string> TimeList = new List<string>();
       public ProgressBar ExcuteProgressBar;//进度条
       protected bool isReadOlayScreenshots = false;
       protected bool SlingThumb = false;//首张略缩截图
        #endregion

      public abstract string MediaPath{get;set;}
       /// <summary>
       /// 获取影片长度
       /// </summary>
      protected int GetVideoLength
      {
          get
          {

              CreateMplayer();
              Process ps = CreateProcess(GetMediaLength);
              ps.Start();
              ps.BeginOutputReadLine();
              GetLenNotify.WaitOne();
              return videoLenValue;
          }
      }
       /// <summary>
       /// 图片自增头
       /// </summary>
      public abstract string IdentityImageHander { get; set; }
       /// <summary>
       /// 图片时间分隔
       /// </summary>
      protected abstract int SpitTime { get; set; }
       /// <summary>
       /// 图片总量
       /// </summary>
      public abstract int ImageCount { get; set; }
       /// <summary>
       /// 开始截图拼图
       /// </summary>
      protected void CupImage()
      {
          GetLenNotify.WaitOne();

          TempImageCount = ImageCount;
          flagNo = 1;
          TimeList.Clear();
          if (ExcuteProgressBar != null)
          {
               
              if(isReadOlayScreenshots)
              ExcuteProgressBar.Maximum = ImageCount;
                  else
              ExcuteProgressBar.Maximum = ImageCount * 2;
              ExcuteProgressBar.Value = 0;
          }

          DeleteFullFile();
          Process cupProcess = CreateProcess(GetTimeJpgArgs(spitTime * flagNo));
          cupProcess.Start();
          cupProcess.BeginOutputReadLine();
          TempImageCount--;
      }
      /// <summary>
      /// 删除所有文件
      /// </summary>
     protected  void DeleteFullFile()
      {
          if (!Directory.Exists(SaveimageFolder))
              Directory.CreateDirectory(SaveimageFolder);
          foreach (string item in Directory.GetFiles(SaveimageFolder))
          {
              File.Delete(item);
          }
      }
      /// <summary>
      /// 产生一个可用进程
      /// </summary>
      /// <param name="args"></param>
      /// <returns></returns>
     public Process CreateProcess(string args)
      {
          Process ps = new Process();

          ps.StartInfo.FileName = ExeMplayer;
          ps.StartInfo.RedirectStandardOutput = true;
          ps.StartInfo.UseShellExecute = false;
          ps.StartInfo.WorkingDirectory = SaveimageFolder;
          ps.StartInfo.CreateNoWindow = true;
          ps.StartInfo.Arguments = args;
          ps.OutputDataReceived += new DataReceivedEventHandler(MoiveDataReceive);
          return ps;
      }
  
      void MoiveDataReceive(object sender, DataReceivedEventArgs e)
      {
          if (!string.IsNullOrEmpty(e.Data))
          {
              ReceiveData(sender, e);
          }
      }
       /// <summary>
       /// 一个进程异步接收
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
      private void ReceiveData(object sender, DataReceivedEventArgs e)
      {
          if (e.Data.IndexOf("ID_LENGTH") >= 0)
          {
              Match math = Regex.Match(e.Data, @"\d+");
              videoLenValue = Convert.ToInt32(math.Value);
              (sender as Process).Kill();
              GetLenNotify.Set();
          }
          else if (e.Data.IndexOf("Exiting") >= 0 && TempImageCount >= 0)
          {
              string tempImagePath=SaveimageFolder + @"\00000001.jpg";
              if(!SlingThumb)
              DrawTimeImage(tempImagePath);
              File.Move(tempImagePath, SaveimageFolder + @"\" +IdentityImageHander+flagNo + ".jpg");


              if (!SlingThumb)
              {
                  if (ExcuteProgressBar != null)
                      ExcuteProgressBar.Value = flagNo;
                  flagNo++;
                  TempImageCount--;
                  if (TempImageCount >= 0)
                  {
                      Process ps = CreateProcess(GetTimeJpgArgs(flagNo * spitTime));
                      ps.Start();
                      ps.BeginOutputReadLine();
                      Process orgPs = (sender as Process);
                      if (!orgPs.HasExited)
                          orgPs.Kill();
                  }
                  else
                      notifyDrawChild.Set();
              }
              else
              notifySaveImgThumb.Set();
            
             
          }
      }
       /// <summary>
       /// 在图片上绘制时间
       /// </summary>
       /// <param name="imgPath"></param>
      void DrawTimeImage(string imgPath)
      {
          MemoryStream ms = new MemoryStream();
          BinaryFormatter bf = new BinaryFormatter();

          int newWidth;
          int newHeight;
          using (Bitmap bitmap=new Bitmap(imgPath))
          {
              using (Graphics g=Graphics.FromImage(bitmap))
              {
                string timeMsg=GetTime(spitTime * flagNo);
                SizeF sf = g.MeasureString(timeMsg, TimeFont);
                PointF pf = new PointF(bitmap.Width - sf.Width, bitmap.Height - sf.Height);
                g.DrawString(timeMsg, TimeFont, Brushes.White, pf);
                TimeList.Add(timeMsg);
                newWidth=bitmap.Width;
                newHeight=bitmap.Height;
                bf.Serialize(ms,bitmap);
                ms.Seek(0, SeekOrigin.Begin);
              }
          }

          using (Bitmap newBitMap=(Bitmap)bf.Deserialize(ms))
          {
              newBitMap.Save(imgPath);
          }

      }
       /// <summary>
       /// 获取时间 格式为:hh:mm:ss
       /// </summary>
       /// <param name="ss"></param>
       /// <returns></returns>
     protected string GetTime(int ss)
      {
          string h = ss / 60 > 60 ? (ss / 60 * 2).ToString().Length==1?"0"+(ss / 60 * 2).ToString()
              : (ss / 60 * 2).ToString() : "00";
          string m = ss / 60 > 60 ? (ss % 60).ToString().Length == 1 ? "0" + (ss % 60).ToString() : (ss % 60).ToString()
              : (ss / 60).ToString().Length == 1 ? "0"+(ss / 60).ToString() : (ss / 60).ToString();
          string s = ss > 60 ? (ss % 60).ToString().Length == 1 ? "0" + (ss % 60).ToString()
              : (ss % 60).ToString() : ss.ToString().Length == 1 ? "0" + ss.ToString() : ss.ToString();
          return h + ":" + m + ":" + s;
      }

      string GetMediaLength
      {
          get {
              return getLengthArgs + "\""+MediaPath+"\"";
          }
      }
       /// <summary>
       /// 获图方示
       /// </summary>
       /// <param name="ss">时间 </param>
       /// <returns></returns>
     public string GetTimeJpgArgs(int ss)
      {
          return "-nofs -ss " + ss + " -noquiet -noframedrop -nosound -vo jpeg -frames 1 " + "\"" + MediaPath + "\"";
      }

       /// <summary>
       /// 创建一个Mplayer 文件目录
       /// </summary>
     public void CreateMplayer()
      {
            string directoryInfo=Path.GetDirectoryName(ExeMplayer);
        
              if(!Directory.Exists(directoryInfo))
              {
                    Directory.CreateDirectory(directoryInfo);
                    CreateMplayer();
              }else if(!File.Exists(ExeMplayer))
              {
                  CreateMplayerFile();
              }
      }
       /// <summary>
       /// 创建Mplayer 文件
       /// </summary>
      private void CreateMplayerFile()
      {
          byte[] buffBytes = Properties.Resources.mplayer;
          using (FileStream fs = File.Create(ExeMplayer))
          {
              fs.Write(buffBytes, 0, buffBytes.Length);
          }
      }

    }
}

using System;
using System.Drawing;
using System.Diagnostics;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace CatchVideoImage
{
    /// <summary>
    /// 一个图片绘制类
    /// </summary>
   public class DrawVideoImage:VideoImageExcute
    {
 
       public DrawVideoImage(DrawGrid drawGrid,string mediaPath)
       {
           DrawImageMedia(drawGrid,mediaPath);
           SetBottmTimeFont = new Font("黑体", drawGrid.ContentSize / 10, FontStyle.Bold);
           SlingThumb = false;
       }

       private void DrawImageMedia(string mediaPath)
       {
           if (!File.Exists(mediaPath))
               throw new ArgumentException("指定文件不存在!");
           MediaPath = mediaPath;
           videoLength = base.GetVideoLength;
           IdentityImageHander = "VideoImage_";
           SpitTime = videoLength / ImageCount;
       }
       /// <summary>
       /// 绘制图片
       /// </summary>
       /// <param name="drawGrid"></param>
       /// <param name="mediaPath"></param>
       private void DrawImageMedia(DrawGrid drawGrid, string mediaPath)
       {
         
           drawGridObj = drawGrid;
           drawGridMap = drawGrid.GetGridBitMap();
           if (!File.Exists(mediaPath))
               throw new ArgumentException("指定文件不存在!");
           this.MediaPath = mediaPath;
           videoLength = base.GetVideoLength;

           IdentityImageHander = "VideoImage_";
           SpitTime = videoLength / drawGrid.ImagePos.Count;
           ImageCount = spitTime == 0 ? videoLength : drawGrid.ImagePos.Count;
       }

       #region Fields
       int videoLength;
       ManualResetEvent notifyDraw = new ManualResetEvent(false);  //一个通知绘制
      
       public int VideoLength
       {
           get { return videoLength; }
       }
       DrawGrid drawGridObj;//一个绘图表格对象
       Bitmap drawGridMap; //一张可用于绘制的整图
       Font SetBottmTimeFont = new Font("黑体",10, FontStyle.Bold);//时间字体
       System.Windows.Forms.Timer clockTime=new  System.Windows.Forms.Timer();//一个处理用时计时器
       public Label info; //信息标签
       DateTime dateTime;
       Action<Bitmap> thumbComplete;//当视频进入后的一张略缩图

       public Action<Bitmap> ThumbComplete
       {
           get { return thumbComplete; }
           set { thumbComplete = value; }
       }

       #endregion

       public override string MediaPath
       {
           get
           {return base.mediaPath;}
           set
           {base.mediaPath = value;}
       }
      public bool IsReadOlayScreenshots
       {
           set {
               base.isReadOlayScreenshots = value;
           }
       }
       public ProgressBar ExcuteBar
       {
           get { return base.ExcuteProgressBar; }
           set {
               base.ExcuteProgressBar = value;
           }
       }
       public override string IdentityImageHander
       {
           get
           {
               return base.identityImageHander;
           }
           set
           {
               identityImageHander=value;
           }
       }
       public override int ImageCount
       {
           get
           {
               return imageCount;
           }
           set
           {
               if (VideoLength < value)
                   imageCount = VideoLength;
               else
               imageCount=value;
               SpitTime = videoLength / ImageCount;
           }
       }

       public  string SaveFolder
       {
           set
           {
               base.SaveimageFolder = value;
           }
       }
       protected override int SpitTime
       {
           get
           {
               return spitTime;
           }
           set
           {
               spitTime = value;
           }
       }
       /// <summary>
       /// 开始截拼图
       /// </summary>
       public void CapImagExcute()
       {
           dateTime = DateTime.Now;
           clockTime.Interval = 500;
           clockTime.Start();
           clockTime.Tick += new EventHandler(clockTime_Tick);
           ThreadPool.QueueUserWorkItem((o) => {
               base.notifyDrawChild = notifyDraw;
               base.CupImage();
           });

           ThreadPool.QueueUserWorkItem(
               (o)=>{
        DrawPictuce();});

        
       }
      
       void clockTime_Tick(object sender, EventArgs e)
       {
           TimeSpan ts= (DateTime.Now-dateTime);

           info.Text = "已用时:" + ts.Hours.ToString() + ":" + ts.Minutes.ToString() + ":" + ts.Seconds;//base.GetTime(totalSS);
       }

       private void DrawPictuce()
       {
           notifyDraw.WaitOne();
           if (!base.isReadOlayScreenshots)
               DrawFullImage();
           else
           {
               clockTime.Stop();
               MessageBox.Show("完成");
           }
       }
       //绘制图片到各个标点
       private void DrawFullImage()
       {
           BinaryFormatter bf = new BinaryFormatter();
           for (int i = 0; i < ImageCount; i++)
           {
               ExcuteBar.Value += 1;
               string imgPath = SaveimageFolder + @"\" + IdentityImageHander + (i + 1).ToString() + ".jpg";

             
               using (MemoryStream ms = new MemoryStream())
               {
                   try
                   {
                       using (Image img = Image.FromFile(imgPath))
                       {
                           bf.Serialize(ms, img);
                       }

                       File.Delete(imgPath);
                       using (Graphics grap = Graphics.FromImage(drawGridMap))
                       {
                           ms.Seek(0, SeekOrigin.Begin);
                           using (Image newImg = bf.Deserialize(ms) as Image)
                           {
                               grap.DrawImage(newImg, drawGridObj.ImagePos[i].X, drawGridObj.ImagePos[i].Y,
                                   drawGridObj.ContentSize,
                                   drawGridObj.ContentSize - drawGridObj.offSizeH);
                           
                               SizeF sf = grap.MeasureString(base.TimeList[i], SetBottmTimeFont);
                               PointF pf = new PointF(drawGridObj.ImagePos[i].X + drawGridObj.ContentSize - sf.Width,
                                   drawGridObj.ImagePos[i].Y + drawGridObj.ContentSize - drawGridObj.offSizeH);
                               grap.DrawString(base.TimeList[i], SetBottmTimeFont, Brushes.White, pf);


                           }
                       }
                   }
                   catch (Exception ex)
                   {
                       MessageBox.Show(ex.Message);
                   }
               }

           }

           drawGridMap.Save(SaveimageFolder + @"\NewVideoImage.jpg");
           clockTime.Stop();
           if (ThumbComplete != null)
               thumbComplete(GetThumbBitmap());
           MessageBox.Show("成功!");
       }
       public Bitmap GetThumbBitmap()
       {
           BinaryFormatter bf = new BinaryFormatter();
           Bitmap ReturnBitmap;

           using (MemoryStream ms = new MemoryStream())
           {
               using (Image img = Image.FromFile(SaveimageFolder + @"\NewVideoImage.jpg"))
               {
                   bf.Serialize(ms, img);
                   ms.Seek(0, SeekOrigin.Begin);
               }
               //File.Delete(SaveimageFolder + @"\Thumb_1.jpg");
               ReturnBitmap = (Bitmap)bf.Deserialize(ms);//new Bitmap(ms);
           }
           return ReturnBitmap;
       }

 


    }
}

using System;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.Serialization.Formatters.Binary;
namespace CatchVideoImage
{
    /// <summary>
    /// 略缩图类
    /// </summary>
   public class VideoImageThumb:VideoImageExcute
    {
       public VideoImageThumb()
       {
           MediaPath = string.Empty;
           IdentityImageHander = "Thumb_";
           SpitTime = 1;
           ImageCount = 1;
           DeleteFullFile();
           SlingThumb = true;
       }
       public void DelFullFile()
       {
           base.DeleteFullFile();
       }
       public Bitmap GetThumbBitmap()
       {
           BinaryFormatter bf = new BinaryFormatter();
           Bitmap ReturnBitmap;
           using (MemoryStream ms=new MemoryStream())
           {
               using (Image img = Image.FromFile(SaveimageFolder + @"\Thumb_1.jpg"))
               {
                   bf.Serialize(ms, img);
                   ms.Seek(0, SeekOrigin.Begin);
               }
               File.Delete(SaveimageFolder + @"\Thumb_1.jpg");
               ReturnBitmap = (Bitmap)bf.Deserialize(ms);
           }
           return ReturnBitmap;
       }

       public void WaitSetOne()
       {
          notifySaveImgThumb.Reset();
           notifySaveImgThumb.WaitOne();
       }
        
 
        public override string MediaPath
        {
            get
            {
                return base.mediaPath;
            }
            set
            {
                base.mediaPath = value;
            }
        }

        public override string IdentityImageHander
        {
            get
            {
                return base.identityImageHander;
            }
            set
            {
                base.identityImageHander = value;
            }
        }

        protected override int SpitTime
        {
            get
            {
                return base.spitTime;
            }
            set
            {
                base.spitTime = value;
            }
        }

        public override int ImageCount
        {
            get
            {
                return base.imageCount;
            }
            set
            {
                base.imageCount = value;
            }
        }
    }
}

using System;
using System.Drawing;
using System.Collections.Generic;
namespace CatchVideoImage
{
   public class DrawGrid
    {
      public DrawGrid(GridRowsCols rowsCols)
       {
           IntRowsCols(rowsCols);
           offsetPointY = (int)((contentSize * serNum)/2f);
           offSizeH = (int)(contentSize * serNum);
       }

      private float serNum = 0.3f;
      private int splitLineSize=5;//分隔线大小
      private int rows=5;//行数
      private int cols=10;//列数
      private int contentSize = 500;//分块图片大小
      private int offsetPointY;//Y坐标偏移
      public int offSizeH;//高度偏移
      Bitmap  drawBitmap;
      Color gridColor = Color.White;

      public Color GridColor
      {
          get { return gridColor; }
          set { gridColor = value; }
      }
      List<Point> imagePos = new List<Point>();
  
      public List<Point> ImagePos
      {
          get { return imagePos; }
          set { imagePos = value; }
      }

      public int ContentSize
      {
          get { return contentSize; }
          set {
              contentSize = value;
              offsetPointY = (int)((contentSize * serNum) / 2f);
              offSizeH = (int)(contentSize * serNum);

              }
      }

      public int SplitLineSize
      {
          get { return splitLineSize; }
          set { splitLineSize = value; }
      }

      public Bitmap GetGridBitMap()
      {
          Size size= GetBitmapSize(cols, rows);
          int bitmapWidth =size.Width;
          int bitmapHeight = size.Height;
    
           drawBitmap = new Bitmap(bitmapWidth, bitmapHeight);
           ImagePos.Clear();

           using (Graphics g = Graphics.FromImage(drawBitmap))
           {
               g.Clear(Color.Gray);
               DrawGridView(g, cols, rows,1);
           }
           return drawBitmap;
      }
 
       /// <summary>
       /// 递归调用绘线
       /// </summary>
       /// <param name="bitmapG"></param>
       /// <param name="col"></param>
       /// <param name="row"></param>
       void DrawGridView(Graphics bitmapG, int col, int row,int rowOffset)
      {
          
              col= col < 0 ? 0 : col;
              row = row < 0 ? 0 : row;
              Size size= GetBitmapSize(col,row);
              int y=size.Height;
              int x = size.Width;
              using (Pen p=new Pen(new SolidBrush(gridColor),splitLineSize))
              {
                  bitmapG.DrawLine(p, 0, y -G_Int , drawBitmap.Width, y - G_Int);//绘横线
                  bitmapG.DrawLine(p, x - G_Int, 0, x - G_Int, drawBitmap.Height);//绘纵线
              }
              if (row > 0)
              {
               
                  for (int i = 1; i <= cols; i++)//添加点
                  {
                      Point orgPoint = new Point(GetBitmapSize(i, i).Width - G_Int - G_Int,
                         GetBitmapSize(i, rowOffset).Height - G_Int - G_Int);
                      Size sizePoint = new Size(contentSize-1 , contentSize - offsetPointY);
                      Point newPoint = Point.Subtract(orgPoint, sizePoint);
                      ImagePos.Add(newPoint);
                   
                  }
              }

              if (col == 0 && row == 0)
                  return;

                  --col;
                  --row;
                  rowOffset++;
                  DrawGridView(bitmapG, col, row,rowOffset);
             
      }
       /// <summary>
       /// 分隔线
       /// </summary>
       int G_Int
       {
           get
           {
               double d = splitLineSize / 2d;
               return (int)Math.Ceiling(d);
           }
       }
   
       /// <summary>
       /// 获取高宽度
       /// </summary>
       /// <param name="col"></param>
       /// <param name="row"></param>
       /// <returns></returns>
       Size GetBitmapSize(int col,int row)
       {
           int x = col * contentSize + col * splitLineSize +splitLineSize;
           int  y= row * contentSize + row * splitLineSize + splitLineSize;
           Size size = new Size(x,y);

           return size;
       }

       void IntRowsCols(GridRowsCols rowsCols)
       {

           switch (rowsCols)
           {
               case GridRowsCols.Rows_18_Cols_25:
               
                   rows = 18;
                   cols = 25;
                   break;
               case GridRowsCols.Rows_18_Cols_23:
                   rows = 18;
                   cols = 23;
                   break;
               case GridRowsCols.Rows_17_Cols_22:
                   rows = 17;
                   cols = 22;
                   break;
               case GridRowsCols.Rows_16_Cols_20:
                   rows = 16;
                   cols = 20;
                   break;
               case GridRowsCols.Rows_15_Cols_19:
                   rows = 15;
                   cols = 19;
                   break;
               case GridRowsCols.Rows_15_Cols_17:
                   rows = 15;
                   cols = 17;
                   break;
               case GridRowsCols.Rows_13_Cols_15:
                   rows = 13;
                   cols = 15;
                   break;
               case GridRowsCols.Rows_12_Cols_15:
                   rows = 12;
                   cols = 15;
                   break;
               case GridRowsCols.Rows_10_Cols_15:
                   rows = 10;
                   cols = 15;
                   break;
               case GridRowsCols.Rows_8_Cols_12:
                   rows = 8;
                   cols = 12;
                   break;
               case GridRowsCols.Rows_6_Cols_11:
                   rows = 6;
                   cols = 11;
                   break;
               case GridRowsCols.Rows_5_Cols_10:
                   rows = 5;
                   cols = 10;
                   break;
               case GridRowsCols.Rows_5_Cols_6:
                   rows = 5;
                   cols = 6;
                   break;
               case GridRowsCols.Rows_3_Cols_5:
                   rows = 3;
                   cols = 5;
                   break;
               case GridRowsCols.Rows_2_Cols_5:
                   rows = 2;
                   cols = 5;
                   break;
               default:
                   rows = 2;
                   cols = 3;
                   break;
           }
       }


    }
}

 

上张效果图

原创粉丝点击