OpenCvSharpを使ってH264動画をWEBカメラから撮る
NuGetでインストール:
OpenCvSharp3-AnyCPU
アプリケーションExeファイルと同じフォルダに必要:
openh264-1.8.0-win64.dll
※上記2者の相性が良くてうまく機能しているが、逆に最新版はダメ。
using System;
using System.ComponentModel;
using System.Windows.Forms;
using OpenCvSharp;
namespace DirectShowLib_Demo
{
public partial class Form1 : Form
{
const int CONST_VIDEO_WIDTH = 1280;
const int CONST_VIDEO_HEIGHT = 700;
const int CONST_VIDEO_RRAMERATE = 30;
int useVideoWidth;
int useVideoHeight;
VideoWriter video;
int cannelIndex = 0;
string filePath = "";
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// DoWorkイベントハンドラの実行を開始
worker.RunWorkerAsync();
aviPlayer.uiMode = "none";
aviPlayer.windowlessVideo = false;
aviPlayer.settings.autoStart = true;
aviPlayer.enableContextMenu = false;
aviPlayer.stretchToFit = true;
aviPlayer.settings.setMode("loop", false);
timer1.Enabled = true;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
try
{
// 動画ファイルを閉じる
if (video != null && !video.IsDisposed)
{
video.Dispose();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
// 動画撮影ボタン押下処理
private void button2_Click(object sender, EventArgs e)
{
try
{
if (label2.Text == "STOP")
{
label2.Text = "REC";
filePath = $@"C:\Temp\video_{DateTime.Now.ToLongTimeString().Replace(":", "")}.mp4";
video = new VideoWriter(
filePath,
FourCC.H264,
30,
new OpenCvSharp.Size(useVideoWidth, useVideoHeight));
}
else if (label2.Text == "REC")
{
label2.Text = "STOP";
// 動画ファイルを閉じる
video.Dispose();
aviPlayer.URL = filePath;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
// バックグラウンドワーカーの作業処理
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
try
{
BackgroundWorker worker = (BackgroundWorker)sender;
while (true)
{
VideoCapture cap = new VideoCapture(cannelIndex);
int curCaneelIndex = cannelIndex;
cap.Set(CaptureProperty.FrameWidth, CONST_VIDEO_WIDTH);
cap.Set(CaptureProperty.FrameHeight, CONST_VIDEO_HEIGHT);
useVideoWidth = cap.FrameWidth;
useVideoHeight = cap.FrameHeight;
if (cap.IsOpened())
{
while (true)
{
if(curCaneelIndex == cannelIndex)
{
var frame = cap.RetrieveMat();
worker.ReportProgress(0, frame);
}
else
{
cap.Dispose();
break;
}
}
}
else
{
MessageBox.Show("Error. There is no Camera!!!");
this.Close();
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
// バックグラウンドワーカーの状態変化処理
private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
try
{
// frameがe.UserStateプロパティにセットされて渡されてくる
Mat image = (Mat)e.UserState;
if (label2.Text == "REC")
{
// 動画ファイルに書き込み
video.Write(image);
}
pictureBoxIpl1.ImageIpl = image;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
//動画ループ再生時ちらつき対策
private void timer1_Tick(object sender, EventArgs e)
{
if(aviPlayer.Ctlcontrols.currentItem != null)
{
if (aviPlayer.Ctlcontrols.currentPosition > aviPlayer.Ctlcontrols.currentItem.duration - 0.01)
{
aviPlayer.Ctlcontrols.currentPosition = 0;
}
}
}
}
}