モロ屋

アキバではたらくWebエンジニア。JavaScript / AWS / Mac

メイキング「Birthday Song for ミク | miku-39.jp」こと技術解説

f:id:Molokheiya:20120903191655p:image:w700


「初音ミク」というキャラクターが登場して5年。彼女の存在は世界中へと広がり、数の多くの人を魅了してきました。

その驚きと感動を盛大に祝ってあげるためのパーティの準備、そんな気持ちでこのミュージックビデオを制作いたしました。


no title


初音ミク生誕5周年おめでとう! ということで「Birthday Song for ミク | miku-39.jp」というサイトを作りました。

せっかくなのでメイキングっぽい技術解説を書いてみたいと思います。


とりあえず miku-39.jp とはなんぞやってことなんですが、

Mitchie M (@)さんが作った「Birthday song for ミク」という曲にあわせて Tatsuro Ogata (@)さんが作ったミュージックビデオにインタラクティブな感じの体感コンテンツを合わせたサイトです。


ミク5周年のお祝いにMitchie Mさんが作った、めちゃ素敵な曲にめちゃスタイリッシュなPVがついて、さらに加速サトウ (@)さんの初公開ミク3Dモデルがめちゃかわいい。

で、インタラクティブな感じのって具体的に何? ってことで以下に

  • 位置情報と連携して、現在地の航空地図がPVの中で使われたり
  • Twitterと連携して、各種アイコンとか投稿した写真なんかがPVの中で使われたり
  • スマートフォンと連携して、パソコンの画面と動きが連動したり、シンボルをパソコンに飛ばしたりできる

f:id:Molokheiya:20120903191654j:image:w360

位置情報とかTwitterと連携するアプリは色々あるんですが、

スマホと連動するミュージックビデオは(たぶん)初なんじゃないかなーと思います。

では大まかに「サーバー」「パソコン」「スマホ」の3つに分けて解説していきますね!



サーバーサイド

基本的に環境としてAmazon Web Service (AWS) を使っています。

使ったのは EC2 & S3 & CloudWatch で、東京リージョンを利用しています。


AWSを選んだ理由は、キャンペーンサイトにありがちな急激な負荷の増加にも柔軟に対応できることや、

今回のように動画を配信しつつ低レイテンシを実現(後述)するのに適しているからです。


f:id:Molokheiya:20120903191656p:image:w360

環境は Cent OS + Apache + MySQL + PHP の標準的なLAMPです。

そして、お気づきの方も多いと思いますが Node.js を使っています。

はい、Socket.IO ですね。

クロスブラウザでリアルタイム通信を実現するための、Node.jsで動くやつです。

これを使って、パソコンとスマホの連携処理をしています。

WebSocketはIEとかIEとかIEとかがまだ対応してないのでショボーン状態。

