Elsaの技術日記(徒然なるままに)

主に自分で作ったアプリとかの報告・日記を記載

MENU

WPFでスクリーン録画してみる

先日、WPFスクリーンショットやスクリーン画面の動画を表示してみました。
elsammit-beginnerblg.hatenablog.com

今回はこちらのコードに録画機能を追加してスクリーン上の映像を録画してみようと思います!!



■OpenCVSharpを準備する

録画するにあたり、OpenCVSharpを用います。
OpenCVC#版ですね。

OpenCVSharpですが、
Visual Studioを用いている場合には
Nugetパッケージ管理
を用いれば簡単にインストールが可能です。

Nugetパッケージ管理ですが、
ソリューションエクスプローラー上の参照を右クリックすると
こちらの通り、選択項目が出てくるのでこちらをクリック。

Nugetパッケージ管理が表示されたら、
上タブから「参照」を選択し、検索画面で「OpenCVSharp」と入力すると
こちらの通り複数バージョンのOpenCVSharpがリストで出力されます。

今回は、
・OpenCvSharp4
・OpenCvSharp4.runtime.win
をインストールしました。
合わせて、Extensionsも利用したいので、
・OpenCvSharp4.Extensions
もインストールします。

これでOpenCVSharpのインストールは完了です。

WPFでスクリーン録画してみる

では本題のスクリーン録画を行ってみます。
xamlは前回と同様こちらのレイアウトとしました。

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Image x:Name="ImgCap" HorizontalAlignment="Left" Height="343" VerticalAlignment="Top" Width="525" Margin="62,34,0,0"/>
        <Button Content="start" HorizontalAlignment="Left" Height="54" Margin="656,351,0,0" VerticalAlignment="Top" Width="113" Click="Button_Click"/>
    </Grid>
</Window>

録画開始するためのボタンと録画中の映像を表示するImagが1つずつあるのみの構成です。

次にC#のコードですが、こちらの通りになります。

using System;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Drawing;
using System.Windows.Interop;
using System.Threading;
using OpenCvSharp;
using OpenCvSharp.Extensions;

namespace WpfApp1
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : System.Windows.Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Thread thread = new Thread(new ThreadStart(() =>
            {
                CaptureMovieAsync();
            }));
            thread.Start();
        }

        private void CaptureMovieAsync()
        {
            using (var writer = new VideoWriter("test.wmv", FourCC.WMV3, 5, new OpenCvSharp.Size((int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight)))
            {
                for (int i = 0; i < 100; i++)
                {
                    using (var screenBmp = new System.Drawing.Bitmap(
                        (int)SystemParameters.PrimaryScreenWidth,
                        (int)SystemParameters.PrimaryScreenHeight,
                        System.Drawing.Imaging.PixelFormat.Format32bppArgb))
                    {
                        using (var bmpGraphics = Graphics.FromImage(screenBmp))
                        {
                            bmpGraphics.CopyFromScreen(0, 0, 0, 0, screenBmp.Size);

                            Dispatcher.Invoke((Action)(() =>
                            {
                                ImgCap.Source = Imaging.CreateBitmapSourceFromHBitmap(
                                screenBmp.GetHbitmap(),
                                IntPtr.Zero,
                                Int32Rect.Empty,
                                BitmapSizeOptions.FromEmptyOptions());

                                Mat mat = BitmapConverter.ToMat(screenBmp).CvtColor(ColorConversionCodes.RGB2BGR);
                                Cv2.CvtColor(mat, mat, ColorConversionCodes.BGR2RGB);
                                Cv2.Resize(mat, mat, new OpenCvSharp.Size((int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight));
                                writer.Write(mat);
                            }));
                        }
                    }
                    Thread.Sleep(100);
                }
            }    
        }
    }
}

前回のスクリーンショット映像表示のみのコードから追加した点は2点です。
1点目は下記コードになります。

using (var writer = new VideoWriter("test.wmv", FourCC.WMV3, 5, new OpenCvSharp.Size((int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight)))

VideoWriterで動画ファイルへの書き込み用オブジェクトを生成します。
動画ファイルはwmvで出力したかったので、FourCCはWMV3としました。
また、動画サイズは画面サイズと合致するため、
new OpenCvSharp.Size((int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight)
としました。

2点目は下記のコードになります。

Mat mat = BitmapConverter.ToMat(screenBmp).CvtColor(ColorConversionCodes.RGB2BGR);
Cv2.CvtColor(mat, mat, ColorConversionCodes.BGR2RGB);
Cv2.Resize(mat, mat, new OpenCvSharp.Size((int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight));
writer.Write(mat);

こちらは、BitmapをMat型に型変換を行った後、
BGR⇒RGBに色変換とサイズ変更後、1点目で記載したVideoWriterへWriteしています。

本ループですが、、、
100ミリ秒のwaitで0から100までループさせているので、計10秒間実施しています。
要するに10秒間のスクリーン画面の録画を行っている、ということですね。

■最後に

今回はスクリーン画面を録画する方法をまとめてみました。
OpenCVが利用できるので、録画以外にもいろいろなことが出来そうですね。