本日は HoloLens2 の技術調査枠です。
MediaCaptureを使ってHoloLens2でスクリプトからホログラムを合成したビデオ録画を行う手順を記事にします。
MediaCapture
UWP アプリでは MediaCapture クラスを使ってカメラデバイスから写真やビデオのキャプチャを実行することができます。
docs.microsoft.com
HoloLens でのキャプチャ時に、アプリケーションの仮想ホログラムやオーディオをビデオに含めたい場合は追加で MRC 効果の設定を行う必要があります。
docs.microsoft.com
本記事ではこの MediaCapture クラスを使ってHoloLens2でホログラムを合成したビデオ録画を行ってみます。
VideoCaptureによる録画
VideoCapture クラスを使ってもビデオ録画を行うことができます。
詳細は以下の記事を参照ください。
bluebirdofoz.hatenablog.com
ただし、VideoCapture の showHolograms オプションは Unity 2020 以降では現在、無効化されています。
docs.unity3d.com
このため、Unity 2020 以降の環境でホログラムの合成を行いたい場合は本記事の MediaCapture を利用してください。
実行例
実際に MediaCapture を用いて録画を実行したサンプルを記述します。
サンプルシーン
動作確認のため、以下のサンプルシーンを作成しました。
ホログラムが同時に録画されていることを確認するため、Cube オブジェクトを配置しています。
サンプルコード
録画を行うための以下のスクリプトを作成しました。
StartRecord 関数で録画の開始、StopRecord 関数で録画を停止します。
・HologramMediaCapture.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using System.IO; public class HologramMediaCapture : MonoBehaviour { #if WINDOWS_UWP /// <summary> /// Mediaキャプチャの参照 /// </summary> Windows.Media.Capture.MediaCapture p_MediaCapture; /// <summary> /// Mediaレコーダの参照 /// </summary> Windows.Media.Capture.LowLagMediaRecording p_MediaRecording; #endif /// <summary> /// 初期化完了フラグ /// </summary> bool isInitialized; /// <summary> /// 録画実行中フラグ /// </summary> bool isRecording; // Start is called before the first frame update void Start() { // 初期化完了フラグをOFF isInitialized = false; // Mediaキャプチャの初期化 MediaInitialize(); } // Update is called once per frame void Update() { } /// <summary> /// 動画記録の開始 /// </summary> public void StartRecord() { StartRecordAsync(); } /// <summary> /// 動画記録の停止 /// </summary> public void StopRecord() { StopRecordAsync(); } /// <summary> /// Mediaキャプチャの初期化 /// </summary> private async void MediaInitialize() { Debug.Log("MediaInitialize"); #if WINDOWS_UWP // MRC 効果の定義 Windows.Media.Effects.IVideoEffectDefinition define = new MrcVideoEffectDefinition(); Windows.Media.Capture.MediaStreamType type = Windows.Media.Capture.MediaStreamType.VideoRecord; // Mediaキャプチャの初期化 p_MediaCapture = new Windows.Media.Capture.MediaCapture(); await p_MediaCapture.InitializeAsync(); await p_MediaCapture.AddVideoEffectAsync(define, type); p_MediaCapture.Failed += MediaCapture_Failed; p_MediaCapture.RecordLimitationExceeded += MediaCapture_RecordLimitationExceeded; #endif // 初期化完了フラグをON isInitialized = true; } #if WINDOWS_UWP /// <summary> /// Mediaキャプチャ失敗時の呼び出し関数 /// </summary> /// <param name="sender"></param> /// <param name="errorEventArgs"></param> private void MediaCapture_Failed( Windows.Media.Capture.MediaCapture sender, Windows.Media.Capture.MediaCaptureFailedEventArgs errorEventArgs) { Debug.LogError("MediaCapture_Failed"); } /// <summary> /// 録画上限時の呼び出し関数 /// </summary> /// <param name="sender"></param> private void MediaCapture_RecordLimitationExceeded( Windows.Media.Capture.MediaCapture sender) { Debug.LogError("MediaCapture_RecordLimitationExceeded"); StopRecordAsync(); } #endif /// <summary> /// レコードの開始 /// </summary> private async void StartRecordAsync() { Debug.Log("StartRecordAsync"); // 初期化未了時は処理しない if (!isInitialized) return; // 録画実行中は処理しない if (isRecording) return; // 録画実行中フラグをON isRecording = true; // タイムスタンプを元にファイル名を作成する string timeStamp = Time.time.ToString().Replace(".", "").Replace(":", ""); string fileName = string.Format("Video_{0}.mp4", timeStamp); #if WINDOWS_UWP // 保存先のファイル設定 Windows.Storage.StorageLibrary myVideos = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Videos); Windows.Storage.StorageFile file = await myVideos.SaveFolder.CreateFileAsync(fileName, Windows.Storage.CreationCollisionOption.GenerateUniqueName); // 録画フォーマットの設定(LowLagMediaRecordingセッションの開始) p_MediaRecording = await p_MediaCapture.PrepareLowLagRecordToStorageFileAsync( Windows.Media.MediaProperties.MediaEncodingProfile.CreateMp4( Windows.Media.MediaProperties.VideoEncodingQuality.Auto), file); // 録画の開始 await p_MediaRecording.StartAsync(); #endif } /// <summary> /// レコードの停止 /// </summary> private async void StopRecordAsync() { Debug.Log("StopRecordAsync"); #if WINDOWS_UWP // 録画の停止 await p_MediaRecording.StopAsync(); // LowLagMediaRecordingセッションの停止 await p_MediaRecording.FinishAsync(); #endif // 録画実行中フラグをOFF isRecording = false; } }
また MRC ビデオ効果の定義クラスを以下の通り作成しました。
・MrcVideoEffectDefinition.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; #if WINDOWS_UWP public class MrcVideoEffectDefinition : Windows.Media.Effects.IVideoEffectDefinition { public string ActivatableClassId { get { return "Windows.Media.MixedRealityCapture.MixedRealityCaptureVideoEffect"; } } public Windows.Foundation.Collections.IPropertySet Properties { get { return _Properties; } } private Windows.Foundation.Collections.IPropertySet _Properties; public MrcVideoEffectDefinition() { _Properties = (Windows.Foundation.Collections.IPropertySet)new Windows.Foundation.Collections.PropertySet(); _Properties.Add("HologramCompositionEnabled", true); // ビデオ キャプチャでホログラムを有効または無効にするフラグ _Properties.Add("RecordingIndicatorEnabled", false); // ホログラムキャプチャ中に画面の記録インジケーターを有効または無効にするフラグ _Properties.Add("VideoStabilizationEnabled", false); // HoloLens トラッカーを利用したビデオ安定化を有効または無効にするフラグ _Properties.Add("VideoStabilizationBufferLength", 0); // ビデオの安定化に使用される履歴フレームの数 _Properties.Add("GlobalOpacityCoefficient", 0.9f); // ホログラムのグローバル不透明度係数:0.0 (透明) ~ 1.0 (不透明) } } #endif
作成したスクリプトを適当なゲームオブジェクトにアタッチします。
ボタンの配置
ボタンオブジェクトを利用するため、Unity プロジェクトに MRTK をインポートします。
MRTK のインポート手順は以下の記事などを参考にしてください。
bluebirdofoz.hatenablog.com
シーンにトグルボタンを配置し、開始/停止関数をイベントに割り当てました。
Capabilitiesの設定
録画を行うため、カメラの権限許可を行います。
メニューから[Edit -> Project Settings..]を開き、[Player]タブの[Publishing Settings]を開きます。
[Capabilities]の項目で[WebCam]にチェックを入れます。
また、今回はスクリプトで録画ファイルの保存先にビデオライブラリを指定しているので、[VideoLibrary]にもチェックを入れておきます。
ホログラムの位置合わせ
デフォルト設定でカメラ映像とホログラムの合成を行うと、カメラ位置のズレにより、動画内でホログラムの位置ズレが発生します。
以下の設定を行うことで、ホログラムの位置ズレ修正することができます。
1. [Hierarchy]から[MixedRealityToolkit]オブジェクトを選択し、Inspector ビューを開きます。
2. MRTK のプロファイルから[Camera -> Camera Settings Providers -> Windows Mixed Reality Camera Settings]を開きます。
3. [Render from PV Camera]のチェックを入れます。
HoloLens2での動作確認
アプリを HoloLens2 にインストールして動作を確認します。
[Toggle]ボタンをクリックすると録画が開始/停止されます。
録画したファイルは HoloLens の Video フォルダに保存されます。
DevicePortal のファイルエクスプローラからダウンロード可能です。
ダウンロードした動画を確認すると、ホログラムが映った動画が撮影できています
スペシャルサンクス
VideoCapture が Unity 2020 で動作しなかったとき、本代替案を教えてくれた方。
・たるこす氏
tarukosu.hatenablog.com