公式WebRTC plugin for Unityのサンプルを公開しました(Android向け)

前回 ↓ からだいぶ間あいてしまいましたが、続編です。

hammmm.hatenablog.com

前回WebRTCのソースからビルドしたプラグインですが、前回以降修正が入って、より最新に近いソースがビルド可能になりました。それを動かすためのサンプルコードを今回作成しました。一応ちゃんとUnityでWebRTCが動きます!ぱちぱちぱち。

プラグイン本体はこちらからダウンロードしてください。(以前より更新しました)

https://github.com/mhama/webrtc-dev-env/releases/tag/master_20180321_085858

プロジェクトはサンプルとして公開しました。

https://github.com/mhama/WebRtcUnityPluginSample

やれること

  • Socket.IOでの簡易なシグナリングを用いて、Unityアプリとブラウザ上のWebRTCクライアントとでリアルタイム動画を送信・受信できます。
  • 簡易なサーバープログラムを作成しました。サーバーホスティング等を用意しなくてもテストができます。

f:id:hammm:20180421020955j:plain

Unity用Socket.IOのライブラリはこちらを使わせてもらいました。

https://github.com/floatinghotpot/socket.io-unity

できないこと

  • シグナリング部分がサンプルレベルなので、エラー処理、状態管理などはザルです。
    まともにするには、サーバーコード、クライアントコードともに調整する必要があると思います。
  • ルームの管理を行っていません。
    同じサーバーに3人以上接続できますが、何が起こるかわかりません。
  • Unityエディタ上でWebRTC機能は動きません。WebRTCプラグインWindows/MacOSビルドができていないためです。今の所Androidビルド(実機)でのみ動作します。

サンプルの使い方

概要

サーバー(node.js)を起動し、ブラウザとUnityアプリの2つがサーバーに接続する形で通信(シグナリング)を行います。この通信によってWebRTCでの動画通信の下準備を整えることができ、準備ができたらP2Pで直接の通信が行われます。

f:id:hammm:20180421233903p:plain

続きを読む

WebRTC Unity Pluginサンプルをビルドする方法 (Android向け)

はじめに

あまり話題にはなっていませんが、本家webrtcライブラリのソースコードには、2017/5月ごろからひっそりとunity pluginのサンプルが入っています。しかし残念ながら、自分が探した限りでは、これをビルドしたライブラリのバイナリ配布や、それを使うUnityプロジェクトは公開されていません。

そこで、この使い方を模索していきます。 今回はひとまずこれをビルドする方法です。

1行で

Android向けのビルド済みライブラリファイルが以下のリンク先にあるのでダウンロードして頂けると良いと思います。詳しい使い方は調査中でもあり、また次回に。

https://github.com/mhama/webrtc-dev-env/releases

まあ、それだけでは味気ないと思うので、細かいことを書いていきます。

Unity Pluginサンプルとは?

こちらのディレクトリに存在するサンプルです。UnityのC#からWebRTCが利用できそうな内容になっています。サンプルといってもライブラリ側のみです。使う方法はサンプルもなく、任されています。

https://chromium.googlesource.com/external/webrtc/+/master/examples/unityplugin/

Android向けのインストラクションがこちらにありますが、ビルドの仕組みに関してだいぶ高い理解度を要する印象です。今回の記事は、基本的にはこの内容に従っています。

https://chromium.googlesource.com/external/webrtc/+/master/examples/unityplugin/ANDROID_INSTRUCTION

以下のREADMEには、PeerConnectionMという、C#側からネイティブのライブラリ機能を利用するクラスのサンプルコード が掲載されています。

https://chromium.googlesource.com/external/webrtc/+/master/examples/unityplugin/README

構成としては、以下のような形になっており、C言語定義の関数を通じてWebRTCのAPIに間接的にアクセスする形になっています。

C++ libwebrtcライブラリ本体
 ↕
C++ simple_peerconnection (クラス)
 ↕
