デレステフォトスタジオのリアルタイム透過プレイヤーをつくった
Touch Barで卯月をつんつんしてから一年が経った。 今年の新ネタはiPhone X関連かと思っていながら予約に負けたので,穏やかな心でイープラスに勝利しつつ文化の日となった。
というわけで今日は文化の日につくった,↓のツイートにあるデレステフォトスタジオのリアルタイム透過プレイヤー,PhotoStudioPlayerの話を書く。
デレステフォトスタジオがブルーバック対応なので,iPhoneの画面をキャプチャしつつクロマキーして透過再生するプレイヤーをつくった。意外にも公開されている情報だけでつくれた。アプリとソースコードはgithub https://t.co/h1zn5MXdSr pic.twitter.com/l24Xgq2oyJ
— ばんじゅん🍓 (@banjun) 2017年11月3日
きっかけ
ちょうど前日に,デレステにフォトスタジオという新機能の追加が発表されたところだった。
プロデュースノートに、新機能「フォトスタジオ」を追加しました!
— スターライトステージ (@imascg_stage) 2017年11月2日
自由にカメラを操作しながら、アイドルにダンスやポーズを「オーダー」できちゃいますよ!https://t.co/mIoEjCBQs4 #デレステ pic.twitter.com/9ecPPChUjW
カメラの視点が自由に回せてズームインアウトもできるということで,従来カメラに対しては(縦化以外では)なにもできなかったデレステの,スクショの幅が増えた。当然MVのようにキャプチャしてLoveLiverで切り取ればライブフォトにもできる。無限に遊べる。
9年前のニコマス
さらにアイマストドンのタイムラインをみていると,どうやらブルーバックにできるらしく,スクショを経由して,アイドルだけを切り抜いた透過画像を作れるとのこと。これはもしや・・・昔のニコマスの・・・とiMacのディスクをSpotlightし,かつて作った透過プレイヤーのスクショとコードを発見した。
昔はQuartz Composerというのがあってだな,そこのシェーダー的なのでブルーバックを透過させれば,低CPU負荷で透過再生できて,そのqtzファイルを透過ウインドウで再生するアプリをつくると,デスクトップにオーバーレイできたんじゃ (デレステのフォトスタジオに思う) pic.twitter.com/JG8AqZ9zUn
— ばんじゅん🍓 (@banjun) 2017年11月2日
どうやら遅くとも2008年7月ごろのニコマスにはブルー(グリーン)バック素材の動画があったようで,私はいまはなき(なくはない?)当時最先端のQuartz Composerで,動画をリアルタイムに透過しながら再生するプレイヤーをつくっていたようだ。シェーダーめいたなにやらで色変換を記述することで,LLVM的ななにかでGPUに合わせてコンパイルされ透過がGPU処理となる,ような触れ込みだったはず。 当時のmacOSのAPIではこのQuartz Composerのファイルをあたかも動画ファイルのようにプレイヤーのViewに読み込ませることができた。あとは非矩形のウインドウを描く要領で背景透過ウインドウにすれば,アイドルだけがデスクトップに描画されるという仕組み。(→このプロジェクトをHigh SierraとXcode 9でビルドして動かす話は,老人会LT需要があったらやりますよ?)
PhotoStudioPlayer構想
あれから9年経ったいまならもっとすごいことが出来るのではないか。iPhone画面はQuickTime Playerで60fpsでプレビューとキャプチャができる。その経路をフックできれば,iPhoneの画面をリアルタイムに透過するプレイヤーができそう。さらにiPhoneでフォトスタジオのアイドルをフリックすれば,アイドルの向きを変えることもできる。
技術的課題を取り除いて透過プレイヤーを支える技術,の構築にひとまずフォーカスする。明らかな障壁はキャプチャ方法である。
- QuickTime Playerで録画する → ふつうに実現可能だが,録画ファイルよりはリアルタイム処理したい
- https://github.com/libimobiledevice/libimobiledevice をつかう → ライトニングの通信を解析した系があったような,と見てみたが,iOS 11では動かせなかった。深入りしない。
- AirPlayをつかう → 出来そうだが圧縮で不利なのと,調査コストは他に比べて低いと分かりきっているわけでもない
- iOSScreenCaptureAssistantつかう → QuickTime Playerの録画に使われるプロセス。どこが不可能ポイントかすら分からないのでそれが明らかになるまで調べてもいい。
iOSScreenCaptureAssistantの調査
なぜかふつうにmanがある。
iOSScreenCaptureAssistant is used by the CoreMediaIO Device Abstraction Layer Plug-In that provides audio/video capture from iOS devices using AVFoundation Capture APIs. The process allows multiple applications to simultaneously capture from the same iOS device.
複数プロセスからの同時キャプチャにも配慮した設計らしい。実際にQuickTime Playerを2プロセス起動すると,2画面で同時に(やや遅延に差は出る)同じiPhoneをキャプチャできる。 XPC的な制約があるのかはともかく,機能は期待できる。 このプロセスは /System/Library/LaunchDaemons/com.apple.cmio.iOSScreenCaptureAssistant.plist から起動されるようだ。
manのCoreMediaIOとは
https://developer.apple.com/library/content/samplecode/CoreMediaIO/Introduction/Intro.html
CoreMediaIO DAL (Device Abstraction Layer) とは https://developer.apple.com/library/content/samplecode/CoreMediaIO/Listings/Sources_Extras_CoreMediaIO_DeviceAbstractionLayer_Devices_Sample_PlugIn_CMIO_DP_Sample_PlugIn_cpp.html
なるほどわからないが‥ /System/Library/Frameworks/CoreMediaIO.framework/Versions/A/Resources/iOSScreenCapture.plugin にあるキャプチャプラグインを複数プロセスから触れるように,またはカメラとして認識できるように,ラップするものらしい。pluginバンドルとassistantプロセスのパターンは,CoreMediaIO DALではよくあるパターンのようだ。
OBSの調査
ところで3rd partyアプリである OBS - Free and open source software for live streaming and screen recording https://obsproject.com/mantis/ では,iPhoneのキャプチャとクロマキー合成が可能であるとみつける。iPhoneがソースに選べるとは知らなかったが,CoreMediaIO DALになっている仕組みからいって,3rd partyから読む手段はあるのではないか?と機能を探していて,まさにそのものがみつかった。
やりたいことのほとんどは,これで出来ている。画像の上にリアルタイムクロマキー透過したiPhoneを重ねている。あとはウインドウに切り出せれば。 ありがたいことにOBSのソースコードはgithubで公開されている。CoreMediaIO関連のコードをいくつか試していたので,見当をつけてgrepすると,iPhoneをソースとして検索するには,前段階である設定が必要であるとわかる。
さらにありがたいことに,この情報がWWDCで出ていたこともrefしてある。OBSはGPLだが,この行については完全にWWDCセッションのコピペなので,GPLにこだわらずもらってくる。 AppleがWWDCでこの情報を出したとき,私はWWDC現地にいたのだが,「Camera Capture: Manual Controls」というタイトルでこの話を出すのは初見回避というかなんというか。完全にウォッチ対象外であった。
(5:34 -)
Swift最小実装化
ともかくこれをpure Swiftで実装しなおして動くのを確認した。
これでAVCaptureDeviceまで来ているので,iOSアプリ勢にもおなじみのポイントまで辿り着いた。 おそらく最も簡単に低負荷再生するにはAVCaptureVideoPreviewLayerであろうということで,そこに置いて,クロマキーなしのキャプチャ表示が実現した。まるでQuickTime Playerである。

