C# 使用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

我使用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;

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)
  • 检查视频流的颜色空间
位图.GetPixel GetPixel的问题是,它的速度非常慢,因为它必须对每个像素进行大量的管理。这很好,因为您只收到少量调用,并在加载的位图上使用它。如果您想每隔几毫秒在所有像素上使用它,那么这肯定是错误的方法。此现象产生的CPU负载与您的应用程序相关联,并将在process explorer中显示。 最后,我从这里开始编写了自己的像素例程: 如果您只是想要一个内核或比我需要的更普通的东西,请实现 习惯

VideoSource.DisplayPinPropertyPage

如果使用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)
        {


        }

    }
}