Junpei Qawasaki

博報堂アイ・スタジオという会社でテクノロジーをベースに新規事業とかインタラクティブなものとかを色々とやっております

GoPro HERO7 BlackのLiveStreamingを試す

GoPro HERO7 Blackを買いました。
f:id:jkawasaki:20180930184707j:plain

特にカメラ好きな訳でも無く、これまでGoPro自体はそこまで触ってなかったのだけど、HERO7で追加された機能は開発で応用したり企画でも使えるなーと思っての導入。新機能の中で琴線に触れた2点が「HyperSmooth」と「LiveStreaming」。で、今回はLiveStreamingを試してみたという話。

大前提としてGoProは購入してもマニュアルついてる訳では無くて、接続とかはアプリに従ってれば良い感じに出来るという思想です。とはいえ、個人的にもストリーミングの設定でハマったので、上手くいかない場合はこちらにあるマニュアルを見ると色々書いてあるので、ハマった人はぜひ。

さて、お仕事で使う前提で考えてるので、まずはGoProの映像がどうやってネットワークに出て行くかを知らないといけません。
結論から言うとスマホのAppで連携して外部に出ていきます。
接続を進めて行くと分かるんですが、BluetoothWiFiの共有で上手い感じにネットに出ていきます。Facebookの連携もスマホからやります。
ざっくり言うと以下のような感じですね。

f:id:jkawasaki:20180930180844p:plain

ここでポイントなのが

スマホ側から接続したいAPを指定出来る
・パーソナルホットスポットスマホの回線を使う事も可能

と、言う事です。
前者は高速なWiFiがある環境の時には使えるけど、GoProでLive配信したい時って屋外の環境が多いと思うので、その場合は後者を使う感じになります。
ちなみに、最初やろうとした時は何回やっても「カメラとの接続が切れました」って出て上手くいかずカメラの初期化&アプリ再設定したら治りました。おそらくなんだけど最初にBluetooth接続→WiFi接続をやるときにカメラの名前があったりとか、GoProアカウントとFacebookアカウントの連携が上手く言ってなかったので、同様の状況な人はやり直すとすんなり行くかと思います。

f:id:jkawasaki:20180930181709p:plainf:id:jkawasaki:20180930181706p:plainf:id:jkawasaki:20180930181722p:plainf:id:jkawasaki:20180930181717p:plainf:id:jkawasaki:20180930181714p:plain

だいたいこんな感じで、スマホの回線を使ってる場合はテザリングみたいな表示になります。この辺りのWiFiでカメラと接続、回線はキャリア回線を使うってシーンが例えばSONYのCameraRemoteAPIだと手動でIP指定したりとか、既存のWiFiが使えないとかの制約があるのに対してGoProはその辺りストレスなく使えるのでホスピタリティが高いなぁと思った次第です。

ちなみにFBアカウントは同じスマホ内に入れたFBアプリのアカウントに紐付くので、専用の配信アカウントとかでやりたい場合はFB側で入り直して連携すればそれに紐づきます。ライブストリーミングの設定自体が上手くいかん、と言う方は詳細な設定方法のURLが製品マニュアルに載ってるのですが、そこから直リンク叩くと404になったので、一応、こちらからライブストリーミングの設定方法に飛べます。ただ、英語しかないのと、あんまり詳しいことは書いてないです。

さて、Live配信の方ですが、HERO7自体がストリーミング出来ると言うのがウリで贅沢はいえないのですがクオリティは720p(または480p)になります。そしてネットワーク環境によるけど、ラグはそこそこあるので「超高解像度でリアルタイム配信」とか言ってしまうとそれは嘘になるのでご注意を。超クオリティのLive配信をしたい場合にはGoProじゃなくて、既存の高解像度配信の仕組みを使うのが良いです。

とはいえ、良いのがこのLive配信でも「Hyper Smooth」は生きるところ。ジンバルとか用意しなくともブレの無い画像でストリーミング配信が出来ます。逆に言うと定点カメラだとそんなに意味ないって感じすね。HERO7では夜景でのラプス撮影とかの機能も追加されてますが、それはストーミングでは使えません。あくまで目に見えてるのと同じような風景になる感じです。また配信範囲の設定はストリーミング前の設定画面で出来ますが、最初は「自分のみ」にしておいて配信が出来てからFacebook側で公開範囲を変えるのが良いかなと思います。でも事前に告知したい時とかは「公開」でやっておいて一時停止にするのが良いのかも。

