C# 使用Accord.net(AForge)录制视频
我使用Accord.net(AForge)连接网络摄像头并录制视频 但存储的视频是慢动作。。。 这是我的项目:C# 使用Accord.net(AForge)录制视频,c#,video,ffmpeg,video-capture,aforge,C#,Video,Ffmpeg,Video Capture,Aforge,我使用Accord.net(AForge)连接网络摄像头并录制视频 但存储的视频是慢动作。。。 这是我的项目: using AForge.Video; using AForge.Video.DirectShow; using AForge.Video.FFMPEG; using System; using System.Drawing; using System.IO; using System.Threading; using System.Windows.Forms; namesp
using AForge.Video;
using AForge.Video.DirectShow;
using AForge.Video.FFMPEG;
using System;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
namespace CaptureWebcam
{
public partial class Form1 : Form
{
private VideoCaptureDeviceForm captureDevice;
private string path = Path.GetDirectoryName(Application.ExecutablePath) + @"\Videos\";
private FilterInfoCollection videoDevice;
private VideoCaptureDevice videoSource;
private VideoFileWriter FileWriter = new VideoFileWriter();
private Bitmap video;
bool isRecord = false;
public Form1()
{
InitializeComponent();
}
private void videoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
video = (Bitmap)eventArgs.Frame.Clone();
pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone();
}
private void btnStartCam_Click(object sender, EventArgs e)
{
videoDevice = new FilterInfoCollection(FilterCategory.VideoInputDevice);
captureDevice = new VideoCaptureDeviceForm();
if (captureDevice.ShowDialog(this) == DialogResult.OK)
{
videoSource = captureDevice.VideoDevice;
videoSource = captureDevice.VideoDevice;
videoSource.NewFrame += new NewFrameEventHandler(videoSource_NewFrame);
videoSource.Start();
timer1.Enabled = true;
}
//videoSource.DisplayPropertyPage(IntPtr.Zero);
}
private Thread workerThread = null;
private bool stopProcess = false;
private void recordLiveCam()
{
if (!stopProcess)
{
while (isRecord)
{
FileWriter.WriteVideoFrame(video);
}
FileWriter.Close();
}
else
{
workerThread.Abort();
}
}
private void btnRecord_Click(object sender, EventArgs e)
{
//try
//{
isRecord = true;
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
int h = captureDevice.VideoDevice.VideoResolution.FrameSize.Height;
int w = captureDevice.VideoDevice.VideoResolution.FrameSize.Width;
FileWriter.Open(path + "recorded at " + DateTime.Now.ToString("HH-mm-ss") + ".mp4", w, h, 25, VideoCodec.MPEG4);
stopProcess = false;
workerThread = new Thread(new ThreadStart(recordLiveCam));
workerThread.Start();
//}
//catch (Exception ex)
//{
// MessageBox.Show(ex.Message);
//}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void btnStopRecord_Click(object sender, EventArgs e)
{
stopProcess = true;
isRecord = false;
FileWriter.Close();
workerThread.Abort();
video = null;
}
private void btnStopCam_Click(object sender, EventArgs e)
{
try
{
if (videoSource.IsRunning)
{
videoSource.SignalToStop();
videoSource.Stop();
pictureBox1.Image = null;
pictureBox1.Invalidate();
if (FileWriter.IsOpen)
{
FileWriter.Close();
video = null;
}
}
else
return;
}
catch
{
videoSource.Stop();
FileWriter.Close();
video = null;
}
}
float fts = 0.0f;
private void timer1_Tick(object sender, EventArgs e)
{
fts = videoSource.FramesReceived;
label1.Text = "Frame Rate : " + fts.ToString("F2") + " fps";
}
}
}
单击btnStopRecord时,出现以下错误:
其他信息:尝试读取或写入受保护内存。这通常表示其他内存已损坏
您可以尝试放置一些计时器,以了解哪个操作正在减慢进程。(秒表类将是完美的)
我不知道你的帧的格式,但通常转换成位图是一个瓶颈,因为转换速度很快。此外,您可以将时间戳传递给WriteVideoFrame方法,则Open中指示的帧速率仅用于重放视频。Aforge将在正确的时间以正确的顺序协调帧。
那是根据我的经验。希望能有所帮助。“慢动作”可能有多种原因。首先,您需要知道新帧生成时的实际帧速率是否太慢(那么有多少赫兹?),或者CPU是否太忙。或者是图形卡 对于所有与DirectShow相关的内容,我强烈建议使用GraphEdit和AMCap来了解该设备的真正功能。阿福热很容易出现过采样现象,我也不怀疑这是否与阿福热相似 此外,您可以始终依靠旧的processexplorer来查看负载(如果有)是由系统或中断引起的,还是由您的可执行文件实际产生的 发生在我身上的另一件事是PictureBox。VideoSourcePlayer要好得多,最后我自己做了一个blitting 值得一提的是这三个优化:
- 不要使用位图。GetPixel李>
- 使用
videoSource.DisplayPinPropertyPage(IntPtr.Zero)
- 检查视频流的颜色空间
如果使用AgFuff-BIT机制来选择分辨率和启动视频流,则不能设置帧数(我不认为这是A伪造中的bug)。因此,Forge始终选择最高帧率。如果您绕过videoSource.VideoCapabilities并直接显示本机设备配置对话框(正式称为“视频捕获Pin属性对话框”)。在那里,您可以手动设置所有参数,对话框将填充相应的帧率。这样,您将在回调中获得“真实”(硬件)刷新率。这种过采样的CPU负载发生在系统进程中
颜色空间转换在我的例子中,相机支持三种输出格式:YUY2、MJPG和RGB24。根据您使用的格式,图像由一个RGE转换为RGB(我认为实际上是ARGB32)。所有三种格式的渲染DirectShow图形都不同,RGB显然比其他格式使用更少的CPU,因为颜色转换非常简单。此转换产生的负载也会显示在系统进程中,而不会显示在应用程序exe中。您可以使用emguCV录制视频
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 Emgu;
using Emgu.CV;
using Emgu.CV.Structure;
namespace Load_Images
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
double TotalFrame;
double Fps;
int captureFrameNo;
VideoCapture capture;
VideoWriter writer;
bool isCapturing = false;
private void button1_Click(object sender, EventArgs e)
{
if (isCapturing == false)
{
capture = new VideoCapture(0);
TotalFrame = capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameCount);
Fps = capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps);
isCapturing = true;
int fourcc = fourcc = VideoWriter.Fourcc('H', '2', '6', '4');
capture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameWidth, 2048);
capture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameHeight, 1024);
//int fourcc = Convert.ToInt32(capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FourCC));
int width = Convert.ToInt32(capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameWidth));
int height = Convert.ToInt32(capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameHeight));
string destin_path = "D:\\out.mp4";
writer = new VideoWriter(destin_path, fourcc, Fps, new Size(width, height), true);
capture.ImageGrabbed += Capture_ImageGrabbed;
capture.Start();
}
}
private void Capture_ImageGrabbed(object sender, EventArgs e)
{
try
{
if (isCapturing == true)
{
if (capture == null)
{
return;
}
Mat m = new Mat();
capture.Retrieve(m);
writer.Write(m);
pictureBox1.Image = m.ToImage<Bgr, byte>().Bitmap;
}
}
catch (Exception)
{
throw;
}
}
private void button2_Click(object sender, EventArgs e)
{
if (isCapturing == true) {
capture.Stop();
isCapturing = false;
}
}
private void button3_Click(object sender, EventArgs e)
{
if (capture != null) {
capture.Pause();
}
}
private void button4_Click(object sender, EventArgs e)
{
if (writer.IsOpened)
{
isCapturing = false;
writer.Dispose();
}
MessageBox.Show("Completed");
}
private void Form2_Load(object sender, EventArgs e)
{
}
}
}
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用系统数据;
使用系统图;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用System.Windows.Forms;
使用Emgu;
使用Emgu.CV;
使用Emgu.CV.Structure;
名称空间加载\u映像
{
公共部分类表单2:表单
{
公共表格2()
{
初始化组件();
}
双全帧;
双Fps;
int captureFrameNo;
视频捕获;
录像作者;
bool isCapturing=false;
私有无效按钮1\u单击(对象发送者,事件参数e)
{
如果(isCapturing==false)
{
捕获=新的视频捕获(0);
TotalFrame=capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameCount);
Fps=capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps);
isCapturing=true;
intfourcc=fourcc=VideoWriter.fourcc('H','2','6','4');
capture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameWidth,2048);
capture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameHeight,1024);
//intfourcc=Convert.ToInt32(capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.fourcc));
int width=Convert.ToInt32(capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameWidth));
int height=Convert.ToInt32(capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameHeight));
字符串destin_path=“D:\\out.mp4”;
writer=新的VideoWriter(目标路径、fourcc、Fps、新大小(宽度、高度)、true);
capture.image抓取+=捕获\u image抓取;
capture.Start();
}
}
私有无效捕获(对象发送方,事件参数e)
{
尝试
{
如果(isCapturing==true)
{
如果(捕获==null)
{
返回;
}
Mat m=新Mat();
捕获、检索(m);
writer.Write(m);
pictureBox1.Image=m.ToImage().Bitmap;
}
}
捕获(例外)
{
通过
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 AForge;
using AForge.Video.DirectShow;
using Accord.Video.FFMPEG;
using System.IO;
using AForge.Video;
using System.Threading;
namespace New_Project_2
{
public partial class Form1 : Form
{
private VideoCaptureDeviceForm captureDevice;
private FilterInfoCollection videoDevice;
private VideoCaptureDevice videoSource;
private VideoFileWriter FileWriter = new VideoFileWriter();
bool isRecord = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void videoSource_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
try
{
if (isRecord == true)
{
pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone();
FileWriter.WriteVideoFrame((Bitmap)eventArgs.Frame.Clone());
}
}
catch (Exception)
{
throw;
}
}
private void button1_Click(object sender, EventArgs e)
{
videoDevice = new FilterInfoCollection(FilterCategory.VideoInputDevice);
captureDevice = new VideoCaptureDeviceForm();
if (captureDevice.ShowDialog(this) == DialogResult.OK)
{
isRecord = true;
int h = captureDevice.VideoDevice.VideoResolution.FrameSize.Height;
int w = captureDevice.VideoDevice.VideoResolution.FrameSize.Width;
FileWriter.Open("d:\\" + "recorded at " + DateTime.Now.ToString("HH-mm-ss") + ".mp4", w, h, 25, VideoCodec.MPEG4);
videoSource = captureDevice.VideoDevice;
videoSource.NewFrame += new NewFrameEventHandler(videoSource_NewFrame);
videoSource.Start();
}
//videoSource.DisplayPropertyPage(IntPtr.Zero)
}
private void button2_Click(object sender, EventArgs e)
{
}
private void button3_Click(object sender, EventArgs e)
{
isRecord = false;
FileWriter.Close();
}
private void button4_Click(object sender, EventArgs e)
{
}
}
}