2020年、明けてましたおめでとうございます。
今年は変化の多い年になる予感しかしないです。どうぞよろしくお願い致します。


この記事は「WordCamp Osaka 2019 ひとつき遅れのアドベントカレンダー」の第5日目の記事です。

さてWordCamp Osaka 2019が終わり、早いもので1ヶ月が経とうとしています。
昨年(2018年)のWordCamp Osakaでは実行委員長を務めた僕ですが、今回(2019年)は動画・撮影チームの(名ばかりの)リーダーとして実行委員参加しておりました。

例年であれば、記録撮影や当日会場で流す動画等で終わるこのチームですが、今回はタイトルにもなっております「リアルタイム配信」にチャレンジしました
そのリアルタイム配信の裏側について、ここでは書き綴りたいと思います。

なお本記事は「チーム/コード編」ですので、機材については軽くしか触れません。
機材関連は別の方(シマさん)がブログを書くそうなのでそちらをご覧ください。

では少々長いですがお付き合いくださいませ。

メインホールのセッションのリアルタイム配信をしていました

改めまして、WordCamp Osaka 2019の当日に、メインホールのセッションをYouTube Liveでリアルタイム配信をしていたのをご存知でしたでしょうか?

こちらでアーカイブの埋め込みをしておりますので、8時間程度のお時間がとれるかたは、ぜひご覧ください。

配信はオープニングから最後のライトニングトークまでしていました。
なお、お昼の時間帯のライトニングトークや閉会の挨拶等は配信しておりません。ご了承ください。

実に8時間程度の長丁場で、当日はほぼメインホール袖の配信ブースにこもっていました。
裏方とはそういうものです。

告知について

今回、リアルタイム配信の告知は当日まで行いませんでした。
これには以下のような理由がります。

  • 初見のチャレンジであるため失敗したときのリスクを考えた結果
  • 大々的に告知をしてしまうと当日会場に来る人が減るのではないかという恐れ

要するに日和ったワケです。

結果として配信したことによる評価自体は高かったように思うので、次回のWordCampで配信することになればちゃんと告知しようと思います。
1週間くらい前に。

配信当日まで何をしていたのか

今回の配信を行うまでにはいくつかのプロセスががあったのですが、実際にやったり決めたりしたことを簡単にまとめてみました。

  • 配信をどのサービスを使うかやどのアプリケーションを使ってやるかを決める
  • 配線図を作る
  • どの機材を使ったらいいかの仮説を立てる
  • 下見でラインや端子がどこから生えているか、ケーブルや電源をどの程度伸ばさなければいけないか等の仮説込みの検証をする
  • 知見を得るためにその手の人に聞く
  • 簡易的な配信テストをする
  • 配線の簡略化を考える
  • 配信に必要な素材を作る
  • 配信テストを繰り返す

不思議なことに、最初は意図していなかったですが「仮説を立てる→試す→問題点を洗い出す→改善策を考える」というまるでPDCAサイクルをまわすような感じで進めていました。

配信における、サービス・アプリケーション・配線

リアルタイム配信で実際に使ったサービスはYouTube Live上で、ゲーム実況系YouTuber御用達のOBSというアプリケーションを使って配信しました。

実際の配線

最終的には以下のような配線となり、セッションスライドとスピーカーのバストアップ映像を同時に映像に乗せ、セッションは日英同時翻訳をしていただいていたブレインウッズさんのブースから音声を日英2つともいただいた上でミキサーで日本語音声のみを乗せるオペレーションをしました。

リアルタイム配線のイメージ

詳しい機材関連についてはシマさんのブログ記事をご覧ください。

また、セッションの間はOBSのシーンの切り替え機能で、Keynoteで作成したスポンサーロゴまわしの映像(Keynoteからアニメーション込みで映像に出力したもの)を映すようにしていました。
Keynoteアニメーション職人がんばりました。

ロゴまわしについては今回解説しませんが、要望がありましたら別途解説しますので、SNS等でコメントやDMをください。

OBSによる配信画面

先程の配線に基づくOBSの配信画面のイメージは次の画像のとおりです。

配信のレイヤーイメージ

OBSのソースを複数重ねて配信に乗せています。

  • 音声入力キャプチャ(登壇者音声/翻訳音声)
  • 映像キャプチャデバイス1(スライドビュー)
  • 映像キャプチャデバイス2(登壇者ビュー)
  • ブラウザ(HTML背景)

2つ映像を使用すると、先程の画像を見てもわかるように、クロップしない限りは、どうしても画面に余白ができてしまいます。

通常であれば画像を背景に配置すればそれっぽく見えて良いのですが、今回はカンファレンスを垂れ流ししているため、複数登壇者の情報を見せたいと思っていました。
複数の情報とは、セッション人数分のセッション情報、のことです。

まず最初に考えたのは「画像を作成してOBSのシーンを複数作り、各シーンに配置、該当のセッションの時間になったら手動でシーン切り替えをする」ですが、これはとても非効率で、常にオペレーションに気を張らないといけません。

僕たちは腐ってもディベロッパー。自動化するに越したことはない。
…ということで、PHPかJavaScriptを使用して自動で切り替えるようにすれば、楽してズルしていただきかしら♪です。

