基于AForge实现C#摄像头视频录制功能
本文为大家分享了AForge实现C#摄像头视频录制功能的具体方法,供大家参考,具体内容如下
1. 概述
最近由于兴趣学习了下在C#上使用AForge录制摄像头视频并压缩编码。总体上来说这个第三方.net视觉开发库还是比较稳定的(AForge lib下载、离线帮助文档下载)。但是由于这个第三方库维护不怎么样,导致会出现不兼容的问题。这里将这些与大家分享,希望对您有帮助。
在使用AForge第三方库录制本地视频所要使用到的类主要有这几个:FilterInfoCollection、VideoCaptureDevice、VideoSourcePlayer、VideoFileWriter。下面我就简单的介绍一下这几个类涉及到的方法等。
FilterInfoCollection:
该类主要是用于摄像头视频输入设备列表检测的。是继承自C#中的System.Collections.CollectionBase类。
这是离线帮助文档上对这个类的调用方式:
其中构造函数传递进去的参数是需要采集的信号的类型,他还有其他的输入类型(如声音等):
VideoCaptureDevice:
这是该类中的一些成员函数和变量
这个类便是要选择了视频输入的设备了,他的构造函数是
在实际的使用过程中可能会存在多个设备的情况,便可以通过第二个参数进行输入设备的指定。初始化是这样的
在本例子的实际使用过程中对上面该类事件NewFrame函数进行了响应,然后提取出当前帧。
VideoSourcePlayer:
该类是AForge.Control中的类,是控件中调用的,这里将它添加进来是为了作为拍照功能使用的,这里就不做介绍了。
VideoFileWriter:
该类是视频写操作类,主要实现视频文件的压缩和写入到文件中。
本例子中先使用VideoFileWriter.Open()函数设定录制视频的高度、宽度、帧率、编码类型。
这是该第三方类库支持的视频编码格式
然后使用下面这个函数就可以将当前帧写入到视频文件中了。
2. 实现
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Timers; //using AForge using AForge; using AForge.Video; using AForge.Video.DirectShow; using AForge.Video.FFMPEG; using AForge.Controls; namespace video_record { public partial class Form1 : Form { public Form1() { InitializeComponent(); } //关闭窗口响应函数 private void button2_Click(object sender, EventArgs e) { if (this.writer.IsOpen) { MessageBox.Show("视频流还没有写完,请点击结束录制。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } this.videoSource.SignalToStop(); this.videoSource.WaitForStop(); this.videoSourcePlayer.SignalToStop(); this.videoSourcePlayer.WaitForStop(); this.Hide(); this.Close(); this.Dispose(); } private FilterInfoCollection videoDevices; //摄像头设备 private VideoCaptureDevice videoSource; //视频的来源选择 private VideoSourcePlayer videoSourcePlayer; //AForge控制控件 private VideoFileWriter writer; //写入到视频 private bool is_record_video = false; //是否开始录像 System.Timers.Timer timer_count; int tick_num = 0; //窗体初始化函数 private void Form1_Load(object sender, EventArgs e) { this.label5.Visible = false; this.videoSourcePlayer = new AForge.Controls.VideoSourcePlayer(); this.videoSource = new VideoCaptureDevice(); this.writer = new VideoFileWriter(); //设置视频编码格式 this.comboBox_videoecode.Items.Add("Raw"); this.comboBox_videoecode.Items.Add("MPEG2"); this.comboBox_videoecode.Items.Add("FLV1"); this.comboBox_videoecode.Items.Add("H263p"); this.comboBox_videoecode.Items.Add("MSMPEG4v3"); this.comboBox_videoecode.Items.Add("MSMPEG4v2"); this.comboBox_videoecode.Items.Add("WMV2"); this.comboBox_videoecode.Items.Add("WMV1"); this.comboBox_videoecode.Items.Add("MPEG4"); this.comboBox_videoecode.SelectedIndex = 1; //设置视频来源 try { // 枚举所有视频输入设备 videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice); if (videoDevices.Count == 0) throw new ApplicationException(); //没有找到摄像头设备 foreach (FilterInfo device in videoDevices) { this.comboBox_camera.Items.Add(device.Name); } //this.comboBox_camera.SelectedIndex = 0; //注释掉,选择摄像头来源的时候才会才会触发显示摄像头信息 } catch (ApplicationException) { videoDevices = null; MessageBox.Show("没有找到摄像头设备", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } //秒表 this.timer_count = new System.Timers.Timer(); //实例化Timer类,设置间隔时间为10000毫秒; this.timer_count.Elapsed += new System.Timers.ElapsedEventHandler(tick_count); //到达时间的时候执行事件; this.timer_count.AutoReset = true; //设置是执行一次(false)还是一直执行(true); this.timer_count.Interval = 1000; } //视频源选择下拉框选择之后的响应函数 private void comboBox_camera_SelectedIndexChanged(object sender, EventArgs e) { int selected_index = this.comboBox_camera.SelectedIndex; this.videoSource = new VideoCaptureDevice(videoDevices[selected_index].MonikerString); // set NewFrame event handler videoSource.NewFrame += new NewFrameEventHandler(show_video); videoSource.Start(); videoSourcePlayer.VideoSource = videoSource; videoSourcePlayer.Start(); this.label5.Text = "连接中..."; this.label5.Visible = true; isshowed = true; } bool isshowed = true; //新帧的触发函数 private void show_video(object sender, NewFrameEventArgs eventArgs) { if (isshowed) { this.label5.Visible = false; isshowed = false; } Bitmap bitmap = eventArgs.Frame; //获取到一帧图像 pictureBox1.Image = Image.FromHbitmap(bitmap.GetHbitmap()); if (is_record_video) { writer.WriteVideoFrame(bitmap); } } //拍摄图像按钮响应函数 private void button1_Click(object sender, EventArgs e) { if (this.videoSource.IsRunning && this.videoSourcePlayer.IsRunning) { Bitmap bitmap = this.videoSourcePlayer.GetCurrentVideoFrame(); bitmap.Save("img.jpeg", System.Drawing.Imaging.ImageFormat.Jpeg); } else MessageBox.Show("摄像头没有运行", "错误", MessageBoxButtons.OK, MessageBoxIcon.Information); } //开始录像按钮响应函数 private void button_start_Click(object sender, EventArgs e) { int width = 640; //录制视频的宽度 int height = 480; //录制视频的高度 int fps = 9; //创建一个视频文件 String video_format = this.comboBox_videoecode.Text.Trim(); //获取选中的视频编码 if (this.videoSource.IsRunning && this.videoSourcePlayer.IsRunning) { if (-1 != video_format.IndexOf("MPEG")) { writer.Open("test.avi", width, height, fps, VideoCodec.MPEG4); } else if (-1 != video_format.IndexOf("WMV")) { writer.Open("test.wmv", width, height, fps, VideoCodec.WMV1); } else { writer.Open("test.mkv", width, height, fps, VideoCodec.Default); } } else MessageBox.Show("没有视频源输入,无法录制视频。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); timer_count.Enabled = true;//是否执行System.Timers.Timer.Elapsed事件; this.label5.Visible = true; this.label5.Text = "REC"; this.is_record_video = true; } //停止录制视频响应函数 private void button_stop_Click(object sender, EventArgs e) { this.label5.Visible = false; this.is_record_video = false; this.writer.Close(); this.timer_count.Enabled = false; tick_num = 0; } //暂停按钮响应函数 private void button3_Click(object sender, EventArgs e) { if (this.button3.Text.Trim() == "暂停录像") { this.is_record_video = false; this.label5.Visible = false; this.button3.Text = "恢复录像"; timer_count.Enabled = false; //暂停计时 return; } if (this.button3.Text.Trim() == "恢复录像") { this.is_record_video = true; timer_count.Enabled = true; //恢复计时 this.label5.Visible = true; this.button3.Text = "暂停录像"; } } //计时器响应函数 public void tick_count(object source, System.Timers.ElapsedEventArgs e) { tick_num++; int temp = tick_num; int sec = temp % 60; int min = temp / 60; if (60 == min) { min = 0; min++; } int hour = min / 60; String tick = hour.ToString() + ":" + min.ToString() + ":" + sec.ToString(); this.label4.Text = tick; } } }
3. 结果
4. 错误和注意事项
1. 在使用AForge这个软件过程中需要的不仅仅是将Release文件夹下对应的lib添加到项目的引用中,在进行视频压缩编码的时候需要将External文件夹下的相关lib添加到程序运行的Debug目录下
2. 在使用的时候会遇到这个错误“混合模式程序集是针对“v2.0.50727”版的运行时生成的,在没有配置其他信息的情况”的错误。这是因为.net框架不兼容的问题,AForge使用的比较老好像是2.0的。。。-_-||。所以需要在App.config对其进行配置,使其对前版本的兼容,配置如下(这是我添加的配置):
<startup useLegacyV2RuntimeActivationPolicy="true"> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/> <supportedRuntime version="v2.0.50727"/> </startup>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持猪先飞。
相关文章
- 我们在使用C#做项目的时候,基本上都需要制作登录界面,那么今天我们就来一步步看看,如果简单的实现登录界面呢,本文给出2个例子,由简入难,希望大家能够喜欢。...2020-06-25
- 这篇文章主要介绍了C# 字段和属性的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下...2020-11-03
- 这篇文章主要介绍了C#中截取字符串的的基本方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-03
- 本文给大家分享C#连接SQL数据库和查询数据功能的操作技巧,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友参考下吧...2021-05-17
- 这篇文章主要介绍了C#实现简单的Http请求的方法,以实例形式较为详细的分析了C#实现Http请求的具体方法,需要的朋友可以参考下...2020-06-25
- 本文主要介绍了C#中new的几种用法,具有很好的参考价值,下面跟着小编一起来看下吧...2020-06-25
使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序)
这篇文章主要介绍了使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25- 这篇文章主要介绍了C#开发Windows窗体应用程序的简单操作步骤,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-12
- 这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2021-01-16
- 最近做一个小项目不可避免的需要前端脚本与后台进行交互。由于是在asp.net中实现,故问题演化成asp.net中jiavascript与后台c#如何进行交互。...2020-06-25
- 这篇文章主要用实例讲解C#递归算法的概念以及用法,文中代码非常详细,帮助大家更好的参考和学习,感兴趣的朋友可以了解下...2020-06-25
- 本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
- 轻松学习C#的基础入门,了解C#最基本的知识点,C#是一种简洁的,类型安全的一种完全面向对象的开发语言,是Microsoft专门基于.NET Framework平台开发的而量身定做的高级程序设计语言,需要的朋友可以参考下...2020-06-25
- 本文主要介绍了C#变量命名规则小结,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-09
- 这篇文章主要介绍了c#中(&&,||)与(&,|)的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
- 这篇文章主要介绍了C#绘制曲线图的方法,以完整实例形式较为详细的分析了C#进行曲线绘制的具体步骤与相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
- 本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
- 这篇文章主要介绍了c#自带缓存使用方法,包括获取数据缓存、设置数据缓存、移除指定数据缓存等方法,需要的朋友可以参考下...2020-06-25
- 下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
- 这篇文章主要介绍了C#中list用法,结合实例形式分析了C#中list排序、运算、转换等常见操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25