撮影した画像とか、ハード仕様の詳細なんかは以下、「強火で進め」さんがまとめられておりますので割愛。
d.hatena.ne.jp
d.hatena.ne.jp

そんなこんなでスマホとGoProがあれば細々とした作り込みが不要で、手ブレ少ないLiveStreamが出来ると言うのは強力だと思っていて、今後、色々と活用が広がる気がしてます。
ただ、個人的には企画で使う際に「現場での設定のめんどさ」みたいなのは加味した方が良いかなと思いました。手放しで誰でも出来るものでは無いので、初期設定はしておいて、あとは使う度「こう使ってね」と言うマニュアルを簡単に作ればイベントなどでの実運用にも耐えれるな、と。あと、気になるバッテリーは配信せずに1時間くらいいじってたらバッテリー半分くらいまで減ったのと、自動で配信が切れる時間が15分だか30分だかであるので「配信前まで充電」して「15分配信したらバッテリー交換」みたいな使い方をある程度決めれば良いかなと思いました。長尺で回しっぱなし配信したい、みたいな時は有線で繋ぎながらで出来るけど、スマホ側かGoPro側がスリープに入ると切れるので、その辺りはそういう使い方したい場合に検証した方が良いかなと思いました。

今回はLiveStreamをするまでの流れの把握と、その実態を知るのがメインだったのでこの辺で。
次はGoPro APIを叩いてみるみたいなことをやってみたいなと思います。

【機械学習&IoT】星空と記念撮影する自動撮影ブースを作りました

f:id:jkawasaki:20180727115801j:plain

2018年3月のSXSWにも出展した自動撮影ソリューション『capture』をバージョンアップ。
captureは元々、特定物体検出のライブラリ「YOLO」をiPhone上で動かして、条件がそろったら自動撮影してくれるアプリで、ニセコでスキーの自動撮影を実験的にやってました。それについては以下のリリースをご覧くださいませ。

www.i-studio.co.jp

今回は"特別な瞬間を自動で撮影"というコンセプトはそのままに、アウトドア環境で星空と一緒に撮影出来るカメラを作るという企画で、撮影のためのグランピングブースから制作し、ブース内のLED照明とセンサと高感度カメラ(SONY α7)を同時制御してます。

f:id:jkawasaki:20180727115617p:plain

captureはいわゆるiOSアプリなので、星空を撮影するにはいくつかハードルがあります。ノイズ、シャッタースピードISO感度、絞りなど。※ちなみにカメラには詳しくないです

まず最初はiOS側でAV Foundationで設定をいじってどこまで撮影出来るか確認。→ノイズ多い。
確かに星は映るけど、ノイズ多すぎて駄目。

根本の原因であるノイズなのでハード的な限界はある為、考えたのがSONY CameraRemote API
簡単に言うとSONYのカメラ製品をプログラムから制御出来るヤツ。最終的にブースではiPhoneとカメラを設置にしなきゃなので大きさを考慮して"QX100"と言うものを中古で購入して試してみたところ、ノイズは大幅に低減。

f:id:jkawasaki:20180727121044p:plain

しかしながらこのQX100はやりたいことに大して大きな問題ありまして、リファレンス上は"Shutter Speed"と"ISO SpeedRate"のAPIでSet出来ると書いてあるけど実際にはエラーが返るという。

Camera RemoteのらSDK自体はもうあまり更新されてないのだけど、機体のファームウェアバージョンとかSDK最新じゃないと不具合起きるとのことで403 ForbiddenのままでQXは役割を終えました。

画質の最大化やバッテリー容量の観点からQXだと心許ないので、「α7」に変更

レンズはSEL28F20はフルサイズの28mm(カメラ詳しくないのであんまり分からない)。
カメラ決まったのでこれをiPhoneと一緒に設置出来るための筐体を制作。コストと運用しやすさを加味してシンプル&化粧板設計。
f:id:jkawasaki:20180727111711p:plain
f:id:jkawasaki:20180727111722p:plain

そして星が映っても人の顔がちゃんと映らないと意味が無く、大自然の中にカメラだけ置いてもそれが良い写真になるかは体験者に依存してしまうので、グランピングブースを制作して、LED照明をカメラと連動させる事に。
最終的なブース全体像と、スマホカメラとの差分はこんな感じです。
f:id:jkawasaki:20180727121744j:plain