配信用HTML背景を作る

選ばれたのはVue.jsでした。

ローカルで使用するものなのでPHPで組んで $ php -S localhost:3000 してもいいですが、なんとなく使いたかっただけ。

なお開催1週間前に突貫で作成したので粗だらけなのですが、それはそのうち開発してアップデートする予定です。
現状は下記リポジトリでソースを観覧することができます(後日自分のリポジトリにPushしたものを改めて公開します)。

上記リポジトリのソースでは、JSONは埋め込んでるわ、分岐は力技だわで見るに耐えないものなのですが、基本的にやりたかったことは「JSONを利用して登壇者情報の切り替え時間を制御すること」です。

基本構成

Vue.jsはほぼデフォルト状態の設定で、必要なもののみコンポーネント化しています。

基本はローカルで使うものなのでSEOなんて気にしなくてもいいですし、SSR(サーバサイドレンダリング)する必要もありません。

Vue.js コンポーネント構成図

上記画像にある通り、コンポーネント化したセクションは EventInfo.vue と SessionInfo.vue です。

実験的にmoment.jsも組み込みましたが、結果として使うことはありませんでした。

EventInfo.vue

このコンポーネントではTwitterのハッシュタグ要素を変更することができるようにしています。
他のカンファレンスで使用する際にはその他の要素も自由に配置すると良いと思います。

今回は画像を枠外にはみ出させたかったので、Index.vueの背景としてイベント画像を配置しました。

Session.vue

このコンポーネントではセッション・登壇者情報を配置できるようにしています。

  • セッションタイトル
  • 登壇者名
  • 登壇者アイコン

今回は最終的にこの3つを表示することにしました。
当初は「セッションの開始時間と終了時間」「セッションの概要」も表示しようとしていたのですが、OBSでプレビューしたときに文字が読めないなということになったのでやめました。

ここではJSONに含まれる以下の情報をもとに条件分岐をしてデータバインディングしています。

export default {
  name: 'SessionInfo',
  data () {
    return {
      now: new Date(),
      speakerName: null,
      speakerIcon: null,
      sessionTitle: null,
      session: {
        sessionXX: { //セッションの区分名
          startTime: '', //開始時間
          endTime: '', //終了時間
          name: '', //登壇者名,
          title: '', //セッションタイトル,
          description: '', //セッション概要(今回は使用せず)
          gravatarMD5Hash: '', //Gravatarのハッシュ値
        }
      }
    }
  }
}

mountedで現在時刻が開始時間と終了時間の間であれば情報を取得するように時刻をフォーマットして条件分岐を組みます。

mounted: function () {
  var toDoubleDigits = function(num) {
    num += "";
    if (num.length === 1) {
    num = "0" + num;
    }
    return num;
  };
  var hh = toDoubleDigits(this.now.getHours());
  var mi = toDoubleDigits(this.now.getMinutes());
  var se = toDoubleDigits(this.now.getMinutes());
  const nowTime = hh + ':' + mi + ':' + se;
  
  if ( nowTime >= this.session.sessionXX.startTime && nowTime < this.session.sessionXX.endTime ) {
    const sessionData = this.session.sessionXX;
    this.speakerName = 'Speaker : ' + sessionData.name;
    this.speakerIcon = 'https://secure.gravatar.com/avatar/' + sessionData.gravatarMD5Hash + '?s=400&d=mm&r=g';
    this.sessionTitle = sessionData.title;
    this.sessionStart = sessionData.startTime;
    this.sessionEnd = sessionData.endTime;
  }
}

その後、各セッションの情報をバインディングして終了。
これで、その時間にアクセスすれば自動的に情報が表示されるHTMLの出来上がりです。

終了時間が長引く場合があるので、休憩時間の半分くらいを目安に終了時間を設定すると良いでしょう。

また、前のセッションが遅れてそのまま時刻がずれる場合はJSONの開始時刻・終了時刻を編集して再読み込みします。

ローカルで動かしている場合は自動更新されますが、OBSシーンの切り替えでもブラウザリフレッシュされるので、OBS側で再設定する必要はありません。

先述したとおりJSONをvueファイルに埋め込み、分岐も力技でしているため、後日API経由で取得してループできるように改修予定です。

Gravatarもメールアドレスから自動的に取得できるようになると便利なので、これも改修予定。

OBS用にフォントサイズの調整

$ npm run serve することでブラウザ上で確認できますが、OBSでの読み込みを想定しているため、実際のブラウザで観覧するとフォントの大きさがすごいことになります。

3840px × 2160pxのブラウザサイズで観覧した場合

OBSでは指定したフォントサイズがブラウザプレビューでの想定より小さくなるので、開発時にはOBSを立ち上げて実際にはめ込みをしながら、フォントサイズの調整をしていくのをおすすめします。

今後の開発タスク

  • JSONを切り離し、axiosでAPIを読み込むようにする
  • アイコンはGravatarの場合メールアドレスから自動で変換するようにする
  • 条件分岐をループさせて汎用的に使えるようにする
  • 自動リフレッシュ

