がなかったので、自分で開発した。その後発表された公式アプリやSparkoCamとの差についてはこちらを参照。
tl;dr
- カメラからライブビュー (LV) を取ってきてOBS経由で仮想カメラにするソフト mtplvcap をGoで書いた
- PCやスマホからカメラのフォーカス等を制御できるリモコンもある
- libusbとOBSのおかげで Windows/macOS/Linux 全対応!
- マジめっちゃ動作確認情報を欲してるので、動いた/動かなかった情報を@puhitakuにガンガン送ってほしい(DM可)
最新リリースと動作確認情報(2020/11/26 現在)
Version 1.1.2リリース。
開発者 puhitaku は新しい機種での動作確認を渇望している。以下の機種以外でもし動いたら是非 Twitter で教えてほしい。
- D3200(lvisi さんありがとうございます!)
- D3300(unasuke さんありがとうございます!)
- D5000(rch850 さんありがとうございます!)
- D5100(shigureanko さんありがとうございます!)
- D5300
- D5500(nasustim さんありがとうございます!)
- D600(ohtayo さんありがとうございます!)
- D610(hazlitt さんありがとうございます!)
- D7000(takashi0314 さんありがとうございます!)
- D7100(TheMidlander さんありがとうございます!)
- D7200(br_spike_love さんありがとうございます!)
- Z6(ShadowXii さんありがとうございます!)
- Z7(zacheadams さんありがとうございます!)
類似ソフトウェアとの比較
Nikon公式のWebカメラ化アプリ「Webcam Utility」(以下、WU)やSparkoCam(以下、SC)との違いは以下の通り。(情報は2020年11月26日現在)
mtplvcap | WU | SC | |
---|---|---|---|
OS | Win, Mac, Linux | Win(MacはTBA) | Win |
課金 | Free | Free | Paid |
PCからの撮影設定 | Yes | No | Yes |
機種 | D3200, D3300, D5000, D5100, D5300, D5500, D600, D610, D7000, D7100, D7200, Z6, Z7 他随時追加中*1 | D5, D6, D500, D750, D780, D810, D850, D3500, D5300, D5500, D5600, D7200, D7500, Z5, Z6, Z6 II, Z7, Z7 II, Z50 | D3, D3s, D3X, D300, D300s, D4, D4s, D5, D500, D5000, D5100, D5200, D5300, D5500, D5600, D6, D600, D610, D700, D750, D780, D7000, D7100, D7200, D7500, D800, D810, D810A, D800E, D850, D90, Df, 1 V3, Z6, Z7, Z50 |
Webcam Utility は Beta 版でほぼ最新の機種のみへの対応を発表した。その後2020年11月4日に正式版がリリースされたが、依然として一部の機種にしか対応していない。mtplvcap は Webcam Utility がサポートする機種を完全サポートし、さらに広い範囲の機種へ対応することを目指している。
使い方
日本語のREADMEを書いておいたのでそれを参照してください。
経緯
昨今のアレにより手持ちの一眼をWebカメラにするのが流行っている。CanonのWebカメラソフトはBetaながらMacとWindowsに対応してきたし、SIGMA fpはなんとUVCに対応している。 Sonyも2020年8月現在Windowsのみながら公式対応を発表した*2。しかしどうもそれ以外のベンダーは対応が遅れている。Nikon*3ユーザーな僕は、家で寂しく指をくわえるしかなかった。
4月以降はインカメが最高なPixel 3で快適にビデオ通話できてたし、一眼をわざわざ使う理由は正直ないのだが、
やっぱり…一眼で撮れたら嬉しいよね…。
ということで、開発に踏み切った。
日頃はほぼMac + ヘッドレスなLinuxの構成なので、Macで写したい。既存手法で出ているv002 Camera Liveや謎の海外ソフトで頑張る方法だと、Macのみ・Windowsのみの対応となり汎用性がない。ソフトでライブビューを表示してそのウインドウをキャプチャするなんていう記事もあるけど、ゲーム配信じゃないんだし…とてもエレガントとはいえない。
ではどうやって画を取ってきて仮想カメラに流し込むか?その算段はついていた。カメラからMTPで画を取り出し、WebSocketで配信、それをOBSのBrowserSource(OBSにエンベッドされたChromiumの画面をソースにできるやつ)で表示してOBSの仮想カメラに流すというものだ。
MTPとはMedia Transfer Protocolの略で、デバイスの制御とファイルのやり取りを網羅しているプロトコルだ。ベネッセ個人情報流出事件で用いられたテクニックはMTPと言えば思い出す人もいるかもしれない。USB Mass Storageとは異なるのでWindows以外では扱いにくくよく厄介者扱いされるが、機能的にはMass Storageよりも豊富なため携帯プレーヤーなどではデファクトスタンダードとなっている。
開発
要件は以下のように決めた。
- Windows/macOS/Linux全対応
- 昨今のカメラベンダーの対応に業を煮やしていたので
- Goで書く
- cgoが神
- リンクが楽
- ランタイムがいらない
- USB部分と仮想カメラ部分はOS間で差異があるためlibusbとOBSに任せる
色々探していると、これまたドンピシャなOSS go-mtpfs を発見した。AndroidなどのMTPデバイスとlibusb経由で低レベル通信をしつつ、FUSEを使ってマウントするものだ。
USBの低レベル通信とWebサーバーによる配信を1プロセスでやるにあたって、Go + libusbで書きたいと思っていたので、まさに願ったり叶ったり。macOSでデバイスの初期化が上手くいかない問題はあったもののGoLandのデバッガーのお陰でスムーズに解決し、forkした。
まず取り掛かったのはライブビューの開始。MTPではuint16の命令番号的なのを送りつけることで動作を命令することができる。例えば、ライブビューの開始は0x9201
が対応している。これを送りつけたり応答をパースしたりする部分はgo-mtpfsの力を借りる。
GoのコードからMTPでNikon D5300のLive ViewをONにできた!まず一歩! pic.twitter.com/tfwP7WkpSj
— Takumi Sueda (@puhitaku) 2020年7月8日
次に取り掛かったのはライブビューの画の取得。ここでちょっと心拍数が上がってくる。これもまたライブビューの開始と同様に 0x9203
を送りつけるとキャプチャできる。
LVの画像データ取得できたぜキタキタキタ pic.twitter.com/I9RoNqk4Vg
— Takumi Sueda (@puhitaku) 2020年7月9日
この画像をOBSのBrowserSourceで表示するには、フロントエンドを用意して、画像シーケンスを配信する必要がある。これはWebSocketでサクッと解決できた。
Nikon D5300→USB (MTP)→Goで書いたコード→WebSocket→ブラウザ と映像ストリームを渡すことに成功。あとはOBSのBrowserSourceで表示させれば…マルチプラットフォームなNikon一眼Webカメラの完成や!! pic.twitter.com/nANlR10sCN
— Takumi Sueda (@puhitaku) 2020年7月9日
そしてそして、お待ちかねのOBS + Zoomの結合も難なく成功!やったー!
キター!! pic.twitter.com/U54Wwe8JDJ
— Takumi Sueda (@puhitaku) 2020年7月9日
ひとまずのマイルストーンを達成したので、LinuxとWindowsでも動作確認。結論から言うと、WindowsのWSL 1では動作しなかったが、MinGW (MSYS2) では楽勝で動かすことが出来た。やはり年の功というか、歴史が長いだけあってのことか。MinGWだとネイティブのexeが出てきてくれるので、環境を用意する障壁がWSLよりも圧倒的に低い。これは超嬉しかった。
WSLでもlibusbのcgocallでSEGV…ハァ…
— Takumi Sueda (@puhitaku) 2020年7月11日
結局MSYSを入れるハメに…😇😇めんどくせぇ👺👺👺👺👺👺👺
— Takumi Sueda (@puhitaku) 2020年7月12日
Windowsでもlibusbキター!!!! pic.twitter.com/BCtFphc2Y7
— Takumi Sueda (@puhitaku) 2020年7月12日
この後、紆余曲折を挟みつつも*4、ISOや絞りも変えることができた。
画像が安定して撮れるようになったところで、リモコンの実装に着手した。
リモコンはBootstrap + jQueryで書いた古式ゆかしいフロントエンド*5で、絞り・ISO・オートフォーカス(一定間隔でAFさせるのも設定可)・フレームレート制限を設定できる。カメラのダイヤルでモードをAUTOにすれば自動で輝度が調整されるので、それで十分であれば絞りやISOを手で変更する必要はない*6。
./mtplvcap -host 0.0.0.0
という風に外からのアクセスもListenするようにすれば、スマホからでも操作できる。
まとめ
当初はD5300とD3300でしか確認できていなかった動作も、ユーザーの皆さんのおかげで今では13機種まで増えた。あなたにもぜひお手元のNikonカメラで動作を確認してみて欲しい。
なお、MTPで通信をするカメラであれば、原理上他メーカーでも対応が可能なはずだ。やり方としては、USBのVendor IDとProduct IDを見て動作を振り分ける方法を想定している。今はまだこの仕組みはないが、もしMTPで通信すると判明しているカメラがあって、私に貸していただけるならば実装を引き受けることも可能かもしれない。
*1:現在動作確認ができているもののみを挙げている
*2:対応機種も幅広くて好感が持てる
*3:当初は非公式かつWinのみの仮想カメラソフトを公式が紹介するのみで、最近WindowsとmacOSにのみ対応したNikon Webcam Uitlityを公開した。
*4:Arrayなどを内含できるDevice Propertyなる可変な構造体があり、例えばISO値はこれで送られてくる。Goは可変な構造体は扱いにくくたいていreflect祭りになる。この割と複雑なエンコード・デコード処理が実装されておらず、go-mtpfsのコードを手で紐解く必要があった。
*5:いわゆるモダンさはないけど、これでいい。当然node.jsなどに触れることもないので、超シンプルになってくれるのが最高。
*6:現在はカメラの動作モードを見に行く処理がないので、AUTOモードで絞りやISOを変更しようとするとAccessDeniedが返ってくることに注意