そこでWebSocketが使えないならFlashのSocket使えばいいじゃない、Flashも使えないならAjaxでLong pollingすれば… それも使えないなら(ry

…とフォールバックしてくれるナイスガイです。安心してリアルタイムアプリが作れるよ、やったねたえちゃん!

f:id:Molokheiya:20120903222222j:image:w640

パソコンとスマホを接続するために、カラーコードを入力という方法をとっています。

これを順番に入力すると、接続されるわけですね。

まずパソコンで miku-39.jp を開くと、ソケットサーバーに接続して認証キーを要求します。

この時に返ってくる認証キーは「111111~666666」の間となっていて、この1~6 をそれぞれボーカロイドカラーに当てはめて表示しています。

そしてスマホで miku-39.jp を開きカラーコードを打ち込むと、コードを数字に変換した認証キーをソケットサーバーに送信します。

それでパソコンで認証待ちをしているキーの中から一致すれば、相互に繋ぐブリッジとなります。

f:id:Molokheiya:20120903191658p:image

つまりパスコード認証なんですが、ただ数字を打ってもらうよりも雰囲気が出て良かったです!

あとはパソコン側のソケットIDと、スマホ側のソケットIDをサーバー側で認証キーを使って相互に送信出来るようにしておきます。

これで準備はオッケー!


Twitter認証はアイコン画像とったり、最近の画像を取得したり、Followingとったり、壁紙つきツイートをpostしたりと、いろいろな部分で使っています。

あと Imagemagick を使って、サーバーで壁紙を合成して生成していますよ。

f:id:Molokheiya:20120903191659j:image:w600 加速ミクやば。。

Imagemagick は突き詰めていくとPhotoshop並の処理が出来たりするので、他にも色々いじってみたいです。

スマートフォン

スマホ連携して再生開始すると、パソコンで再生されてる動画と連動した動画が流れます。

で。すっかり忘れてたんですが、videoタグってインライン再生が出来ないんですよね。

videoタグを使うと、iPhoneならQuickTimeでフルスクリーン表示になってしまうし、そもそも制御出来ない…

そこで巨大なCSS Spriteを作成して、background-position をずらしてコマ送りで動画を表現するというゴリ押しをしています。

f:id:Molokheiya:20120903191700p:image:w640 壮観

CSS Spriteや、background-image を切り替えてコマ送り動画を表現するのは結構あちこちで使っています。

( miku-39.jp を開いた時に、背景のケーキのろうそくがチラチラしてるのとか)


あとこれはパソコン側でも使ってるんですが、いろんな要素をアニメーションさせるのに

jQueryのanimateだとスムーズにならないのでCSS Transitionで描画しています。

ここで直接書いてしまうと、コードがむちゃくちゃな感じになってしまうので、jQuery Transit という素晴らしいプラグインを使います。

Transit - CSS transitions and transformations for jQuery

これを使えばjQueryのAnimateと同じように書いて、Transitionとかが直接書ける。jQuery Transit is god... つまり神プラグイン。


ただIEが全然ダメなので、miku-39.jp ではCSS Transitionに対応していないブラウザの場合はAnimateに切り替えたり、

Transform Y を Top に変えて計算する処理を加えるカスタマイズを加えています。

パソコン

最初にGeolocation API を使って位置情報をとっていて、Google Maps API と連動して現在地の航空写真が出てきます。

f:id:Molokheiya:20120903212940p:image:w640

アイコンが出てくるところも、CSS Spriteでアニメーションさせたパーティクルが飛びます。

動画の再生についてですが、まずウィンドウのリサイズイベントに紐づけて、ビデオが常にウィンドウいっぱいに表示されるようにしています。

そして動画再生中のとき、おおまかに3つのレイヤーが存在しているような概念でロジックを仕込んでいきます。

少しややこしい話になるのですが、ちょっと説明しますと

1. 動画が再生されるレイヤー

2. 動画のサイズに合わせてスケールが変形されるレイヤー

3. 通常のブラウザと同じように等倍で表示されるレイヤー

と、3つのレイヤーがあります。

例えば、動画が1分30秒のときにX: 100px Y: 400px の位置にボックスを配置して動画の上に重ねる演出をしたいとします。

しかしその時ブラウザの左上から100px, 400pxの位置にCSSで配置しても、

もともと1280x720の動画をブラウザサイズに合わせて伸ばしたり位置を変えたりしている為、座標が一致しなくなります。


そのため1280x720の動画のズーム比を取得して、そのズーム比でレイヤー全体のスケールを変形して、動画の座標と実際の座標を一致させています。

ただ、動画中にバースデーメッセージが下から流れるシーンがあるのですが、ああいった文字が流れる部分は拡大縮小させる意味がないので等倍で表示しています。


そういうレイヤーというかDIV要素を用意して、その中に各演出用のDIV要素を作り、動画の再生に合わせて表示・非表示を切り替えて演出を発動させる感じです。


あと、HTML5のVideoタグは非常に残念ながらアルファ(透過情報)を持った動画を再生しても、対応していないので透けてくれません。


f:id:Molokheiya:20120903212938p:image:w360


そこでまず、RGBとアルファを上下に分割した動画を用意してVideoタグで再生するのですが、このVideoタグは非表示にしておきます。

そしてcanvasを使って、VideoタグのRGBとアルファのピクセルを読み込み、canvas上でアルファ情報を合成して書き出す。という処理を全フレームで実行します。


f:id:Molokheiya:20120903212939p:image:w800 ペヤング


あとはTwitter連携されている場合は、投稿されている画像を取得してきて背景に並べて、

その上にcanvasを乗せるとミクさんが歩いている感覚が得られる! ってな感じです。


iframeを下に敷いて、別のWebサイトの上をミクさんが歩いたりもします。



あとは、サビのシンボル飛ばし。


といってもサーバーサイドで説明した通りパソコンとスマホは既に連動しているので、スマホでシンボルを飛ばした瞬間にインターネット経由で通知されます。

座標とシンボルの種類をそのタイミングで受け取って、画面に描画するだけです。


f:id:Molokheiya:20120903212941j:image


シンボルが出るタイミングで中心から波紋が広がるんですが、ここはcanvasを使わずに実装してみました!

jQueryとCSS3のみで実装しています。


canvasを使わない波紋っぽい演出 - jsdo.it - Share JavaScript, HTML5 and CSS


jsdo.itにサンプルコードを載せてみました。クリックすると波紋が出ます。


飛ばされたシンボルはサーバーサイドでデータベースに記録していて、最新の数百件が再生される仕組みになっています。

ちなみにシンボルを飛ばす部分はBroadcastでソケット通信していて、miku-39.jp を開いている全員にリアルタイムで送信しているため、

世界のどこかで同じ時間にシンボルを飛ばしている人がいると、その人の飛ばしたシンボルが同時に表示されます。


あとこれはミクの誕生日に追加した機能なんですが


f:id:Molokheiya:20120903215911j:image


canvasを使ってスマホで一筆書きをすると、そのシンボルがパソコン上に転送されるようにしてみました。


タッチ座標を計算して、lineToでシンボルを描画。タッチ座標の軌跡を配列化して送信して、それをパソコン側で再描画することで実現しています。

ちなみにこれもデータベースに保存されるので、他人の描いたシンボルが表示されるようにもなっています。






miku-39.jp はFlashを使わず、JavaScript + CSS オンリーで製作しました。

その為、モダンブラウザでの再生を推奨しています。


Flashを使うか、HTML5を使うか。

最初はかなり迷いましたが、HTML5を選択した理由は「初音ミクの5周年記念だから」です。


ミクの代表曲である、みくみくにしてあげる♪ には「科学の限界を超えて、私は来たんだよ」というフレーズがあったりします。

音声合成という技術が、曲だけにとどまらずにMikuMikuDance、透過スクリーンライブなど様々なジャンルで共鳴して広がっていきます。


初音ミクには、それがメインストリームになるかどうかに関わらず、

新しいことにチャレンジして未開の領域を切り拓いて行って欲しい。そういう想いを込めてこのインタラクティブ・サイトを製作しました。



もう誕生日は過ぎましたが、9月14日までの期間限定サイトとなっていますので、ぜひご覧になってみて下さい。

そして、スマホを持っている人は電子の世界でも、持ってない人は心の世界で、繋がってお祝いしてあげましょう。




初めて君の 声の音聴いて 世界が変わる Happy Birthday!

また新しい 歴史を歩む エンジェルに「おめでとう」