C++ unity_plugin_api (C関数定義)
↑ ここまでが webrtcライブラリ (libjingle_peerconnection_so.so)
----------------------
↓ ここからがUnity Assets内
C# SimplePeerConnectionM (クラス)
 ↕
Unity 任意のスクリプト
続きを読む

REGZAタイムシフト用HDD AVHD-ZRC7 の内蔵HDDを交換してみた

はじめに

東芝のテレビREGZA Z8シリーズ等でタイムシフト機能(直近数日間の全番組を録画し続ける機能)を利用するための外付けハードディスク装置の、内蔵HDDを換装する話です。

アイオーデータ AVHD-ZRC7 は、3TB(3.5inch)+3TB(3.5inch)+1TB(2.5inch) の合計7TB が載ったもので、REGZA 47Z8 とUSBで接続します。基本的には単なるUSBハードディスクのガワが3つセットになったようなものです。これで、REGZA 47Z8では、6チャネル分のタイムシフトが可能です。最後の1TBはいわゆる通常の録画領域です。

2年9ヶ月ぐらいほぼ連続利用して、ついにへたってきたので交換を試みました。もうちょっと持ってほしかった気持ちはあります(汗。

今回の換装の結果としては、3TB+3TBを4TB+4TBに交換したので、容量アップで実質 AVHD-ZRC9 相当になりました。なお、4TB以上のHDDへの交換は、可能かどうかはわかりません。特にそのあたりに壁があるとも聞かないのでいけそうな気もしますが、推測にすぎません。

現象と原因推定

タイムシフトの過去番組をしばらく(10分程度)再生していると、再生が止まったようになったり、妙に早口で早送りするようになったり、画像と音声が一致していなかったりという現象が発生しました。途中から復帰することもあります。また、1チャンネルの約1日分が過去番組表から消えたりもしました。

この時点では、テレビが悪いのか、HDDが悪いのか、あるいはHDDのガワが悪いのかは特定しづらいところでしたが、REGZAタイムシフト機能ではハードディスク1個が3チャンネル分を担当しており、ちょうど調子が悪いのも特定の3つのチャネルに偏っていました。このことからHDDが悪いに違いない、ということで交換に踏み切りました。

なお、交換でうまくいかなかったら、USB3.0向けHDDケースを買ってそちらに装着する方法もあるので、無駄になることはないだろう、というバックアッププランは考えていました。

注意事項

  • HDDを入れ替えると、タイムシフトの過去動画はすべて消え去ります。引き継ぐなどが可能かどうかは不明です。残したいものは録画用のHDD等にムーブ・コピーしておきましょう。
  • 分解・交換は保証外の行為で、自己責任です。うまく動かなくてもメーカーのサポートは受けられないでしょう。
  • 作業としては比較的簡単な部類ではありますが、前提としてPC自作程度の経験はあったほうが良いように思います。
  • 交換用HDDとして、WD Blue (WD40EZRZ)を選択しました。動作はしているものの、良い選択かどうかは不明です。
  • 何にしても自己責任です!

HDDの仕様

AVHD-ZRC7に入っていたHDD

WesternDigital社のWD30EURX (回転数可変) でした。 AV-GPというラインの、動画に最適化されたモデルで、低発熱、低騒音とのことです。アイオー・データは同業他者とくらべて比較的信頼しているのですが、ここでも最適なHDDの選択を行っているといって良いでしょう。 なお、通常録画用の1TBのほうは調べていません。特別問題ないのでそのまま利用することにしました。

交換した新HDD

WD Blue 4TB (WD40EZRZ 5400rpm)と交換しました。最近は4TBで1万円以下でお手頃ですし、低騒音、低発熱を謳ってもいます。なお、回転数7200rpmのHDDもありますが、発熱が多く常時稼働のタイムシフトには向いていないので選ばないようにしたほうが良さそうです。電力もよりAVHD-ZRCのガワの想定した電力を超えてしまう可能性もあります。

交換手順

続きを読む

Insta360 Air (Dual Fisheye) 向けUnityシェーダーを書いた

概要

前回このような記事を書きました。

hammmm.hatenablog.com

今回は、Unity3Dを使ってInsta360 AirからのUSB経由の映像を球体にマップして見ることができるよう、シェーダーを作りました。

なお、Windows/Mac上でInsta360 Airからの映像を使いたいというだけであれば、今回のシェーダーがなくても、公式のスティッチソフトウェア(※)を使えば、最初からEquirectangulae形式での出力が可能になります。そちらのほうがスティッチ精度は高いでしょうし、特別なシェーダーも不要です。USBカメラと同じ方法で取り込むことができるはずです。

GearVRで使いたいとか、ネット経由で使いたいとか、遅延を可能な限り減らしたいとか、そういった用途の方には役に立つのではないかと思います。

制限事項としては、単純なスティッチ(合成)方法のため、つなぎ目が距離によって非常に目立ちます。

https://www.insta360.com/download/insta360-air こちらの “Webcam Software”

詳細

Insta360 AirのDual Fisheye形式 を Equirectangular形式 に変換して球体にマップするシェーダーを作りました。

Noraさんの ThetaShaderPack をベースにしています。ありがとうございます!いろいろ変更した結果だいぶコードが異なってきています。

シェーダー本体は これ です。

Insta360 Airの Dual Fisheyeは、おおまかにはTHETA Sと同様ですが、レイアウトが多少異なります。

  • Insta360 Airでは、映像の縦横比が 1:2 となっており余白はありません。
  • 中央で左右に分割すると、それぞれのセンサーの画像になります。
  • 各センサー画像において、Dual Fisheye画像での下のほうがカメラの下方向になります。 (THETA Sとは異なる)
  • 各FishEye画像を4度程度回転させて扱わないときっちりあわないようです。 (センサーが傾いて設置されている?)

同じシェーダで THETA S と Insta360 Air に両対応するようにしています。シェーダのパラメータで機種を選べます。 内部のパラメータをいじれば他のDual Fisheyeにも対応できるだろうと思います。

動作検証端末

ダウンロード

https://bitbucket.org/mhama/thetaoculuslivestreaming/downloads/

使い方

  • Unity3Dでプロジェクトを開いてください。
  • Unityで、Assets/ThetaLiveStreaming/Scenes/SimpleInsta360AirStreaming.unity を開いてください。
  • Insta360 AirをUSBポートにつないでください(※)
  • Playしてください

これでInsta360 Airからの映像がゲームビューに表示されると思います。

※ 最近出荷分のInsta360 AirにはUSBケーブルが入っていないという話を聞きます。その場合、PCにつなぐには、 カモン MBA-L01 USB(2.0) microB(メス)-A(オス)L型変換ケーブル(左向き) 0.1m のようなものが必要になるかと思います。

f:id:hammm:20170528013117j:plain:w600

注意

Insta360 Airは、THETA Sとくらべてレンズ間の距離が離れているため、THETA S以上にスティッチの誤差が目立ちます。オプティカルフロー等の技術を使い、重複部分を見てずらして合わせたりする技術が存在しますが、今回はシンプルな方法(テンプレートベース)を利用しています。


Insta360 Airの360度USBウェブカメラ(UVC)としての性能はなかなか優秀

概要

あるしおうねさんのこちらのツイートを見て、おっ!となって検証してみました。

PCとつなぐとこんな感じ。PC接続用の硬めのケーブルも標準でついてきます。

f:id:hammm:20170422233711p:plain:w400

Insta360 Airは、スマホと連携して360度カメラとして動作するというのが通常の使い方といえますが、VR/AR 関連開発者にとって見過ごせないのがそのUSBウェブカメラ、つまりUVC(USB Video Class)規格での動作です。UVC規格で動作すれば、PCやあるいはラズベリーパイ等で、様々なアプリや自作アプリから利用可能になります。

Insta360 Airから直接出力される映像はDual Fisheye(魚眼x2)形式です。今回はこのまま扱う前提での話です。

  • Dual Fisheyeはこのような出力になります。

    f:id:hammm:20170422230648p:plain:w300
    ※画像はカメラを寝かせた状態での結果なので参考まで。

  • リアルタイムスティッチソフトについて

    Insta360 Air用に、Windowsでリアルタイムにスティッチしてくれるソフトがあります。つまり、Dual Fisheye形式から、各種動画サイト等で一般的なEquirectangular(正距円筒図法)形式に変換した上で、ウェブカメラと同様のインタフェースで扱うことができるものです。

    以下のページから、英語モードにして、"Webcam Software" というタイトルのものが、この変換用のソフトです。

    https://www.insta360.com/download/insta360-air

今回は、利用用途として遅延を増やしたくない関係で、上記ソフトは一旦無視でいきます。Dual Fisheyeのまま使います。Unityのシェーダーとかでなんとかする前提です。

Unityのシェーダーとかの話は近いうちに書こうと思います。

amazonのリンクを置いておきますが、ヨドバシのほうがポイントがついてお得でした。

結論

先に結論を書きますが、Insta360 Air、360度対応のUSBウェブカメラとしてなかなか優秀です。MJPG 3008x1504 30フレーム というモードが特に有用で、ノイズはあるものの非常に高い解像感があります。今までTHETA SとキャプチャカードFEBON178を組み合わせていましたが、それを凌駕している印象です。特にUSB2.0環境でもつなぐだけで動作しますし、各種のウェブカメラ接続の手法がそのまま利用できます。

なお、入力したDual Fisheye画像をどう料理するかは今回は省略しますが、簡単に触れますと、右と左の正方形にわけたときに、それぞれの正方形の中央にレンズのセンターがきています。ただセンサーの配置の関係か、経度方向に4度程度傾いているようです。ご注意ください。

やや大きな難点としては、2つのレンズの間の視差がTHETAと比べると大きいため、近くのものと遠くのものを同時に綺麗に合成(スティッチ)することは難しくなります。この点はTHETA Sに分があります。Insta360 Airではスティッチソフトの高度化によってこれに対処しようとしているようです。

以下、詳細になります。

続きを読む

3Dプリンター QIDI TECH I をTMC2100 (SilentStepStick)で静音化してみた

はじめに

TMC2100チップを搭載したサイレント・ステップ・スティックと呼ばれるモータードライバモジュールを使ってQIDI TECH Iを静音化してみました。

f:id:hammm:20170318115531j:plain:w100 f:id:hammm:20170318115633p:plain:w150

先に結論を書いておきます。

  • メリット

    音量は明らかに下がる。「意外な音」はしなくなり、普通に機械が動いているという感じになる。

  • デメリット

    今までにはなかったシュー、シャー、ピャーというような高周波的なノイズが追加され、3Dプリンターの近くにいたり、他にノイズ源のない静かなところでは、この高周波が結構気になる可能性がある。

ちょっとザワついたオフィスのような場所では十分有効な静音化になると思います。なお、作業には多少のはんだ付け能力が必要です。

背景

一般的なプラスチックを積層するタイプ(FDM)方式の3Dプリンターといえば、動作時の特徴的な「変わった音」が印象的です。まるで昔のゲーム音楽のようなその音は、楽しい気分になることもありますが、意外なメロディーが発生するため「気になる」存在感を放ち、近くで動いているとノイズをなかなか意識の外に追いやれないのも事実です。ちょっとしたものを作る場合でも数時間以上になることが一般的のため、設置場所を選ぶ感じがあります。日本では、家庭にしろオフィスにしろ、十分な広さがとれないことも多く、静音化が求められているといえましょう。

他の静音化手法

ドライバモジュールを変更することのほかに、以下の静音化方法があります。

  • プリント速度を下げる

    プリント時にヘッドが動作する速度を下げることで、結構ノイズレベルは低下します。スライサーソフト側の設定で対処する必要があります。

  • ファンを交換する

    冷却用のファンが騒音源である場合は静音なものに交換するという手があります。

  • 防音箱に入れる

    3Dプリンタ全体を防音箱に入れる手があります。

QIDI TECH Iについて

今回のターゲットはQIDI TECH Iなので、簡単に紹介しておきます。

特徴

お安いわりに機能的には全部入りでちゃんと動く中華3Dプリンターです。サポートも丁寧なのがポイント。ただし日本語対応はカタコト。 MakerBot社が3Dプリンタの設計をオープンソースにしていたために、派生したクローン製品の一つです。 こういう経緯のため、おおよそMakerBot/FlashForgeの資産や知識も利用できるというメリットがあります。

その他特徴

  • 造形物の最大サイズ 23cm x 15cm x 15cm
  • ベッドの加熱が可能のため、一般的なPLA/ABSおよび他の素材も利用できる
  • 金属製でがっしりしている
  • そこそこ密閉されておりABSでの造形に有利、ノイズ的にも有利
  • エクストルーダ(押出機)2つ搭載

系譜

  • MakerBot Replicator系の血をひいています。今回は、メイン基板が"MightyBoard"(マイティボード)と呼ばれる系統であることを意識する必要があります。
MakerBot社のReplicator Dual
  ↓ クローン
FlashForge Creator Pro
  ↓ クローン
QIDI TECH I

QIDI X-Oneは?

同じQIDI社のX-OneはTECH Iと同様に、安価かつ評判も良いものですが、だいぶ系統の異なる中身の3Dプリンタです。特に今回やろうとしているドライバモジュールの交換についてですが、X-Oneではメイン基板に直接はんだ付けされているため、交換不可能ですのでご注意ください。

続きを読む

高解像度Motion JPEGストリーミングを低遅延で再生するAssetをプレビュー公開しました。

これは何?

このAssetを使うと、GearVR などで FullHDなどのMotion JPEG ストリーミングを低遅延(おおよそ0.2~0.4秒以内)で再生できます。ということは、THETA SのUSB/HDMIライブビューなんかをRaspberryPiやPC経由でWi-Fiで飛ばしてGearVRで一人称視点で眺める、つまりテレイグジスタンスっぽいことができるかも!です。あるいは、リアルタイム性を活かして、Raspberry Piとラズパイカメラを載せたラジコンから映像を飛ばしてFPV(一人称視点操作)なども可能です。

発端

以前の記事で、Raspberry PiからMotion JPEGでGearVRに配信するということを行いました。

hammmm.hatenablog.com

AVI Player with Playmaker actions というAssetの中のMovie Streamerを利用しましたが、遅延が数秒以上になることと、fpsが低いという問題がありました。

また、HLSでの配信も試しましたが、こちらは遅延が数十秒と、リアルタイム性に大きな問題をかかえていました。

そんなときにのしぷさんの記事

noshipu.hateblo.jp

を拝見して、Motion JPEGのデコード方法がわかったので、これだ!と思ってGearVRで動かそうとしてみましたが、ソースが高解像度の場合、単純な実装では安定動作しないことがわかりました。高画質で低遅延を実現するには、以下の問題をクリアする必要がありました。

  • 遅延(読み取りが遅く、未読み取りのフレームがサーバー側に貯まる問題)
  • 遅延(読み込み済みの後のキューが伸びてしまう問題)
  • ネットワーク読み込み速度の問題
  • メインスレッド負荷の問題

これらに対策を打った結果が今回のAssetになります。結果的にそれなりの規模の実装になってしまいました。ついでにAsset Store掲載を画策しているところです。

のしぷさんと、サンプルプロジェクトを作られた伊藤さん(@warapuriさん)に感謝しています!

特徴

www.youtube.com

  • スレッドを利用して、最大限サーバーの出力に追いつくように実装しています。
  • JPEGデコードはlibjpeg-turboを利用して高速化しています。
  • バックグラウンドスレッドでデコードするようにしています。これにより、メインスレッドに大きな負荷をかけず、スムーズな描画を阻害しません。
  • バッファの再利用により、メモリ使用/確保量もできるだけ抑えるようにしています。

ダウンロードについて

プレビュー版ということで、しばらくの間無料配布いたします。なお、もし商用利用されたいというような場合がありましたらお問い合わせください。

こちらからダウンロードできます。キーは mjpg です。

[Unity] MJStreamingPlayer Asset - BowlRoll

対応プラットフォーム

現状、Android (GearVR) および Windows 32/64bit 対応です。 Unityはちょっと古いですがバージョン5.3.4で確認しています。

利用可能なサーバープログラムの例(確認済み)

組み込み方法

  1. 本Asset (MJStreamingPlayer.unitypackage)をプロジェクトにインポートしてください。
  2. 再生対象マテリアルを持つGameObjectに、MJStreamingPlayerコンポーネントを追加してください。
    • 現在の仕様では、メインのマテリアルが持つメインのテクスチャとして、動画テクスチャがセットされます。
    • 特にこだわりがなければ、シェーダは Unlit/Texture にしてください。デフォルトの Standard シェーダも利用可能です。
  3. MJStreamingPlayerコンポーネントを設定してください。
    • ServerUrl: MJPGストリーミングサーバーのストリーミングURLをセットしてください。
    • PlayAutomatically: 自動で再生開始する場合はONにしてください。OFFの場合は、スクリプトからStartStreaming() を呼ぶ必要があります。
  4. 上記GameObjectが見えるようにCameraを設定し、UnityでPlayしてください。

組み込み例

  • 前項の方法で、以下の記事のプロジェクト(Oculus RiftでTHETA画像を表示)にも組み込めます! hammmm.hatenablog.com

  • 設定例

    WebCamDrawerは無効化して、かわりにMJStreamingPlayerを追加しています。 f:id:hammm:20161214210934p:plain

  • 動作例

    ※ここでは、Unityと同じPCで GMax IP Camera を動かし、THETA S のHDMI出力を FEBON178 経由でUSBウェブカメラ扱いで入力しています。 さらに、Android向けにして、osig, bundle-id等を設定するとGearVRでの動作も可能でした。 f:id:hammm:20161214230528j:plain

動作

  • フレームレートはサーバーが送信する速度および描画速度に依存します。
  • 無駄なデコードを避けるため、表示可能なフレームレート以上のデコードは行わず、スキップします。
  • テクスチャサイズはサーバーが送信するMJPGの画像サイズに依存します。

サーバーURL設定例

  • mjpg_streamerの場合
  • GMax IP Camera (MJPG版)の場合
  • webcamxp 5の場合
  • ホストのIPアドレス、ポート番号の求め方
    • LAN内の場合
      • IPアドレス サーバープログラムを実行しているPCのLAN上でのIPアドレスを取得します。
      • ポート番号 サーバープログラムによって、デフォルトのポート番号は異なります。サーバープログラムのドキュメントを参照してください。
    • インターネット上のサーバーの場合
      • IPアドレス、ポート番号 ネットワークの知識がなければなかなか難しいことですが、mjpegサーバーとなるPCが、グローバルIP経由でアクセスできる状況を作成してください。 上記サーバーにアクセスできるグローバルIPと、サーバープログラムが動作しているポート番号を利用します。

☠ データ通信料金に関するご注意 ☠

本Assetでは、MJPGストリーミング時だけでなく、大容量ファイルが置かれたURLを接続先に指定したケースなど、大量のデータ転送を発生させる可能性があり、特に従量課金制のネットワークをご利用の場合、課金が高額となる恐れがありますのでご注意ください。

今後の修正点

  • ターゲットマテリアルを変更できる機能は早々に実装するつもりです。

悩み

Unityで自前のスレッド利用時、まともにプロファイリングできないためにボトルネックがよくわからない、というのが悩みです。Unityのプロファイラは自前ワーカースレッドの負荷を別のスレッドにつけかえて表示してしまう印象があり、あまり役にたたない気がしています。

最後に

是非使ってみてください!