画面キャプチャいろいろ調べていたらMicrosoft Expression Encoderが面白そうだったので、いろいろいじってみた。
動画の画面キャプチャについて、かなり簡単にできるようだったので、ちょっと作りこんでみた。無償版なら10分まで動画のキャプチャが可能。音声も録音できるので便利。
Expression Encoder 4
http://www.microsoft.com/japan/products/expression/products/encoder_overview.aspx
なお、こちらの方のエントリーを参照した。
http://code-life.net/?s=Expression+Encoder
実行画面
画面キャプチャのAPIがはじめから用意されていて、範囲を指定すると緑の枠が表示され、その範囲がキャプチャされる。キャプチャされたファイルは Expression Encoder 画面キャプチャ ファイル (.xesc) というファイル形式で保存される。このままではWindowsMediaPlayerでしか再生できないので、Expression Encoderの機能を使用して、wmv(VC-1コーデック)に変換して終了。これで他の動画プレイヤーやYoutubeにアップできる形式になる。
詳細はSDKをインストールした時にできるSDKフォルダの中のサンプルを参照すると良い。
動画キャプチャソース
_scrJob = new Microsoft.Expression.Encoder.ScreenCapture.ScreenCaptureJob(); _scrJob.CaptureRectangle = GetLocation(); _scrJob.ScreenCaptureVideoProfile.FrameRate = 25; _scrJob.OutputScreenCaptureFileName = @"C:\Movie\aaa.xesc"; var devs = Microsoft.Expression.Encoder.Devices.EncoderDevices.FindDevices(Microsoft.Expression.Encoder.Devices.EncoderDeviceType.Audio); _scrJob.AddAudioDeviceSource(devs[3]); /// ここはデフォルトに設定されているデバイスがくるようにする _scrJob.Start();
キャプチャ対象位置の指定
キャプチャ画面の幅と高さかは偶数値を指定しないとだめなので、プロパティCaptureRectangle に渡す数値を決めるGetLocation関数は次のようになる。
※Formに貼り付けているPanelControlのサイズをキャプチャ対象とする場合。
/// <summary> /// キャプチャ対象画面の位置を取得 /// </summary> /// <returns></returns> public Rectangle GetLocation() { var rc = new Rectangle(panel1.PointToScreen(panel1.ClientRectangle.Location), panel1.Size); rc.Width = (rc.Width % 2 == 0) ? rc.Width : rc.Width + 1; rc.Height = (rc.Height % 2 == 0) ? rc.Height : rc.Height + 1; return rc; }
録音デバイスの指定
録音デバイスの指定で音声も録音できるようになる。複数の音声デバイスがある場合、デフォルトの音声デバイスが指定されるようにする。
さて、デフォルトの音声デバイスはどうやってわかるのやら。。。
var devs = Microsoft.Expression.Encoder.Devices.EncoderDevices.FindDevices(Microsoft.Expression.Encoder.Devices.EncoderDeviceType.Audio); _scrJob.AddAudioDeviceSource(devs[3]); /// ここはデフォルトに設定されているデバイスがくるようにする
wmv(VC-1)へのエンコード
MediaItem mItem; mItem = new MediaItem(@"C:\Movie\aaa.xesc"); Job job = new Job(); job.MediaItems.Add(mItem); job.Encode();
動画を連結する場合
複数の動画を連結させてからエンコードをかける事ができる。MediaItem()には引数なしのコンストラクタが無いので、初めのファイルをコンストラクタに指定し、後のファイルはMediaItemのSourcesに追加する。
var files = System.IO.Directory.GetFiles(_dir).ToList(); /// MediaItemのコンストラクタに1つめのファイルを指定 MediaItem item = new MediaItem(files.First()); /// 後のファイルをAddする foreach (var file in files.Skip(1)) { item.Sources.Add(new Source(file)); } Job job = new Job(); job.MediaItems.Add(item); job.Encode();
動画を連続してキャプチャする
無償版は10分までキャプチャが可能であるが、10分を超えた場合自動でキャプチャが停止する。キャプチャが自動で終了した時に発生してくれるイベントがある。これを利用することで、次のキャプチャを開始すれば良い。
後はキャプチャ動画を連結してエンコードをかけることで、10分を超える動画の作成が可能。
イベントを利用して継続してキャプる例
キャプチャ動作を手動で停止した際にもイベントが発生してしまうので、状態管理を施しておく。Microsoft.Expression.Encoder.ScreenCapture.ScreenCaptureJob型のインスタンスを2つ(0,1)持っておき、交互に動作を切り替える。
/// 動画キャプチャが自動停止した場合、新規JOBを自動的に開始 job.ScreenCaptureFinished += (s, e) => { /// 状態がRECODEのみ新規JOB開始 if (_stat == MediaStatus.RECODE) { /// カレントのJOB番号を入れ替える _currentJob = _currentJob == 0 ? 1 : 0; StartNewJob(); } }; /// 動画キャプチャ開始 job.Start();
今回作成したソースはこちら※ExpressionEncoderとNewtonsoft.Jsonの参照が必要。