LEDは撮影前、撮影中、待機中で、それぞれ個別に光量が変化。照明制御はRaspberryPiとiPhoneをBLE連携、LEDはI2C制御基盤を4枚。iPhone側と信号をラリーする形で自動撮影を進めております。

そんな感じで多分、星空と記念撮影に特化したブースは他であんまり無い物になったかと思います。
このブースは「ほしのしずくスタジオ」と言う名前で2018年7月28日より岩手県の雫石プリンスホテルに常設されますので、ぜひ!

★ Staff List
Art Director: Yosuke Sasagaki
iOS Engineer: Yuta Hirakawa, Takafumi Oyama
Device Engineer: Yasuyuki Ogino
3D WebViewer: Hiroshi Koi
Front and Backend Engineer: Kota Toda
Technical Director(Web):Yoshimasa Yokoyama
Product Design:Takumi Maezawa , Yosuke Sasagaki
Designer: Yosuke Sasagaki
PR : Miki Senoo , Takafumi Kato
Producer and Technical Director : Junpei Qawasaki

■ニュース記事は以下です
news.ibc.co.jp
news.biglobe.ne.jp

【Unity】vj-kitで音楽とオブジェクトを連動させてビジュアライザを作る

音楽と連動するオブジェクトを作りたいな、と思いました。
で、調べたらvj-kitなるものがあるじゃないですか。

GitHub
https://github.com/unity3d-jp/fuze-vj-kit/

使い方は説明しすぎないざっくりしたREAD MEもついてるのでそちらと、他にも紹介しているページあるのでそれをご覧下さい。

■参考
fuZe VJKitの使い方 | Design Ambience Blog

で、前回のエントリで書いた地球と宇宙のサンプルにそのまま音を反映させていきます。
f:id:jkawasaki:20140301052418p:plain


①音を鳴らす準備
vj-kitのサンプルのHierarchyに[AudioPlayer]と[VJManager_HighMidLow]ってのがあるのでその2つをコピって自分のHierarchyにぶち込みます。
f:id:jkawasaki:20140301171744p:plain

②音を選択する
AudioPlayerを選択してAudioSourceに音を入れます。
今回はyoutubeにも上げたいのでたかがブログで権利が云々言われたくないのでYoutube Audio Libraryからフリーの音を広いました。

SphereとPlaneにコンポーネントを追加する
[VJMaterial Propety Modifer2]のコンポーネントを追加します。Modiferは音に合わせて常に変化するコンポーネント。ビジュアライザならこれがおすすめです。
地球の方はHighの音に合わせて色が変わるように[VJMaterial Propety Modifer2]のHighを、Planeの円はBassに合わせて大きさが変わるように調整。
f:id:jkawasaki:20140301172347p:plain

これだけやって実行すると音に合わせて大きさと色が変わるようになります。
デフォルト設定でも「それなり」な感じになりますが、結構反応しちゃうので今回はMid全切り(いわゆるドンシャリ)に設定を変えたりしてます。

実行した結果はこんな感じ。

vj-kitとても使い易いのですがデメリットは親切がゆえにファイルが重過ぎる事ですね。
4月に原宿で展示がある予定なのでそこまでにちゃんと派手なのを作っていきたいな、と思います。

【Unity】SkyBox(背景)を簡単に360度回転させる方法

ちょっと下記のようなScene背景を自動で動かさなくてはならない事がありました。
f:id:jkawasaki:20140301052418p:plain

Webでちょいちょい情報転がっているだろうと思って調べてみましたが、思ったよりも情報量少なくてしかもほとんどが海外のQA情報交換レベルだったので困った。
で、時間も無かったのでUnity Technologys Japanに技術問い合わせしたらUnityエバンジェリストの高橋さんが1日くらいでサンプル作成して返信くれた。優しぃ。

GitHub
https://github.com/keijiro/GalaxyBox

で、せっかくサンプルまで頂いたので
今回はこれを元に実際に回転させるやり方を説明します。

Scene上で背景を表示させるには「SkyBox」を使います。
最終的に回転させるのには標準Assets使わないのですが基本として覚えて貰った方が話が早いです。Standard Assetsにskyboxesというのがあるのでこれを使います。

