KlakNDIのセットアップ 2.0.3

今回は、KlakNDIのセットアップを紹介します。
そもそもNDIとは何か？NDIは、LANで映像データを送ることができるサービスです。KlakNDIでは、Unityのカメラで映した映像を、NDI化して送信します。

**NDI本家様**：[NDI SDK](https://www.ndi.tv/sdk/?gclid=Cj0KCQjwpImTBhCmARIsAKr58czX3Pu3SRqFTsv3VOoBJ-bjMbTWVdLPF_8gsXQJtplj1IbzrxpsBMQaAhgREALw_wcB)

**KlakNDI本家様**：https://github.com/keijiro/KlakNDI

以下を参考にさせていただきました。手順はかなり異なるので、もし本記事でうまくいかない場合はご確認ください。
**参考**：[【Unity】KlakNDIを使ってみる](https://note.com/hikohiro/n/n5a3e2e337228)

# 0. 動作環境
本記事では、以下の環境で試しました。
Unity:2019.4.29f1
KlakNDI:2.0.3
PC:MacOS Monterey

# 1. 必要なパッケージを準備
KlakNDIを使うためには、Scoped Registryを使用する必要があります。Scoped Registryとは、簡単に説明すると「元はUnityにないPackage」です。詳しくは[スコープ付きレジストリ](​​​​​​​​https://docs.unity3d.com/ja/2020.3/Manual/upm-scoped.html)をご確認ください。

## 1-1. PackageManagerにScoped Registryを追加
Scoped Registryの追加方法です。
Edit > Project Settings > Package Manager > Scoped Registriesを開きます。左下の＋ボタンを押し、要素を追加します。以下、それぞれ入力が完了したら、右下の「Save(保存する)」を押します。

〜〜〜〜〜〜〜〜〜〜
Name：Keijiro
URL：https://registry.npmjs.com
Scope(s)：jp.keijiro
〜〜〜〜〜〜〜〜〜〜
Name：Unity NuGet
URL：https://unitynuget-registry.azurewebsites.net
Scope(s)：org.nuget
〜〜〜〜〜〜〜〜〜〜

![スクリーンショット 2022-04-23 15.47.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/778b5322-03bb-a241-fbdc-42da57d970a7.png)

## 1-2. Assembly Version Validationのチェックを外す
パッケージをインポートする前に、同じプロジェクト設定から設定を済ませます。
そして、「Project Settings > Player > Other Settings > Assembly Version Validate」のチェックを**外します**。~~ここを切っておかないと、なぜかエラーが出ます~~。エラーというか、コンポーネントを追加できません。追加しようとした時、エラーが出ます。dllの参照に問題があるみたいですが、正直よく分かりません。情報求む。

(2022/05/14追記)
どうやら、レジストリのUnityNuGetのバージョンが4.5.0を使用しているのに対し、KlakNDIのバージョンが4.5.3でズレている所が怪しいかも？マネージドdllのバージョンを合わせた方がいいとのことです。(にー兄さん、ありがとうございます)
![スクリーンショット 2022-04-23 15.57.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/02cfc2aa-d0eb-7be6-1e8b-732a6254d4bf.png)


## 1-3. PackageManagerからインポート
「Window > Packgage Manager」でPackageMangerを開きます。
左上から、「My Registry」を選択します。
![スクリーンショット 2022-04-23 16.02.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/7c1f8347-57de-ee1a-54a7-743d6a2689a0.png)
そして、以下を探し、右下の「Install」ボタンでインストールします。
**・KlakNDI**
**・System.Memory(NuGet)**

# 2. 送信側の設定
## 2-1. RenderTextureを作成
Projectビューの「＋ボタン」を押す > 「RenderTexture」を押す
名前はなんでもいいです。私は「SenderTexture」としました。
![スクリーンショット 2022-04-23 16.07.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/7206db66-e5cc-55e8-e852-3a77ea17f025.png)
また、解像度も指定しましょう。私は「1600x900」にしました。
![スクリーンショット 2022-04-23 16.13.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/bc04b194-a56c-1d00-ddc2-5c259e96fe19.png)

## 2-2. NDI送信用カメラの作成
### 2-2-1. カメラを追加
送信用プロジェクトには、2つカメラが必要になります。

**・送信用プロジェクト側の表示をするカメラ(Main Camera)**
**・受信用プロジェクト側にデータを送るカメラ(NDISenderCamera)**

既存のMain Cameraに加えて、「NDISenderCamera」(名前は自由)というカメラを作りましょう。
![スクリーンショット 2022-04-23 16.19.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/07418d0c-f232-8b42-3945-010669e3c03f.png)

### 2-2-2. 位置を合わせる
NDISenderCameraは、Main Cameraと同じPosition・Rotationにしましょう。見えているもの(Main Camera)と実際に送るもの(NDISenderCamera)が違うと具合が悪いと思うので。

### 2-2-3. RenderTextureをアタッチ
ヒエラルキーの＋ボタンから、「Camera」を押します。名前は、「NDISenderCamera」とします。名前に決まりはありません。
NDISenderCameraのインスペクタから、「Camera > Target Texture」に2-1で作成したRenderTextureをドラッグ&ドロップで追加します。
![スクリーンショット 2022-04-23 16.22.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/413a1e47-93a6-dc58-9313-08e849680541.png)

### 2-2-4. コンポーネント追加
次に、NDISenderCameraのインスペクタに「NdiSender」というコンポーネント(スクリプト)を追加します。AddComponentというボタンを押し、検索をかけるとすぐ見つかります。
![スクリーンショット 2022-04-23 16.24.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/66ea69ad-2740-28f8-9b80-ad03a334e183.png)

### 2-2-5. NdiSenderの設定
(1) NdiSenderの「CaptureMethod」を「Texture」にします。
![img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/0886da27-9597-7784-95a8-8d25fdef1727.png)

(2)NdiSenderの「NDI Name」に、送信するNDIの名前を入力します。名前は自由です。今回は、「NDISender」としました。

(3)表示された「Source Texture」に2-1で作成したテクスチャをドラッグ&ドロップで設定します。
![スクリーンショット 2022-04-23 16.34.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/36f10ef8-f4d5-e02a-2de3-ecaf36597249.png)

ちなみになぜ2つのカメラで役割を分けるかというと、NDISenderCameraにはRenderTextureをアタッチしているからです。アタッチすると、カメラが映らなくなります。送信側・受信側で同じものが映ってもいいなら、MainCameraの子にNDISenderCameraを指定し、MainCameraをカメラワークするといいでしょう。

## 2-3. 適当にオブジェクト配置
映したいものが既にある場合、この工程は不要です。
何もなかったら、キューブの一つでもカメラの前に配置しておきましょう。
![スクリーンショット 2022-04-23 16.42.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/5c1d1f09-0032-6780-4874-e16d0415bb75.png)

## 2-4. ビルドする
(1)「File > Bulid Settings」を押し、ビルド設定ウィンドウを表示します。
(2)「シーンを追加」ボタンで、現在のシーンを追加します。
(3)右下の「Build」を押します。
![スクリーンショット 2022-04-23 16.44.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/9f4881f6-8afc-9416-cc23-7b2773641c13.png)

保存先や名前を聞かれますが、適当で問題ないです。ただし、ビルドするとフォルダやファイルが６つほど生成されて保存先が汚くなります。なので、先に「NDISender」的な名前のフォルダを作成して、その中にビルドすることをおすすめします。

# 3. 受信側の作成
受け取り用のシーンを作成します。
もしくは、受け取り側の別プロジェクトを作ります。その場合、送信側と同じようにKlakNDIを導入しましょう。手順1番(1-1〜1-3)だけでいいです。送信側の作成は不要です。
## 3-1. RenderTextutreを作成し、マテリアルにする
2-1と同じ手順でRenderTextureを作成します。
その後、Projectビューの＋マークを押し、マテリアルを作成します。Shaderは「Standerd」になっていると思いますが、これを「Unlit > Texture」にします。そして、RenderTextureをアタッチします。
![スクリーンショット 2022-04-23 16.49.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/0e1a3a74-1749-8281-8cc8-2f941edadf84.png)


## 3-2. スクリーンを作成
(0)まず、ビルドした**送信側**のファイルを実行しておきましょう。

(1)ヒエラルキーの＋ボタンを押し、「3D Object > Quad」を押してQuadを作成します。
![スクリーンショット 2022-04-23 16.54.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/b5206754-3a58-7680-788d-f6e1f8b3bd67.png)
NDIで受け取った映像を映すスクリーンなので、PlaneやCubeでも問題はありません。(VR系ではQuadをスクリーンにするのが一般的な気がするので、特別理由がなければQuadがいいでしょう)
Quadの縦横比は、RenderTextureと同じ縦横比にしましょう。

(2)Quadに3-1で用意したマテリアルをアタッチします。

(3)Quadに「AddComponent」でNDIReceiverを追加します。![スクリーンショット 2022-04-23 16.59.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/74a49788-b7b3-bd36-6f2e-f1e2e4283451.png)

(4)NdiReceiverには「NDI Name」という項目があります。手入力もできますが、スペース・大文字小文字など多分間違えてうまく行きません。右にあるボタン「Select」を押し、2-2で指定した送信側のNDI Nameを探します。名前は、[PC名(NDI名)]という感じになっています。

(5)「Target Texture」には、3-1で作成したRenderTextureを指定します。

## 3-3. 実行
実行してみます。すると、Quadに映像が映し出されるはずです。
以下は静止画ですが、送信側でキューブが動くと、受信側でもキューブが動いて見えます。
![スクリーンショット 2022-04-24 12.37.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/3d64ea97-9613-4452-4629-7fb7deb8432b.png)


# 4. トラブルシューティング
**・Canvasが映らない！**
→ワールド空間しか映らないようです。

**・映像が歪む！**
RenderTextureとQuadのアスペクト比が一致していない可能性があります。

**・NDISender、NDIReceiverが追加できない**
→「Project Settings > Player > Other Settings > Assembly Version Validate」のチェックを外す。それでも出てこなければ、Unityを再起動する。

**・送信側の画面が真っ暗。でも受信側で映る**
→RenderTextureをアタッチしたカメラは、映像を映しません。

**・送信側も、受信側もオブジェクトが映らない**
→Unityで初歩的なミスをしている可能性あり。カメラのインスペクタから「near」「far」の指定が正しいですか？nearより近い・farより遠いと映りません。

# 5. まとめ
いかがでしたでしょうか。今回は、KlakNDIの使い方を紹介しました。
エンジニア側はサーバを用意せず、LANで繋がれたネットワーク内で映像を共有できます。