使用AForge Video进行录像
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
using System.IO;//Path、Directory用到
using System.Timers;
using AForge;
using AForge.Video;
using AForge.Video.DirectShow;
using AForge.Video.FFMPEG;
using AForge.Controls;
namespace AforgeVideo
{
public partial class Form1 : Form
{
private delegate void MyDelegateUI();//多线程问题
public FilterInfoCollection videoDevices = null; //摄像头设备
public VideoCaptureDevice cam1 = null; //视频的来源选择
public VideoFileWriter videoWriter = null;//写入到视频
public Bitmap bm1 = null;
Boolean is_record_video = false;
Boolean ifCam1 = false;
int i = 1; //摄像头数
int hour = 0;
int tick_num = 0;
int width = 640; //录制视频的宽度
int height = 480; //录制视频的高度
int fps = 20; //正常速率,fps越大速率越快,相当于快进
System.Timers.Timer timer_count;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//初始化按钮状态
labelScreen.Visible = false;
btnPauseVideo.Enabled = false;
btnStartVideo.Enabled = false;
btnStopVideo.Enabled = false;
btnTakePic.Enabled = false;
//设置视频编码格式
comboBox_videoecode.Items.Add("MPEG");
comboBox_videoecode.Items.Add("WMV");
comboBox_videoecode.Items.Add("FLV");
comboBox_videoecode.Items.Add("H263p");
comboBox_videoecode.Items.Add("MSMPEG4v3");
comboBox_videoecode.SelectedIndex = 0;
//设置视频来源
try
{
// 枚举所有视频输入设备
videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
if (videoDevices.Count == 0)
throw new ApplicationException(); //没有找到摄像头设备
foreach (FilterInfo device in videoDevices)
{
comboBox_camera.Items.Add(device.Name);
textBoxC.AppendText("摄像头" + i + "初始化完毕..." + "\n");
textBoxC.ScrollToCaret();
i++;
}
//comboBox_camera.SelectedIndex = 0; //注释掉,选择摄像头来源的时候才会才会触发显示摄像头信息
}
catch (ApplicationException)
{
comboBox_camera.Items.Add("No local capture devices");
videoDevices = null;
MessageBox.Show("没有找到摄像头设备", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
//秒表
timer_count = new System.Timers.Timer(); //实例化Timer类,设置间隔时间为1000毫秒;
timer_count.Elapsed += new System.Timers.ElapsedEventHandler(tick_count); //到达时间的时候执行事件;
timer_count.AutoReset = true; //设置是执行一次(false)还是一直执行(true);
timer_count.Interval = 1000;
}
private void comboBox_camera_SelectedIndexChanged(object sender, EventArgs e)
{
cam1 = new VideoCaptureDevice(videoDevices[comboBox_camera.SelectedIndex].MonikerString);
//cam1.DesiredFrameSize = new System.Drawing.Size(width, height);
//cam1.DesiredFrameRate = fps;
cam1.NewFrame += new NewFrameEventHandler(Cam_NewFrame1);
cam1.Start();
labelScreen.Text = "连接中...";
labelScreen.Visible = true;
ifCam1 = true;
//激活初始化按钮状态
btnTakePic.Enabled = true;
btnPauseVideo.Enabled = true;
btnStartVideo.Enabled = true;
btnStopVideo.Enabled = true;
}
private void Cam_NewFrame1(object obj, NewFrameEventArgs eventArgs)
{
pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone();
bm1 = (Bitmap)eventArgs.Frame.Clone();
if (is_record_video)
{
videoWriter.WriteVideoFrame(bm1);
}
}
//计时器响应函数
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 (min%60==0)
{
hour = min / 60;
min = 0;
}
else
{
min = min - hour * 60;
}
String tick = hour.ToString() + ":" + min.ToString() + ":" + sec.ToString();
MyDelegateUI d = delegate
{
this.labelTime.Text = tick;
};
this.labelTime.Invoke(d);
}
private void btnStartVideo_Click(object sender, EventArgs e)
{
//创建一个视频文件
String video_format = comboBox_videoecode.Text.Trim(); //获取选中的视频编码
String picName = GetVideoPath() + "\\" + DateTime.Now.ToString("yyyyMMdd HH-mm-ss");
if (-1 != video_format.IndexOf("MPEG"))
{
picName = picName + ".avi";
}
else if (-1 != video_format.IndexOf("WMV"))
{
picName = picName + ".wmv";
}
else
{
picName = picName + ".mkv";
}
textBoxC.AppendText("Video保存地址:" + picName + "\n");
textBoxC.ScrollToCaret();
timer_count.Enabled = true;//是否执行System.Timers.Timer.Elapsed事件;
labelScreen.Text = "REC";
textBoxC.AppendText("录制中...\n");
is_record_video = true;
videoWriter = new VideoFileWriter();
if (cam1.IsRunning)
{
if (-1 != video_format.IndexOf("MPEG"))
{
videoWriter.Open(picName, width, height, fps, VideoCodec.MPEG4);
}
else if (-1 != video_format.IndexOf("WMV"))
{
videoWriter.Open(picName, width, height, fps, VideoCodec.WMV1);
}
else
{
videoWriter.Open(picName, width, height, fps, VideoCodec.Default);
}
}
else
{
MessageBox.Show("没有视频源输入,无法录制视频。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void btnStopVideo_Click(object sender, EventArgs e)
{
labelScreen.Visible = false;
this.is_record_video = false;
this.videoWriter.Close();
this.timer_count.Enabled = false;
tick_num = 0;
textBoxC.AppendText("录制停止!\n");
textBoxC.ScrollToCaret();
}
private void btnExit_Click(object sender, EventArgs e)
{
if (this.videoWriter == null)
{
//MessageBox.Show("videoWriter对象未实例化。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
//return;
videoWriter = new VideoFileWriter();
}
if (this.videoWriter.IsOpen)
{
MessageBox.Show("视频流还没有写完,请点击结束录制。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
cam1.SignalToStop();
cam1.WaitForStop();
Hide();
Close();
Dispose();
}
private void btnPauseVideo_Click(object sender, EventArgs e)
{
if (this.btnPauseVideo.Text.Trim() == "暂停录像")
{
is_record_video = false;
labelScreen.Visible = false;
btnPauseVideo.Text = "恢复录像";
timer_count.Enabled = false; //暂停计时
return;
}
if (this.btnPauseVideo.Text.Trim() == "恢复录像")
{
is_record_video = true;
labelScreen.Visible = true;
btnPauseVideo.Text = "暂停录像";
timer_count.Enabled = true; //恢复计时
}
}
private void btnTakePic_Click(object sender, EventArgs e)
{
if (ifCam1)
{
String filepath = GetImagePath() + "\\"+DateTime.Now.ToString("yyyyMMdd HH-mm-ss") + ".bmp";
bm1.Save(filepath);
textBoxC.AppendText("摄像头1保存:" + filepath + "\n");
textBoxC.ScrollToCaret();
}
else
MessageBox.Show("摄像头没有运行", "错误", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
//获取Video相对路径?
private String GetVideoPath()
{
String personImgPath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory)
+ Path.DirectorySeparatorChar.ToString() + "MyVideo";
if (!Directory.Exists(personImgPath))
{
Directory.CreateDirectory(personImgPath);
}
return personImgPath;
}
//获取Img相对路径?
private String GetImagePath()
{
String personImgPath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory)
+ Path.DirectorySeparatorChar.ToString() + "MyImages";
if (!Directory.Exists(personImgPath))
{
Directory.CreateDirectory(personImgPath);
}
return personImgPath;
}
}
}
代码
在使用AForge这个软件过程中需要的不仅仅是将Release文件夹下对应的lib添加到项目的引用中,在进行视频压缩编码的时候需要将External文件夹下的相关lib添加到程序运行的Debug目录下
在使用的时候会遇到这个错误“混合模式程序集是针对“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>
【1】在writer.Close()执行前,视频帧都是在内存中的,虽然通过writer.Open()在硬盘上也生成了文件,但是文件大小为0.。 若果长时间录制不间断,内存就会溢出。除非录制一段时间后,就把内存中的视频保存到硬盘一次。
【2】图像大小不完全显示
【1】基于AForge的C#摄像头视频录制 - CSDN博客
http://blog.csdn.net/m_buddy/article/details/62417912
【2】AForge.net 使用之录像拍照功能实现 - CSDN博客
http://blog.csdn.net/chenhongwu666/article/details/41965801
【3】C# 调用AForge类库操作摄像头 - CSDN博客
http://blog.csdn.net/chenhongwu666/article/details/40594365
【4】C#实现录音录像录屏源码 - zhuweisky - 博客园
http://www.cnblogs.com/zhuweisky/p/3593917.html
【5】AForge.net 使用之录像拍照功能实现 - ching126 - 博客园
http://www.cnblogs.com/ching2009/p/4168000.html
【6】C# 下写入视频的简单实现 - CSDN博客
http://blog.csdn.net/whw8007/article/details/21232737
【7】AForge.Video.FFMPEG库使用注意事项 - liang12360640的专栏 - CSDN博客
http://blog.csdn.net/liang12360640/article/details/46044763
【8】C#:AccessViolationException: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。解决办法收集(转载) - 焦涛 - 博客园
http://www.cnblogs.com/Joetao/articles/5779328.html