Assetsに見当たらなかったら右クリック[import package]でインポートしてください。
f:id:jkawasaki:20140301035314p:plain

で、まずは空を出すのですがこれは簡単で、[Edit]➡[RenderSetting]を選択してInspectorのskyboxの設定を変えるだけです。
f:id:jkawasaki:20140301040649p:plainf:id:jkawasaki:20140301040700p:plain
さっきのSkyboxesをインポートしておけば選択画面で標準搭載のSunny1が選べるのでまずはそれを選択します。
※Skybox適用前
f:id:jkawasaki:20140301040729p:plain
※適用後
f:id:jkawasaki:20140301040756p:plain
背景が表示されました。これだけでも充分いきふん(雰囲気)でます。これがskyboxの力です。

で、回転させるとなると少し手順が変わります。

①必要なファイルをプロジェクトに格納
上記GitHubのコードから下記3点をAssetsに入れます。
・GalaxyBox.shader
・GalaxyBoxUpdater.cs
・RandomRotation.cs
shaderはshaderフォルダに、他2つはScriptに格納するとわかり易いです。

②背景imageの準備
背景にしたい画像をAssetsに放り込んでダブルクリックするとimageSettingが開かれます。
ここでは2048*2048の画像を使っています。まずは図のようにsettingを変更してみてください。
f:id:jkawasaki:20140301051940p:plain
変更すると画像アイコンがボックス型に変わります。
各種設定は色々意味があるのですが、今回に関してはこれがわかり易かっただけなので適宜変えてもらえればと。

②Materialにシェーダーを追加する
新規にマテリアルを作成して、そこに②の画像を適用します。そして①で追加した回転出来るシェーダに変えてあげます。[Shadet]->[Custom]からGalaxyBoxを選択してください。
f:id:jkawasaki:20140301043643p:plain
ちなみに今回紹介する方法、現状ではcubemap形式じゃないと背景は適用出来ないです。
skyboxである以上、boxのそれぞれの面にテクスチャ指定とかもやり方あると思いますが。

コンポーネントの追加
で、最後に適用したいオブジェクトにコンポーネントを追加してあげます。
今回は真ん中の玉(sphere)に2つのスクリプトを適用します。Updater.csの方にはまたマテリアル適用してあげないといけないのでご注意ください。

で動かすとこんな感じになります。
わかり易くplaneとsphereにはテクスチャを貼ってます。

画面全体が動く感じになるのでダイナミックさが増して良い感じ。
宇宙以外のリアルな使い道はいまの所思い浮かばないのですが。
いまはスクリプト上、ランダムで360度に動いていますが、ちょっと変えてあげればスピードも回転方向も自分でカスタム出来るかと。

こんな感じで簡単に回転出来ました。Unity Japanサポートのお陰ですが。
必要な方は是非お試しください。<告知>
UniteJapan2014にて「フィジカルコンピューティング分野におけるUnityの可能性」というタイトルで講演させてもらうことになりました。
http://japan.unity3d.com/unite/unite2014/schedule

なんでこれが必要だったかも含めたかも話す予定です。ぜひご覧ください。

【EYE TRIBE】視線でのマウス操作をスムーズにしてみた

なんとEYETRIBEを借りました。
起動にはSDKが必要だったりするのですがそのあたりが知りたい方は貸主の1Fさんブログをご覧下さい。

EYETRIBEを起動してみた!EYETRIBEを起動してみた! | HACKist

開発環境はVisualStudioなので別に未知の領域ではないのですが正直C#はそんなに得意じゃないです。
なので無茶はしないでとりあえず講演用にマウス操作を視線で行いたいな、と。

