追試：FreeBSD で USB 接続の HDMI キャプチャが使えた

[しまねソフト研究開発センター](https://www.s-itoc.jp)（略称 ITOC）にいます、東です。

FreeBSD Advent Calendar 2024 9日目 に、@mina_im さんが投稿された記事、[「FreeBSD で USB 接続の HDMI キャプチャが使えた」](https://qiita.com/mina_im/items/1e37ebc84531ebf52815) を見て、これは良いことを知ったと私もさっそく購入しようしましたが、記事の通り４年も前の製品で、同型機の購入はおそらく不可能だろうと思いました。
そこで、現在入手可能な製品でも同様な形状のものなら、記事と同じ方法で使えるのではないかと思い、以下に示した製品を購入してみました。

型番：KLK-TYPE-LZK
メーカ：Newluck

![202501-1_KLK-TYPE-LZK.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/2b1a6b66-6815-a704-d549-e913d64b2cd3.jpeg)

結果、記事通りの手順で使うことができたので、報告を兼ねて｢FreeBSD Advent Calendar 2024の余った箇所を12月25日を過ぎたあとに書いてみよう会?｣会員に参加させてもらうべく記事にします。
なお、私はこの方面に関しては全く素人なので、この記事は先の記事のおさらいと、私の試行錯誤の結果を記しただけです。


# デバイス認識状況

OS: FreeBSD 14.2 RELEASE
WindowManager: Xfce 4.18

```
$ dmesg
ugen1.3: <MACROSILICON USB3. 0 capture> at usbus1
uhid1 on uhub3
uhid1: <MACROSILICON USB3. 0 capture, class 239/2, rev 2.00/21.00, addr 3> on usbus1
uaudio0 on uhub3
uaudio0: <MACROSILICON USB3. 0 capture, class 239/2, rev 2.00/21.00, addr 3> on usbus1
uaudio0: No playback.
uaudio0: Record[0]: 96000 Hz, 1 ch, 16-bit S-LE PCM format, 2x4ms buffer. (selected)
uaudio0: No MIDI sequencer.
pcm5 on uaudio0
uaudio0: No HID volume keys found.
```

```
$ usbconfig list
ugen1.3: <MACROSILICON USB3. 0 capture> at usbus1, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON (500mA)
```

先達の記事と全く同じですね。チップ名はわかりませんが、同じものを使っているのかもしれません。
音声はサウンドデバイスとして認識されるのも、先の記事通りです。

```
$ cat /dev/sndstat
Installed devices:
pcm0: <NVIDIA (0x0051) (HDMI/DP 8ch)> (play)
pcm1: <NVIDIA (0x0051) (HDMI/DP 8ch)> (play)
pcm2: <Realtek ALC888 (Rear Analog)> (play/rec) default
pcm3: <Realtek ALC888 (Onboard Digital)> (play)
pcm4: <Realtek ALC888 (Onboard Analog Speaker)> (play)
pcm5: <MACROSILICON USB3. 0 capture> (rec)
```



# 導入するツール

cuse カーネルモジュールと webcamd を導入します。恒久的に使えるように、起動時の設定も追加します。

```
pkg install webcamd
pw groupmod webcamd -m <username>
```

```/etc/rc.conf
kld_list="cuse"
webcamd_enable="YES"
```

これで一度再起動してからデバイスを挿すと、ちゃんと webcamd がターゲットデバイスを掴んで起動してくれました。

```
$ ps ax | grep [w]ebcamd
1345  -  I<s   0:00.01 /usr/local/sbin/webcamd -i 0 -d ugen1.3 -B -U webcamd -G webcamd
```

# 任意のビューワーで表示する

今回は、HDMI 端子には PCを接続し、1360x768 ドット 60Hz の映像を入力してテストしました。


## pwcview

先の記事通り、pwcview は問題なく表示してくれます。

### インストール
```
pkg install pwcview
```

### 実行
```
pwcview -d /dev/video0 -f 30
```

## VLC

先の記事では、カクカクになって使い物にならないと記されている VLC です。

### インストール
```
pkg install vlc
```

### 設定・実行

`メディア` > `キャプチャーデバイスを開く` で表示されたダイアログから、ビデオデバイスに、`/dev/video0` を指定することで表示できます。
![202501-1_16-42-54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/85d0ec27-3ae0-d45b-bd7b-59b0bfa6ad71.png)
しかしこのままでは、たしかに表示はカクカクしていて、ちょっと厳しい感じです。

`ツール` > `コーデック情報` を選んで情報を見ると、フレームレートが５ (fps) と、動画というには程遠いですね。解像度も、1920x1080と、入力している解像度 1360x768 とは違います。

![202501-1_16-45-23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/d0e61a05-db15-f624-de52-b1053a7acdc1.png)


ツールを使って調査してみます。
まずは、インストール。
```
# pkg install v4l-utils
```

v4l2-ctl コマンドが使えるようになるので、それを使って以下の通り。
```
% v4l2-ctl -d /dev/video0 --list-formats

ioctl: VIDIOC_ENUM_FMT
        Type: Video Capture

        [0]: 'MJPG' (Motion-JPEG, compressed)
        [1]: 'YUYV' (YUYV 4:2:2)
```

この情報から、このデバイスは Motion-JPEG と YUYV の２種類のコーデックで出力できることがわかります。
更に詳しく、
```
$ v4l2-ctl -d /dev/video0 --list-formats-ext

ioctl: VIDIOC_ENUM_FMT
        Type: Video Capture

        [0]: 'MJPG' (Motion-JPEG, compressed)
                Size: Discrete 1920x1080
                        Interval: Discrete 0.017s (60.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                Size: Discrete 1600x1200
                        Interval: Discrete 0.017s (60.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                Size: Discrete 1360x768
                        Interval: Discrete 0.017s (60.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                Size: Discrete 1280x1024
                        Interval: Discrete 0.017s (60.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                Size: Discrete 1280x960
                        Interval: Discrete 0.017s (60.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                Size: Discrete 1280x720
                        Interval: Discrete 0.017s (60.000 fps)
                        Interval: Discrete 0.020s (50.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                Size: Discrete 1024x768
                        Interval: Discrete 0.017s (60.000 fps)
                        Interval: Discrete 0.020s (50.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                Size: Discrete 800x600
                        Interval: Discrete 0.017s (60.000 fps)
                        Interval: Discrete 0.020s (50.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                Size: Discrete 720x576
                        Interval: Discrete 0.017s (60.000 fps)
                        Interval: Discrete 0.020s (50.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                Size: Discrete 720x480
                        Interval: Discrete 0.017s (60.000 fps)
                        Interval: Discrete 0.020s (50.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                Size: Discrete 640x480
                        Interval: Discrete 0.017s (60.000 fps)
                        Interval: Discrete 0.020s (50.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
        [1]: 'YUYV' (YUYV 4:2:2)
                Size: Discrete 1920x1080
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1600x1200
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 1360x768
                        Interval: Discrete 0.125s (8.000 fps)
                Size: Discrete 1280x1024
                        Interval: Discrete 0.125s (8.000 fps)
                Size: Discrete 1280x960
                        Interval: Discrete 0.125s (8.000 fps)
                Size: Discrete 1280x720
                        Interval: Discrete 0.100s (10.000 fps)
                Size: Discrete 1024x768
                        Interval: Discrete 0.100s (10.000 fps)
                Size: Discrete 800x600
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 720x576
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 720x480
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
                Size: Discrete 640x480
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.050s (20.000 fps)
                        Interval: Discrete 0.100s (10.000 fps)
                        Interval: Discrete 0.200s (5.000 fps)
```

この情報と、先の VLC のコーデック情報から、YUYV, 1920x1080 では、5fps しかサポートしていないことがわかります。
一方、Motion JPEG を選べば、60fpsまでサポートしているようなので、次の通り設定をしてみます。

メディアを開くダイアログの `詳細設定オプション` ボタンをクリックし、詳細設定オプションダイアログが表示されたら、以下の通り入力します。
 * ビデオ入力のクロマ形式 `MJPG`
 * 幅 `1360`
 * 高さ `768`
 * フレームレート `60`

![202501-1_15-03-24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/1df0d256-3e3e-e7c5-25cf-23f0c227a95f.png)

この設定で表示してみると、意図通り60fpsで表示ができました。
![202501-1_15-03-42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/ab59e328-26d4-f1bf-b0b8-daee2adae5ba.png)

一方、音声ですが、Motion JPEG ということもあり、おそらく動画データには音声が重畳していないと思われます。そこで、dmesg で表示されている pcm5 on uaudio0 つまり、/dev/dsp5 から音声入力すればよいと思うのですが、残念ながらこれ以上調べきれませんでした。詳しい人おしえてください。

なお、この詳細設定は保存されませんので、次回起動したらまた最初から入力し直しです。
保存するには、以下の手順でデフォルト設定を変更すると良いようです。
 * `ツール` > `設定` を選び、設定ダイアログを表示します
 * ダイアログ下部の `設定の表示` を `すべて` に変更します
 * `入力／コーデック` > `アクセスモジュール` > `V4L` を選びます
 * さきほどの設定を入力し、`保存` をクリックします


## OBS Studio

最初に結論をいうと、OBSは音声を含めた動画表示と録画ができました。ただこのソフトは動画配信を目的としたもののため、ビューアとして使いたい場合は画面構成が少し違うと感じるかもしれません。

### インストール
```
pkg install obs-studio
```

### 設定・実行

実行すると以下のような画面が表示されます。

![202501-1_16-34-46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/ab338bc3-d658-273f-a32b-48f9275e6592.png)

ここへ、映像ソースと音声ソース、双方を追加します。

 * 画面下部、「ソース」の `[+]` アイコンをクリックします
 * 映像キャプチャデバイス(V4L2) を選びます

![202501-1_16-35-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/cd2382b8-6b1a-12af-33f7-3b483c9ac3ad.png)

表示されたダイアログは、そのままOKをクリックします。

![202501-1_16-35-35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/240cb761-4089-7d73-4b88-17f654e8a4fd.png)

次のダイアログでは、映像フォーマットは Motion-JPEG のはずですが、なぜかそれでは動画が表示されず、(Emulated) がついたものどれかを選ぶと表示されます。各々の違いはよくわかりませんが、比べてみると多少色味が違うことがわかります。ここでは、YU12 を選びました。

![202501-1_16-36-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/ddd5d27d-e4aa-e6ea-e42b-62744cddc065.png)

映像の追加ができました。

![202501-1_16-38-32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/9ea9e162-07b0-58c7-e8c8-d0c1530b19d9.png)

次に、音声ソースを追加します。

映像と同様に追加の操作を行い、音声入力キャプチャ (PulseAudio) を選びます。

![202501-1_16-38-43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/e5f417dd-429d-645b-e053-4cb6b051f936.png)

表示されたダイアログは、そのままOKをクリックします。

![202501-1_16-39-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/0996fadf-b0f7-bed9-889c-396c0fd059d2.png)

デバイス欄で、MACROSILICON USB3.0 capture を選び OKをクリックします。

![202501-1_16-39-27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/cc29c9ae-c1fc-c5b0-46ab-430fc00de4b1.png)

音声の追加ができました。

![202501-1_16-40-19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/5fc1e66b-45d1-de9f-1ee3-c209d8ae9603.png)

音声のモニタは、「音声ミキサー」ペインの歯車アイコンをクリックし、表示されたダイアログで音声入力キャプチャの音声モニタリングを `モニターと出力` にします。

![202501-1_16-40-58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504019/b7d42701-e504-a916-e92d-59eae1dc13bb.png)

以上で設定終了です。
これで リアルタイムに画像と音声が流れ、`録画開始` ボタンをクリックすると、mkv 形式で動画ファイルができます。

# おわりに

HDMI ビデオキャプチャデバイスが FreeBSD で使えるという情報をもとに、追試をしてみました。その結果、2025年1月現在購入可能なデバイスで、それなりに実用になるであろうレコーディング環境が得られました。
いろいろ苦労されたであろう先達たちに感謝して、この記事を締めくくろうと思います。