Unity Editor上でADX2再生データの音を録音する with Unity Recorder


はじめに

こちらの投稿は、
Unity + ADX2環境でゲーム中の音を録音する
https://qiita.com/Takaaki_Ichijo/items/faf96c22740ff5a7587d

の続きです。上記記事は実機動作中のゲーム内での録音、当記事はUnity Editor上でADX2サウンドソースの録音方法を紹介します。

動作確認環境

  • Unity 2019.3.1f1 + ADX2 LE SDK 2.10.05
  • Unity 2018.4.13f1 + ADX2 (CRIWARE SDK for Unity 3.00.04)

パッケージ

ADX2 for Unity Recorder
https://github.com/TakaakiIchijo/ADX2forUnityRecorder

使い方

パッケージ導入後、Window/CRIWARE/CriAtomRecorderからツールウィンドウを呼び出すことができます。
ウィンドウは保存先ディレクトリ指定、ファイル名指定、Start Recordingのでかいボタンと保存先ディレクトリを開くボタンという激烈シンプルなものです。
録音中は録音ファイル名がボタン下部に表示されるようになっています。

ゲーム再生時、任意のタイミングでStart Recordingボタンを押し、止めたいところで同じボタンをもう一度押すだけです。
Add Timestamp to file name オプションで、ファイル名の後ろに日付・時刻を自動で入れます。
オプションをオンにすると、同一ファイル名で上書きしていく挙動になります。

Unity Recorderとの連動

UnityRecorder用の拡張も用意してあり、動画の録画と(ほぼ)同じタイミングで録音できます。

Unity Recorderを開き、+Add New RecordersからADX2 Audioを選択します。 Movieと同時に録音するときは、Movie側のCapture Audioのチェックを外してください。

ADX2データの読み込みの完了待ちがあるため、若干動画とタイミングがずれます。動画編集ソフトなどでmp4とwavをくっつける場合はタイミングにご注意ください。

wavの保存フォルダはデフォルトではAssets/Recordingsです。

録音の手法

CriAtomExOutputAnalyzerクラスを使ってミキシング後の音声データを取り出し、wavファイルに書き込みます。
https://game.criware.jp/manual/unity_plugin/jpn/contents/classCriAtomExOutputAnalyzer.html

CriAtomExOutputAnalyzerクラスによる音声データのキャプチャは、Update内でExecutePcmCaptureCallbackを叩き続ける必要があります。

CriAtomRecorder.cs
    private void Update()
    {
        if (IsRecording)
        {
            analyzer.ExecutePcmCaptureCallback();
        }
    }

また、CriAtom.CueSheetsAreLoadingをチェックし、再生に必要なデータがロード完了しているかを待つ必要があります。
そのため、ゲームオブジェクトとして録音モジュールをヒエラルキー内に生成し、HideFlags.HideInHierarchyをつけて見えなくしています。
録音停止時点でオブジェクトを破棄します。

Unity Recorder連携

冒頭書いたようにRecorder拡張が完成したので、下記の手順は必要ありません。

ゲーム開発過程において、トレイラームービーを作る際など、ゲームをEditor上で動作させながら動画・音声キャプチャしたいことがあります。
Unityには、Unity Recoderという録画・録音機能が公式に提供されています。以前はUnity Asset Storeにありましたが、現在はPackage ManagerからUnity Recorderを導入できます。
ただしPreview Package扱いです。(2020年2月現在)

Unity RecorderはADX2のエンジンで再生している音をキャプチャできないため、当初はUnity RecorderのAudioRecorderSettingsを拡張してADX2対応させる予定でしたが、必要なクラス一式がinternalで触れないため断念しました。

ただし、UnityEditor.Recorder.RecorderWindow.IsRecording()で録画中かどうかのステートが取れるため、このboolをポーリングしてUnityRecorderで録画が始まったら同時にCriAtomRecorderによる音声録音も開始して、同じくRecorder側での録画終了となったら録音を停止する仕組みを用意します。

CriAtomRecorderEditorWindow.cs
    private void OnEnable()
    {
        UnityEditor.Recorder.RecorderWindow recorderWindow = GetWindow<UnityEditor.Recorder.RecorderWindow>();

        EditorApplication.update += () =>
        {
            if (recorderWindow.IsRecording() && isRecording == false)
            {
                StartRecording();
                this.Repaint();
            }

            if (recorderWindow.IsRecording() == false && isRecording)
            {
                StopRecording();
                this.Repaint();
            }
        };
    }

このウィンドウが有効になった時点でUnity Recorderのウィンドウも開いて参照を取得し、EditorApplication.updateタイミングでIsRecording()を監視します。
(少し不安定なため、上記repoでのパッケージではコメントアウトしています)

CriAtomRecorderウィンドウを開くとUnity Recorderも勝手に開きます。このとき、Movieモジュールのキャプチャ設定で「Capture audio」のオプションを外してください。(どのみちADX2を導入したプロジェクトにはAudioListenerがないので、ワーニングが出ます)

Unity Recorder側の赤い録画ボタンを押せば、CriAtomRecorder側も録音を開始します。(昔のカセットテープで録音ボタンを押すと再生ボタンが同時押しされるやつみたいですね)

問題点

どうにかUnity Recorderとの連携はできましたが、わずかながらキャプチャのタイミングにずれがありますなので、トレイラームービーを作る場合はムービー作成ツール上でタイミングを合わせてあげる必要があります。

また、可能であればUnity Editorの時点で音声と動画をつなげたmp4を生成したいのですが、Recorder内部のMovieEncorderを改造する必要がある模様で、公開がグレーになるため難しいです。

Unity Recorder内部のクラスが触れるようになれば、Recorderウィンドウだけで完結しそうなのですが、Recorder側の開国待ちです。 Recorder用拡張に成功しました。