もともとのソースはこちら
TheEyeTribe - The Eye Tribeで視線でマウスカーソル動かす(C#) - Qiita
から拝借しました。参照設定とかも書かれているのですごく参考になります。

ただこの参考ソースはセンサーの値がそのままなので動きがピーキー過ぎて使いこなせません。
そこで、センサーからのとった値の移動平均値計算処理いれました。

現在の値 = 0.9 * ひとつ前の値 + 0.1 * センサの値

所詮は暫定対処のため実用化、というほどのクオリティには届いていませんが「視線操作出来てる体験」は出来るくらいになりました。でもちょっと丸められすぎなのかも。

加重平均値という話も出たけれど多分、手間をかけてもそこまで改善する気がしないので今回はやめておきます。

合わせて右目閉じたらクリックって処理にしてみたのですが、こちらもコンソールログみると拾い過ぎなので5回に1回の割合で拾ってます。

ソース全体はこんな感じ。

using System;
using TETCSharpClient;
using TETCSharpClient.Data;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

public class EyeCursorControl : IGazeListener
{
    public double before_screenX = 0; //一つ前の座標(平均値用)
    public double before_screenY = 0;
    public double lowpassX = 0;
    public double lowpassY = 0; 

    public int CursorX = 0; //最終的にカーソル位置になる座標
    public int CursorY = 0;
    public int eyeclose_cnt = 0; //右目閉じカウンタ

    public bool Enabled { get; set; }
    public bool Smooth { get; set; }
    public Screen ActiveScreen { get; set; }

    public EyeCursorControl() : this(Screen.PrimaryScreen, false, false) { }

    public EyeCursorControl(Screen screen, bool enabled, bool smooth)
    {
        GazeManager.Instance.AddGazeListener(this);
        ActiveScreen = screen;
        Enabled = enabled;
        Smooth = smooth;
    }

    public void OnGazeUpdate(GazeData gazeData)
    {
        if (!Enabled)
        {
            return;
        }

        // start or stop tracking lost animation
        if ((gazeData.State & GazeData.STATE_TRACKING_GAZE) == 0 &&
           (gazeData.State & GazeData.STATE_TRACKING_PRESENCE) == 0)
        {
            //Console.WriteLine("start or stop tracking lost animation");
            return;
        }

        // tracking coordinates
        var x = ActiveScreen.Bounds.X;
        var y = ActiveScreen.Bounds.Y;
        var gX = Smooth ? gazeData.SmoothedCoordinates.X : gazeData.RawCoordinates.X;
        var gY = Smooth ? gazeData.SmoothedCoordinates.Y : gazeData.RawCoordinates.Y;

        //センサ値
        var sensorX = (int)Math.Round(x + gX, 0);
        var sensorY = (int)Math.Round(y + gY, 0);
        Console.WriteLine(gX + "," + gY);

        if (gazeData.RightEye.SmoothedCoordinates.X == 0 && gazeData.RightEye.SmoothedCoordinates.Y == 0 && eyeclose_cnt > 5)
        {
            Console.WriteLine("right eye close done!");
            eyeclose_cnt = 0;
            NativeMethods.LeftClick();
        }
        else if (gazeData.RightEye.SmoothedCoordinates.X == 0 && gazeData.RightEye.SmoothedCoordinates.Y == 0 && eyeclose_cnt < 5)
        {
            Console.WriteLine("right eye close count");
            eyeclose_cnt++;
        }
        else
        {
            //指数移動平均計算
            lowpassX = 0.9 * before_screenX + 0.1 * sensorX;
            lowpassY = 0.9 * before_screenY + 0.1 * sensorY;

            //カーソル命令のメソッドがintじゃないと落ちるのでcast
            CursorX = (int)lowpassX;
            CursorY = (int)lowpassY;

            //スクリーン座標にマウスポイントを移動
            NativeMethods.SetCursorPos(CursorX, CursorY);

            //ひとつ前の値を保持しとく
            before_screenX = lowpassX;
            before_screenY = lowpassY;
        }
    }

    public class NativeMethods
    {
        [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "SetCursorPos")]
        [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]

        public static extern bool SetCursorPos(int x, int y);

        [DllImport("user32.dll")]

        private static extern void SendInput(int nInputs, ref INPUT pInputs, int cbsize);

        public static void LeftClick()
        {
            const int num = 2;
            INPUT[] inp = new INPUT[num];

            // マウスの左ボタンを押す
            inp[0].type = INPUT_MOUSE;
            inp[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
            inp[0].mi.dx = 0;
            inp[0].mi.dy = 0;

            inp[0].mi.mouseData = 0;
            inp[0].mi.dwExtraInfo = 0;
            inp[0].mi.time = 0;

            // マウスの左ボタンを離す
            inp[1].type = INPUT_MOUSE;
            inp[1].mi.dwFlags = MOUSEEVENTF_LEFTUP;
            inp[1].mi.dx = 0;
            inp[1].mi.dy = 0;
            inp[1].mi.mouseData = 0;
            inp[1].mi.dwExtraInfo = 0;
            inp[1].mi.time = 0;

            SendInput(num, ref inp[0], Marshal.SizeOf(inp[0]));
        }

        private const int INPUT_MOUSE = 0;                  // マウスイベント
        private const int MOUSEEVENTF_MOVE = 0x1;           // マウスを移動する
        private const int MOUSEEVENTF_ABSOLUTE = 0x8000;    // 絶対座標指定
        private const int MOUSEEVENTF_LEFTDOWN = 0x2;       // 左 ボタンを押す
        private const int MOUSEEVENTF_LEFTUP = 0x4;         // 左 ボタンを離す

        [StructLayout(LayoutKind.Explicit)]
        private struct INPUT
        {
            [FieldOffset(0)]
            public int type;
            [FieldOffset(4)]
            public MOUSEINPUT mi;
        };

        // マウスイベント(mouse_eventの引数と同様のデータ)
        [StructLayout(LayoutKind.Sequential)]
        private struct MOUSEINPUT
        {
            public int dx;
            public int dy;
            public int mouseData;
            public int dwFlags;
            public int time;
            public int dwExtraInfo;
        };
    }

    static void Main(string[] args)
    {
        GazeManager.Instance.Activate(GazeManager.ApiVersion.VERSION_1_0, GazeManager.ClientMode.Push);
        if (!GazeManager.Instance.IsConnected)
        {
            Console.WriteLine("EyeTribe Server has not been started");
        }
        else if (GazeManager.Instance.IsCalibrated)
        {
            Console.WriteLine(GazeManager.Instance.LastCalibrationResult);
            Console.WriteLine("Re-Calibrate");
        }
        else
        {
            Console.WriteLine("Start");
        }
        EyeCursorControl cursor = new EyeCursorControl(Screen.PrimaryScreen, true, true);
    }
}

【Unity】Macで作成したものがWindowsでコンパイルエラーになる件

タイトルの通りでハマりました。singletonのクラスのメンバ変数にアクセス出来ないよ、的なエラーが出る。

結果、Mac側とWindowsの改行コード設定が違う、というオチでした。

両方utf-8でcr+lf、bom無しで設定一致していないと駄目です。仮にコンパイル通ってもシンタックスエラーとか出るとかいう事例も見かけました。

今回はこんな感じで解消しましたが、そもそもエディタが違うとか、build設定とか、.NETのバージョンがWindows 8だとデフォルトで4.0だとか疑わしい場所が多くて時間かかったので悔しいすね。




勉強会の集客が突然好調になったのでその理由を考えてみた。

僕は開発者向けのコミュニティ運営を2つばかしやらせてもらっています。

1つは1年半前くらいに作った「Windows 8 Developers」で、Windows上で動くいわゆるストアアプリが主体のコミュニティです。
そのイベント(勉強会)を3/14にやるのですが、今回、過去イベントよりも俄然、集客の「引き」が強いので、その理由の考察をするというのがこのエントリの主旨です。

イベントを開けど集客に難あり

設立当初のイベントは正直集客も思ったように集められんかったのです。
今をときめくJavaScriptでネイティブのアプリ開発が出来るストアアプリにWeb業界の人はさぞ興味深々であろう。などと考え、意気揚々とFacebookグループ立てて第1回カンファレンスを定員90人で開催してみました。

結果、50人の申し込みで実参加者は40人くらいという微妙な感じのコミュニティデビューになり、続けてハッカソンをやってみましたが、こっちはもっと悲惨で10人集めるのが精一杯でした。

人集めりゃ良いって事も無いのですが、やはり「即完」してみたいのが人の性。
とはいえ扱っている内容がメジャーじゃない(言い過ぎ)ので無条件でハネる事はまず無い訳で。

高校生の文化祭ライブじゃないので闇雲に開催して人を誘う、というのも如何なものかと思い、イベントを2回やった後で何か手を考えないと行けないなーと思ったのです。

ハッカソンに付加価値をつけてみる

まず、ハッカソンも「みんなでいっしょに開発しよう」みたいな前時代的な考えでは駄目だと思い、企画ルールとして「ストアアプリ×何か」という風に技術×技術で"お題"を決めました。たとえばこんな感じです。

ハッカソン2回目 「ストアアプリ × enchant.js」
ハッカソン3回目 「ストアアプリ × KINECT

2回目はJavaScript界隈でゲーム向けライブラリで有名なenchant.jsと当時公開されたばかりのSkyDrive APIをターゲットにしました。このタイトルは結構当たって、20名枠に対して25人参加でした。

3回目はまた手法を変えました。そもそもストアアプリと連携出来ないKINECTを無理矢理連携させるチャレンジハッカソンとして定員を5名に絞って超小規模で開催しました。結果、WebSocketでKINECTを繋ぐアプリが出来て、イベント内容に対してコミュニティの活性化が出来たと思います。

他にも某コンテストと連携して「参加賞の景品」を用意したハッカソンも行ってみました。結果としては複数回開催して50人くらい集まったので悪くはなかったのですが景品ではモチベーションは上がらないような気がしました。

なんとなく、先端を取り入れてみる

カンファレンスは会場を抑えたり集客をしたりで準備に手間と時間がかかります。
とはいえ時間を空けすぎるとコミュニティ自体が活性化せず人も離れてってしまいます。なので開催の楽なハッカソンを2回やってカンファレンスを1回やるくらいのペースでイベントを打っていくことにしました。
メンバーが150人を超えたくらいで3回目のカンファレンスを打ってみたところ、やはり4〜50人くらいから集客が伸びず、また次の手を考えきゃいかんなーと思ったので、カンファレンスの時にこんなハッカソンを発表してみました。

f:id:jkawasaki:20140121193703p:plain

ちょうどFirefox OSが発表されて実機が手に入るようになった頃です。「WindowsFIrefox OS」という意外性を持たせて、場所もMozilaJapanさんをお借りしました。結果、このハッカソンはコミュニティ過去最多の40人規模になりました。

この時に発見したのは下記です。

"いかにイベントの第一印象で興味を引き、参加したいと思わせるか"


まぁ、基本と言われれば基本なんですが。


で、そこからは半年くらいコミュニティ寝かせていました。
そろそろイベントを打たないとなーと思い、久々にカンファレンスイベントをやろうと思い、相変わらずの集客の不安を引きずりながら今までのイベントを見つめ直して企画したイベントがこちらです。



f:id:jkawasaki:20140121194407j:plain



すると、

なんということでしょう。

発表から数日で定員の60席が埋まりました。

今回変えた事といえばこんな感じです。

①メインビジュアルをインパクト系(2次元キャラ)にしてみた
②開催日を平日(しかも金曜)の夜2時間だけに絞った
③推したいワードを盛り込んだ(Xamarin,Unity,モーションデバイス)

まず、開発者の属性を考えてFacebook/Twitterとかでシェアしたくなるものをチョイスというのが①の狙いです。結果として今までのイベントでは殆どされなかった「いいね」とツイートをしてもらえ、発信元(Facebookグループ)と関係ない人の参加率が高くなっています。
次にイベント自体をなるべくコンパクトにする為の平日開催ですが、結果的に2時間という制限で気軽に参加しやすくなったのかもしれないです。人と繋がるのが目的な人は「懇親会」に参加してもらえれば良い訳ですし。

で、あとはセッション内容ですがこれはシンプルに「自分がいま技術者として聴きたい事」の3つに絞りました。勿論、ストアアプリに絡めた話をしてもらうのですが、Unity等の「分かり易い」ワードを前面に出しました。

そう、色んな意味でコンテンツが重要って事に今更気付いた訳です。

どんな分野でも変わらないものなのですね。


こんな所がいままでのイベントの振り返りと今回の集客UPの考察です。

たまたま好調なだけかもしれないし、イベントもこれからなのでまだまだ継続して推進出来る手を考える必要はあるのですが、コミュ運営って結構大変なので同じような心境のどなたかの参考にでもなればと思いって書いた次第です。

今回、とりあげてたイベントはまだATNDから参加出来ます。ご興味ある方は是非。
イベントサイトは色々な種類があるのですがATNDはFacebookとの親和性悪いのと、イベントページ編集の操作性が悪いのでそろそろ限界かなーと思ってます。

ちなみに2つやっているコミュニティのもう1つは2013年末に立ち上げた「Unity/OpenCV/WebGLで遊ぶ会」です。Facebookグループでどなたでも参加可能になってますので、お気軽にご参加ください。こっちのコミュニティは名前の通り技術属性強めなので、もうちょっと練ってからイベントやりたいと思ってます。

では。