クロマキー透過
AVCaptureVideoPreviewLayerのまま軽量な変換ができるとは限らない。これは軽量だが通常のCALayerではない。もちろんキャプチャセッションからサンプルバッファーをもらって画素のメモリを見てしまえばなんらかは変換可能だろうが,できればコードから直接メモリをみたりしたくない。そのあたりは裏でGPUをつかってよろしくやってくれる期待感をこめた実装にしたい。
CoreImageのCIFilterを使ってみる。Appleがオススメするクロマキーの例は,CIColorCubeという色変換のLook Up Tableのフィルタを使うことらしい。
Subclassing CIFilter: Recipes for Custom Effects
ただしそのままではlayerにCIFilterは当たらない‥と思っていたがどうやら,親ビューのlayerUsesCoreImageFiltersをtrueにすれば適用されるようになる。
view.layerUsesCoreImageFilters = true previewLayer.filters = [ChromaKeyFilter.filter()]
これで,昔のように,ウインドウの背景色をclearにしてnon-opaqueにして,アイドルのみが描画される透過プレイヤーが完成した。
PhotoStudioPlayerアプリ・コード公開
iPhoneとMacがあればビルドせずすぐ使えるようにアプリを公開するのと,アプリはともかくこの一連の技術を使ってさらに別のものを作れるようにするのと,という観点で,githubに公開・リリースしてtwitterに貼った。
PhotoStudioPlayer公開その後
透過した状態の静止画キャプチャ保存もあったら便利ではあると思って,機能追加した。その話はまた。
@mzp のPull Requestによって,ウインドウの常時前面表示と,複数デバイスのキャプチャ対応(切り替え,ではなく同時表示も可能)に対応した。
https://t.co/ljKNPmDRrR に複数デバイス対応をつっこんだら最高になってきた pic.twitter.com/BVBZe30h02
— mzp (@mzp) 2017年11月5日
iPhone + Mac + デレステ,という組み合わせ以外のプラットフォームにも適用したいという動きがあるようで,いくつか既に実装されていた。 Windows:
Android:Windowsでやってみた pic.twitter.com/Bz2xZQTKOv
— ミクミンP/Kazuhiro Sasao (@ksasao) 2017年11月6日
moonmile/PhotoStudioPlayer at m@suda https://t.co/RjDi862zRA
— Tomoaki Masuda (@moonmile) 2017年11月7日
--
背景差分バージョン。こっちのほうが軽いらしい。
スタックを食い潰して落ちるので、Dispose が足りないっぽいが。 pic.twitter.com/BvCqjQPBLK
なんとなく,手前のブルーバックiPhone + 奥のデスクトップ画面 + 卯月,という文法で動画投稿されているのが,おもしろい。
GitHub Trending Swift Developer
かつてないほどtwitterからgithubにページビューが流れたなと思い,ふとGitHubのトレンディングのページをみると,Trending Swift Developerの23位に入っていた。repoの⭐️は48になった。
GitHub Trending Swift Developer 入りしました https://t.co/v2BNZvU0W9 pic.twitter.com/H9KuLVYzgh
— ばんじゅん🍓 (@banjun) 2017年11月7日
アイマスハッカソン
このあたりの話を含めて,技術はもちろん,よりアイマスに寄った方向性の話も,もっとしたいと思います。 今年の冬のアイマスハッカソンは12月16日(土)とのことなので,是非そこで会いましょう。おはなししましょう。
次回のアイマスハッカソン2017は12月16日(土)になりました!!ご参加の皆様はご周知のほど、よろしくおねがいしますわ! #imas_hack
— ぼでー (@bode_mmk) 2017年9月24日