今後も使用するのですが、今のところ直近で使うことがないのでゆっくり開発します。

緊急テスト配信の実施

チームメンバーで各々テストはしたいたのですが、実際に放送をして検証したかったため、2019年11月16日のKansai WordPress Meetup Osakaにて限定公開の配信テストを行いました。

Kansai WordPress Meetup Osaka #4 での配信中の様子(手前)

これにより実際のオペレーションのテストができ、問題点も見えてきました。

配信当日

本来であれば会場で配線のテストができれば良かったのですが、会場都合により実際の現場でテストできる時間が全くなかったため、実際にできなかったときの保険を加味しながら当日ぶっつけ本番で配線して配信する運びとなりました。

結果は埋め込み動画のとおりですが、小さなトラブルはありました。

  • Webカメラのコードがギリギリで通りにくかったり
  • 設置した際の三脚がちょっと邪魔だなと思ったり
  • HDMIのスイッチャーが死んでたり
  • JSで書いた条件分岐間違ってセッション中に手動で修正したり

どれも大したトラブルではありませんでしたが、現場ではヒヤヒヤしていました。
ともあれ、無事に配信終わってよかったね。

配信のチームについて

チーム内での役割

配信のチームメンバーと役割はだいたい以下の通りです(通名で記載しています)。

  • GOUTEN – チームリーダー/OBS用素材作成
  • シマキョウスケ – 配信オペレーション/機材調達
  • Toro_Unit – 音響オペレーション/機材調達
  • がっきー – 配線図の作成

関わっていただいたメンバーには圧倒的感謝が止まりません。
配信チームで記念撮影でもしておけばよかった。

また、外部で相談に乗っていただいたWordCamp Tokyo 2019の副実行委員長も担われた戸田さんにも感謝いたします。
光ファイバーHDMIとか話聞かないと知らなかった。

自由なコミュニケーション

チームリーダーとして特にこれと言って特別なことをしたわけではないのですが、チームをまわすにあたってコミュニケーションの大事さを再認識しました。

メンバーとは主にSlackとZoomを通じてオンラインで、かなり自由に、ストレスのないコミュニケーションをとっていました。
特にZoomでの会議は(悪い意味ではなく)酷かったです。

この自由っぷりは2020年1月18日に行われる Kansai WordPress Meetup Kyoto のLTのネタにする予定なのでここでは伏せておきますね。
後日LTスライドのリンクでも貼っておきます。

コミュニケーションしている中で、良かったと思った点は以下の2点。

  • 何でも自由に言い合う土壌と信頼関係
  • 自主的に行動を起こすモチベーション

今回はほぼ互いに知っている人でチーム構成をしたのでコミュニケーションは取りやすかったのですし、メンバーがやれることも把握していましたし、各々が勝手に必要なことに取り組んでいたおかげで、とてもスムーズに進行しました。

これが最初からはじめましての人ばかりだとどうなっていたかはわかりません。これは2019年の反省をしている中でも上がった問題です。

次回のチームづくりでは、はじめましてののメンバーと初速でどこまで信頼を勝ち取るか、そしてモチベーションを保つような会話ができるかがポイントになるのではないかと思います。

チームの課題

紛うことなく「お金」。

今回、ほぼ持ち出しの配信設備投入だったので、次やるなら予算がほしい。マジで。

お金があれば何でもできる!

配信のそのおわりに

そもそものきっかけは、2018年のWordCamp Osakaで反省点がたくさんあり、そのひとつが「WordPress.tvにアップする記録映像の質が悪い」というものだったことです。
今回のチームメンバーと「絶対に来年(2019年)は映像頑張る」ということを言い合っていました。

そして2019年の実行委員募集が始まり、早速応募、応募フォームのチームリストにもなかった「映像チーム」を希望する暴挙(複数人での囲い込み)を行い、なんやかんやあって無事映像チームを立ち上げる運びとなりました。

当初は「記録映像のクオリティを上げる」ことが目的だったはずなのですが、会議の1回目が始まる前から何故か「配信しよーぜ!」の流れになっていました。自分でもよく覚えていません。

もし次の関西圏でのWordCampで配信があるなら、ぜひ全セッション配信がしたいです。
というかやる。


「ブログを書くまでがWordCamp

巷ではこう言われいるようでして、参加したWordCampのブログを書かないとその人自身のWordCampは終わってはいけないような風潮になっております(個人差があります)。

住んでる地域だけで思い返してみれば、初めて参加したWordCamp Kobe 2011や、実行委員初体験のWordCamp Osaka 2012や、登壇したWordCamp Kobe 2013は別のブログで書いた覚えがありますが、実行委員復帰後のWordCamp Kansai 2016や副実行委員長として関わったWordCamp Kyoto 2017は特に記事を書いてないし、実行委員長として指揮をとったWordCamp Osaka 2018もサイトには開催のお礼として記事は書いたものの、個人ブログとしては何も記事を書いていないことに気づきました。

そんなこんなで3年越しに、ようやく僕のWordCampは終わりを迎えれる、ということにしましょう。
ありがとうございました。

特にオチはないです。