[UE4] NDIを受信する


はじめに

NDIの映像をUnreal Engine 4で受信する方法を記載。Windowsのみ検証した。

NDIについては、この記事などを参照すると良い。HDMIやSDIのケーブル伝送に比べてしまうと(たとえローカル内であっても)遅延が発生するものの、それが許容される場合であれば、映像のとりまわしが容易なぶん非常に役立ち様々なストレスから開放される。NDIはハードウェアさえ不要で、設定も比較的容易でまさにメシア。

自分自身はBlackmagic DeckLinkなどのキャプチャボードからのUE4へストリームメディアとしての取り込みを何度も試みたが全てくじかれた。Duo2、Quad Recoreder 4K、BlackMagic以外ではAverMedia製品などを試したが、これらすべてUE4(とくに4.25)で直接受信させることができなかった。

Blackmagic Decklinkについては、Blackmagic designから提供されるドライバー類を同梱した、Desktop Video SDKが、バージョン11.6において不具合があり、UE4では受信できないことが報告されている。しかし、11.5.1や11.7においてはこの問題がなくSDIでの映像受信ができる。(事後加筆)

以下インストール方法。

1. NDI SDK、Pluginのインストール

以下2つをダウンロードし、解凍後、インストーラを用いてインストールする。

  • NDI Tools :
    • Runtimeや各種ユーティリティツールなどがインストールできる
    • 同梱されている Test Patterns や Studio Monitor など便利なツールがたくさんありそれだけでも価値がある
  • NDI SDK for Unreal Engine :
    • ドキュメントも同梱されており、この記事と同じような説明が記載されている


上記はTest Patternsからの配信をStudio Monitorで受信している。なお、NDIの配信固有の識別名は マシン名 (アプリ名)のようになる。自分のマシン(DESKTOP-O6G5712)内でTest Patternsを配信した場合、DESKTOP-O6G5712 (Test Pattern)という命名になった。

2. プロジェクトにPluginを配置して有効化

上記の NDI SDK for Unreal Engine がインストールされた場所の、 NDI SDK for Unreal Engine > NDIExamples > Plugins にある、NDIIOPlugin がPluginとなるファイル群の実体。デフォルトのパスは、 C:\Program Files\NewTek\NDI SDK for Unreal Engine\NDIExamples\Plugins となる。

この NDIIOPlugin をそのまま、UE4の適用したいプロジェクトディレクトリ直下の Plugins ディレクトリ(なければ作成)に、コピーして配置。その後、プロジェクトを立ち上げると、Pluginが有効化され、NDIに関するオブジェクトなどが利用できるようなる。

3. NDI用のMedia SourceとTextureを用意

NDI Media ReceiverNDI Media Texture2D をそれぞれコンテンツブラウザ内で作成、名前をつける。
NDI Media Receiverの設定項目にある、Video Textureに先程作成したNDI Media Texture2Dを設定する。

4. NDI Receiverコンポーネントを持つアクターもしくはプレーヤーを配置する

  • アクター(Actor Blueprint)もしくはプレーヤー(Player Controller Blueprint)を作成
  • NDI Receiverコンポーネントを追加する
  • NDI ReceiverコンポーネントのNDI Media Sourceに先程作成した、NDI Media Receiverを設定

NDI Receiverを持つには、アクターかプレーヤーのどちらでも良いが見通しが良くなる方が吉。

なお余談だが、NDI ReceiverNon-Scene ComponentのC++ファイルであるが、上述のNDI Media SourceがPrivate変数となっており、BlueprintのDetailsパネル上からしかアクセスできないのが非常に不便。Blueprintノード上でセットしたり、Levelエディタから設定することができず、このブループリントをNDIソース毎に使い回すことができないからだ。これを解消するにはこのコンポーネントのヘッダファイル(NDIReceiverComponent.h)を書き換えて再Buildする。このステップは任意。

private:
    /** The NDI Media Receiver representing the configuration of the network source to receive audio, video, and
     * metadata from */
    UPROPERTY(EditDefaultsOnly, Category = "Properties",
              META = (DisplayName = "NDI Media Source", AllowPrivateAccess = true))
    UNDIMediaReceiver* NDIMediaSource = nullptr;

public:
    /** The NDI Media Receiver representing the configuration of the network source to receive audio, video, and
     * metadata from */
    UPROPERTY(EditAnywhere, Category = "Properties",
              META = (DisplayName = "NDI Media Source", AllowPrivateAccess = true))
    UNDIMediaReceiver* NDIMediaSource = nullptr;

5. 任意のBlueprintから、NetworkSourceを監視し、変更された際に受信を開始する

NDI Receiverを参照できる任意のBlueprintにノードを配置していく

  • NDI Finderコンポーネントを用意する

  • Network Sourceを監視し、ネットワークが接続されたりするタイミングでNDIを受信するようにする( NDI Finder > Bind Event to On Network Source Changed

  • Callbackとなるイベントに、NDI Finderを引数にとれるCustomEventを追加して用いる。ここでは事前にOnNetworkChangedというCustomEventをつくっておいている。

  • このCallbackイベントにて、ネットワーク内の配信の中から識別名(DESKTOP-O6G5712 (Test Pattern)のような)を使って、ほしい配信を検索し(NDI Finder > Find Network Source By Name

  • 見つかったら、NDI ReceiverというコンポーネントのStart Receiverをコールする

NetworkSourceを監視しないで、いきなりFind Network Source By NameしてStart Receiverを走らせてもPIEでは動くかもしれない。しかし、自分の環境ではコンパイルした実行ファイルにおいては、上記のようにNetworkSouceを監視して、変更の度にNDIを受信をする関数を呼ばないと、NDIを正常に受信することができなかった。(解決にすごく時間を溶かした…)
また、ここでは省略するが、ストリームが不要になった際に、NDI ReceiverEnd Receiverを呼んで、明示的に受信を終わらせたほうが良い。

6. NDI Media Texture2Dで受信を確認し、利用する

作成したNDI Media Texture2Dを確認すると、ただしく受信できていれば動画が確認できる。このTextureはMaterialなどで参照して自由に使える。Chromakeyをしてリアルタイムで切り抜きもできた。


元動画

参照