星火微课系统客户端
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

ZVideoRecordHelper.cs 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. using System;
  2. using System.Drawing.Imaging;
  3. using System.Drawing;
  4. using System.Runtime.InteropServices;
  5. using Accord.Video;
  6. using Accord.Video.FFMPEG;
  7. namespace XHWK.WKTool.Utils
  8. {
  9. using System.Linq;
  10. public class ZVideoRecordHelper
  11. {
  12. public enum RecordState
  13. {
  14. Stop = 0,
  15. Start = 1,
  16. Pause = 2
  17. }
  18. private RecordState _state = RecordState.Stop;
  19. private string _filePath;
  20. private int _width;
  21. private int _height;
  22. //录制帧率
  23. private int _rate = 5;
  24. //录制质量
  25. private int _quality = 8;
  26. private bool _captureMouse = false;
  27. private VideoFileWriter videoWriter = new VideoFileWriter();//视频写入
  28. private ScreenCaptureStream videoStreamer;//视频捕获
  29. public ZVideoRecordHelper(string filePath, int width, int height, int rate = 5, int quality = 8, bool captureMouse = false)
  30. {
  31. _filePath = filePath;
  32. _width = width / 2 * 2;
  33. _height = height / 2 * 2;
  34. _rate = rate;
  35. _quality = quality;
  36. _captureMouse = captureMouse;
  37. _state = RecordState.Pause;
  38. try
  39. {
  40. // 打开写入
  41. lock (this)
  42. {
  43. videoWriter.Open(
  44. _filePath,
  45. _width,
  46. _height,
  47. _rate,
  48. VideoCodec.MPEG4,
  49. _width * _height * _quality
  50. );
  51. }
  52. System.Drawing.Rectangle rec = new System.Drawing.Rectangle(0, 0, _width, _height);
  53. videoStreamer = new ScreenCaptureStream(rec, 1000 / _rate); //帧间隔需要和帧率关联,不然录的10秒视频文件不是10s
  54. videoStreamer.NewFrame += VideoNewFrame;
  55. videoStreamer.Start();
  56. }
  57. catch (Exception)
  58. {
  59. }
  60. }
  61. /// <summary>
  62. /// 开始录制
  63. /// </summary>
  64. public bool StartRecordVideo()
  65. {
  66. _state = RecordState.Start;
  67. return true;
  68. }
  69. [DllImport("user32.dll")]
  70. private static extern bool GetCursorInfo(out CURSORINFO pci);
  71. [StructLayout(LayoutKind.Sequential)]
  72. private struct POINT
  73. {
  74. public Int32 x;
  75. public Int32 y;
  76. }
  77. [StructLayout(LayoutKind.Sequential)]
  78. private struct CURSORINFO
  79. {
  80. public Int32 cbSize;
  81. public Int32 flags;
  82. public IntPtr hCursor;
  83. public POINT ptScreenPos;
  84. }
  85. // 帧返回时绘制上鼠标
  86. private void VideoNewFrame(object sender, NewFrameEventArgs e)
  87. {
  88. if (_state == RecordState.Start)
  89. {
  90. if (_captureMouse)
  91. {
  92. var g = System.Drawing.Graphics.FromImage(e.Frame);
  93. CURSORINFO pci;
  94. pci.cbSize = Marshal.SizeOf(typeof(CURSORINFO));
  95. GetCursorInfo(out pci);
  96. try
  97. {
  98. System.Windows.Forms.Cursor cur = new System.Windows.Forms.Cursor(pci.hCursor);
  99. cur.Draw
  100. (
  101. g,
  102. new System.Drawing.Rectangle
  103. (
  104. System.Windows.Forms.Cursor.Position.X - 10,
  105. System.Windows.Forms.Cursor.Position.Y - 10,
  106. cur.Size.Width,
  107. cur.Size.Height
  108. )
  109. );
  110. }
  111. catch { } //打开任务管理器时会导致异常
  112. }
  113. videoWriter.WriteVideoFrame(e.Frame);
  114. }
  115. }
  116. /// <summary>
  117. /// 结束录制
  118. /// </summary>
  119. public void StopRecordVideo()
  120. {
  121. _state = RecordState.Stop;
  122. // 停止
  123. videoStreamer.Stop();
  124. //结束写入
  125. videoWriter.Close();
  126. videoWriter.Dispose();
  127. }
  128. /// <summary>
  129. /// 暂停录制
  130. /// </summary>
  131. public void PauseRecordVideo()
  132. {
  133. _state = RecordState.Pause;
  134. }
  135. /// <summary>
  136. /// 恢复录制
  137. /// </summary>
  138. public void ResumeRecordVideo()
  139. {
  140. _state = RecordState.Start;
  141. }
  142. /// <summary>
  143. /// 生成缩略图
  144. /// </summary>
  145. /// <param name="mp4Path"></param>
  146. /// <param name="picPath"></param>
  147. public static void GetVideoPic(string mp4Path, string picPath)
  148. {
  149. using (var video = new VideoFileReader())
  150. {
  151. video.Open(mp4Path);
  152. int frameNum = video.FrameCount > 3 ? 3 : 0;
  153. using (var bmp = video.ReadVideoFrame(frameNum))
  154. {
  155. SaveAsJpeg
  156. (
  157. bmp,
  158. picPath,
  159. 90
  160. );
  161. }
  162. video.Close();
  163. }
  164. }
  165. // 保存为jpeg格式,quality为图像质量(0-100)
  166. public static void SaveAsJpeg
  167. (
  168. Bitmap bitmap,
  169. string fileName,
  170. int quality
  171. )
  172. {
  173. var jpegEncoder = ImageCodecInfo.GetImageEncoders().First(codec => codec.FormatID == ImageFormat.Jpeg.Guid);
  174. var encoderParameters = new EncoderParameters(1);
  175. encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, quality);
  176. bitmap.Save
  177. (
  178. fileName,
  179. jpegEncoder,
  180. encoderParameters
  181. );
  182. }
  183. }
  184. }