[ C# + Winform] 手把手教会你winform的视频录制

本文详细描述了如何在C#Winform应用中,针对64位系统,利用Accord.NET库实现摄像头资源获取、视频录制功能的开发过程,包括开发环境设置、工具安装、界面设计和关键代码段的实现。
摘要由CSDN通过智能技术生成

目录

一、写在前面

二、本文内容

三、开发环境

四、工具安装

五、界面搭建

六、代码实现

6.1定义参数

6.2 获取可选像素按钮实现

6.3 打开摄像头按钮实现

6.4 开始录制按钮实现

6.5 结束录制按钮实现

6.6关闭摄像头实现

七、录制视频结果

八、完整代码

九、小结

十、感谢


一、写在前面

       本文所用例子为个人学习的小结,如有不足之处请各位多多海涵,欢迎小伙伴一起学习进步,如果想法可在评论区指出,我会尽快回复您,不胜感激!

        所公布代码或截图均为运行成功后展示。

        嘿嘿,小小免责声明一下!部分代码可能与其他网络例子相似,如原作者看到有不满,请联系我修改,感谢理解与支持!

二、本文内容

        客户在某个医疗项目升级版本中提出需求,希望在病人进行数据测量的同时录制测量过程的视频,并且老版项目也要从32位操作系统迁移到64位操作系统,由此决定使用Accord.net作为视频采集的工具。

        AForge.NET仅支持32位操作系统,但使用方式和Accord几乎没有区别,可按需引用工具。

三、开发环境

        1.开发语言:C#

        2.开发框架:.Net Framework 4.8

        2.界面框架:Winform

        3.开发工具:Visual Studio 2022

四、工具安装

1.点开VS的工具Tools  --> NuGet包管理  -->  管理解决方案的NuGet程序包

2.Accord Accord.Video Accord.Video.DirectShow  Accord.Controls

3.添加引用

五、界面搭建

1.左侧listbox为获取摄像头所有资源模式并展示的列表

2.右侧方框为videoSourcePlayer,引入相应dll后,工具栏中会出现该工具。

3.构建几个功能按钮,开启摄像头、关闭摄像头、开始录制、结束录制等。

六、代码实现

6.1定义参数

        private FilterInfoCollection videoDevices = null;
        private VideoCaptureDevice videoSource = null;
        private VideoCapabilities[] VideoCapabilitiesList;
        private VideoFileWriter videoFileWriter;
        int count = 0;
        long timestamp = 0L;
        String picName;
        private Thread workerThread = null;
        private int mFrameCount = 0;
        Queue<Bitmap> mVideoFrameList = null;
        private bool is_record_video = false;
        private readonly object balanceLock = new object();

6.2 获取可选像素按钮实现

        获取摄像头所有像素模式,并添加至列表中

listBox1.Items.Clear();

            videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
            if (videoDevices.Count != 0)
            {
                for (int i = 0; i < videoDevices.Count; i++)
                {
                    videoSource = new VideoCaptureDevice(videoDevices[i].MonikerString);
                    VideoCapabilitiesList = videoSource.VideoCapabilities;
                    //wxf 获取摄像头所有像素模式
                    for (int j = 0; j < VideoCapabilitiesList.Count(); j++)
                    {
                        String itemStr = ("FrameSize:" + VideoCapabilitiesList[j].FrameSize.Width
                            + " * " + VideoCapabilitiesList[j].FrameSize.Height
                            + " FrameRate:" + VideoCapabilitiesList[j].AverageFrameRate
                            + " MaxFrameRate:" + VideoCapabilitiesList[j].MaximumFrameRate).ToString();

                        listBox1.Items.Add(itemStr);
                    }
                }
            }

6.3 打开摄像头按钮实现

        选择列表某项,并点击按钮,以此资源模式打开摄像头

 CloseVideoSource();
            int frame_index = listBox1.SelectedIndex;

            if (frame_index >= 0)
            {
                videoSource.VideoResolution = new VideoCaptureDevice(videoDevices[0].MonikerString).VideoCapabilities[frame_index];
                videoSourcePlayer1.VideoSource = videoSource;
                videoFileWriter = new VideoFileWriter();
                videoSourcePlayer1.Start();
            }

6.4 开始录制按钮实现

        录制画面并存储

        private void button3_Click(object sender, EventArgs e)
        {
            if (videoSourcePlayer1.IsRunning)
            {
                StarVideo();
            }
        }
 private void StarVideo()
        {
            try
            {
                if (count <= 0)
                {
                    videoSourcePlayer1.NewFrame += NewFrame;
                    count += 1;
                }
                is_record_video = true;
                String fileName = string.Format("{0:yyyyMMdd_HHmmss}.MP4", DateTime.Now);
                String path = Directory.GetCurrentDirectory();
                picName = $"{path}{fileName}";
                if (videoSource.IsRunning && videoSourcePlayer1.IsRunning)
                {
                    VideoCapabilities vc = videoSource.VideoResolution;
                    videoFileWriter.Close();
                    videoFileWriter.Open(picName, vc.FrameSize.Width, vc.FrameSize.Height, vc.MaximumFrameRate, VideoCodec.MPEG4);
                    mVideoFrameList = new Queue<Bitmap>();
                    workerThread = new Thread(new ThreadStart(backgroundWriteVideoToFile));
                    timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
                    workerThread.Start();
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

6.5 结束录制按钮实现

        结束录制并保存最后一帧

        private void button4_Click(object sender, EventArgs e)
        {
            StopVideo();
        }
 private void StopVideo()
        {
            try
            {
                is_record_video = false;

                if (videoFileWriter != null)
                {
                    videoFileWriter.Close();
                }
                if (videoSourcePlayer1 != null)
                {
                    videoSourcePlayer1.NewFrame -= NewFrame;
                    count -= 1;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("StopVideo   " + ex.Message);
            }
        }

6.6关闭摄像头实现

        private void button5_Click(object sender, EventArgs e)
        {
            videoSourcePlayer1.NewFrame -= NewFrame;
            count -= 1;
            CloseVideoSource();
        }
private void CloseVideoSource()
        {
            if (!(videoSource == null))
            {
                videoSourcePlayer1.Stop();
                videoSource.SignalToStop();
                videoSource.WaitForStop();
            }

        }

七、录制视频结果

        录制目录保存在设定目录下

八、完整代码

using Accord.Controls;
using Accord.Statistics;
using Accord.Video;
using Accord.Video.DirectShow;
using Accord.Video.FFMPEG;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window;

namespace AccordDemo
{
    public partial class Form1 : Form
    {
        private FilterInfoCollection videoDevices = null;
        private VideoCaptureDevice videoSource = null;
        private VideoCapabilities[] VideoCapabilitiesList;
        private VideoFileWriter videoFileWriter;
        int count = 0;
        long timestamp = 0L;
        String picName;
        private Thread workerThread = null;
        private int mFrameCount = 0;
        Queue<Bitmap> mVideoFrameList = null;
        private bool is_record_video = false;
        private readonly object balanceLock = new object();

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();

            videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
            if (videoDevices.Count != 0)
            {
                for (int i = 0; i < videoDevices.Count; i++)
                {
                    videoSource = new VideoCaptureDevice(videoDevices[i].MonikerString);
                    VideoCapabilitiesList = videoSource.VideoCapabilities;
                    //wxf 获取摄像头所有像素模式
                    for (int j = 0; j < VideoCapabilitiesList.Count(); j++)
                    {
                        String itemStr = ("FrameSize:" + VideoCapabilitiesList[j].FrameSize.Width
                            + " * " + VideoCapabilitiesList[j].FrameSize.Height
                            + " FrameRate:" + VideoCapabilitiesList[j].AverageFrameRate
                            + " MaxFrameRate:" + VideoCapabilitiesList[j].MaximumFrameRate).ToString();

                        listBox1.Items.Add(itemStr);
                    }
                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            CloseVideoSource();
            int frame_index = listBox1.SelectedIndex;

            if (frame_index >= 0)
            {
                videoSource.VideoResolution = new VideoCaptureDevice(videoDevices[0].MonikerString).VideoCapabilities[frame_index];
                videoSourcePlayer1.VideoSource = videoSource;
                videoFileWriter = new VideoFileWriter();
                videoSourcePlayer1.Start();
            }
        }
        private void StarVideo()
        {
            try
            {
                if (count <= 0)
                {
                    videoSourcePlayer1.NewFrame += NewFrame;
                    count += 1;
                }
                is_record_video = true;
                String fileName = string.Format("{0:yyyyMMdd_HHmmss}.MP4", DateTime.Now);
                String path = Directory.GetCurrentDirectory();
                picName = $"{path}{fileName}";
                if (videoSource.IsRunning && videoSourcePlayer1.IsRunning)
                {
                    VideoCapabilities vc = videoSource.VideoResolution;
                    videoFileWriter.Close();
                    videoFileWriter.Open(picName, vc.FrameSize.Width, vc.FrameSize.Height, vc.MaximumFrameRate, VideoCodec.MPEG4);
                    mVideoFrameList = new Queue<Bitmap>();
                    workerThread = new Thread(new ThreadStart(backgroundWriteVideoToFile));
                    timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
                    workerThread.Start();
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        //[HandleProcessCorruptedStateExceptions]
        private void NewFrame(object sender, ref Bitmap bit)
        {
            /*   try
               {*/
            if (is_record_video)
            {
                if (videoFileWriter.IsOpen && mVideoFrameList != null)
                {

                    mVideoFrameList.Enqueue((Bitmap)bit.Clone());

                    Console.WriteLine("NewFrame CallBack Now = " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffff") + ",FrameCount = " + mFrameCount + ",mVideoFrameList.Count = " + mVideoFrameList.Count);
                }
            }

        }
        [HandleProcessCorruptedStateExceptions]
        private void backgroundWriteVideoToFile()
        {
            try
            {
                while (is_record_video)
                {
                    if (mVideoFrameList != null && mVideoFrameList.Count > 0 && videoFileWriter != null && videoFileWriter.IsOpen)
                    {

                        lock (balanceLock)
                        {
                            Bitmap bitmap = mVideoFrameList.Dequeue();
                            videoFileWriter.WriteVideoFrame(bitmap);
                            bitmap.Dispose();
                        }
                    }
                    else
                    {
                        Thread.Sleep(5);
                    }
                }

                if (videoFileWriter != null && videoFileWriter.IsOpen)
                {
                    videoFileWriter.Close();
                }
                workerThread.Abort();
            }
            catch (Exception ex)
            {
                Console.WriteLine("NewFrame    " + ex.Message);
            }
        }
        private void StopVideo()
        {
            try
            {
                is_record_video = false;

                if (videoFileWriter != null)
                {
                    videoFileWriter.Close();
                }
                if (videoSourcePlayer1 != null)
                {
                    videoSourcePlayer1.NewFrame -= NewFrame;
                    count -= 1;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("StopVideo   " + ex.Message);
            }
        }
        private void CloseVideoSource()
        {
            if (!(videoSource == null))
            {
                videoSourcePlayer1.Stop();
                videoSource.SignalToStop();
                videoSource.WaitForStop();
            }

        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            videoSourcePlayer1.NewFrame -= NewFrame;
            count -= 1;
            CloseVideoSource();
        }

        private void button5_Click(object sender, EventArgs e)
        {
            videoSourcePlayer1.NewFrame -= NewFrame;
            count -= 1;
            CloseVideoSource();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (videoSourcePlayer1.IsRunning)
            {
                StarVideo();
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            StopVideo();
        }
    }



}

九、小结

       C#  64位系统通过Accord实现摄像头的资源获取、录制视频等功能就是这样,有更好的想法请在评论区交流哦,感谢大家的观看!

十、感谢

        感谢各位大佬的莅临,学习之路漫漫,吾将上下而求索。有任何想法请在评论区留言哦!

        再次感谢!

  • 24
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值