RubyMusicMixin 2025でVJをしました
4月16日から18日まで愛媛県松山市で開催されたRubyKaigi 2025のアフターイベントとしてpixivさんが主催されたRubyMusicMixin 2025にてVJをしました。
RubyKaigi自体の感想ブログは会社のテックブログでいずれ出ると思いますのでここではRubyMusicMixinの話をしようと思います。
応募
1月に部署異動をし、ECサービスのSREからRailsを書くアプリケーションエンジニアとなったので、「今年のRubyKaigiに行きたいし、Mixinも2年ぶりに出演したい」と思ってました。
そう思っている中、今年もpixivさんがRubyMusicMixinを開催&DJとVJ募集を行っていたので応募をし、無事に選考が通りました。
最近はアーティストさんのテクニカルのサポート周りを多くやっており、VJ自体は久々でVJ筋が衰えかけている所でしたが...
準備
松本で出演した際は荷物の半分がVJ機材で埋まってしまい服や、貰ったノベルティーが入らないという事象があったのと、今回は航空機移動なので手回り品の荷物は極力減らしたいという思いからVJ機材は宅配で事前に送る準備を行っていました。
そんな中、いつも使っているVJソフトVDMXのアップデートで人物切り抜きの機能が実装されているのを荷造りを行っているタイミングで知り、「これは松山で試すしかない」と思いましたが準備時間がなかったのでソフト側の検証や設定全く行わず、現地に付いてからなんとかなるだろ精神でカメラなどの必要な機材一式を追加で箱に詰め込んで愛媛県に送りました。 vdmx.vidvox.net

あとはロゴモーション動画を作ったりの準備を行きの空港ラウンジや前日夜に行うなどしていました ありがとう、How to Make 〇〇 動画。
改めてRubyMusicMixin 2025 ありがとうございました!
— yuchi (@F_YUUCHI) 2025年4月19日
こんな感じのモーション動画を作って流していました🎛️🎥#rubykaigi #rubymusicmixin pic.twitter.com/S1iJ5L0Ucc
演出の方向性
RubyMusicMixinはRubyKaigi参加者のみのイベントであるため、普段クラブに来ている人が少なく、そういった方が多くいる環境で激しい動きや点滅などは控えた落ち着いたVJを行おうと思っていました。
しかし、RubyKaigi会期中に会場廊下で合ったありたそさんに「yuchiくんのVJの時間はガチガチのクラブミュージックかけるDJを集めたので」と言われてしまい、「これは普段クラブでやるVJスタイルは一切崩さずに松山に渋谷を作るぐらいの勢いでVJをやったほうが面白いだろう」という方針転換をして本番に望みました。
リハでは大量の機材たちをなんとか設営をして本番を迎えました。

人物切り抜き機能はリハ時間で準備が終わらかったのでぶっつけ本番かつ、一番オーディエンスが盛り上がっているタイミングで映像を出しましたが、思っていた以上にうまく切り抜かれてたことでVJが終わった後も人々に「カメラのやつすごかった」と褒められが多数発生してニコニコしてました (ただ、CPU使用率は高くて出力のFPSに影響が多少あったので次回以降使うかは要検討)
#rubymusicmixin そしてしれっとやってるVJ業者 @F_YUUCHI のカメラ芸ヤバいな pic.twitter.com/I0IrhM4QIE
— いかるが (@UVB_76) 2025年4月18日
あと DJ してた時は全然気づいてなかったけど @F_YUUCHI さんの VJ が本当に最高だった。ありがてえ・・・ #rubykaigi #rubymusicmixin https://t.co/xgCXOM8e93
— バロメトリカ / sagawa@IVRy (@barometrica) 2025年4月20日
ゆーちくんなにしたの?!!?!!!??? pic.twitter.com/mSYhVHrbUd
— 炬燵(kotatsu) (@sakahukamaki) 2025年4月18日
他に動画を録ってる方が居たらハッシュタグ #rubymusicmixin に流したり自分に送ってもらえるととても嬉しいです、、、!
概略版ですがいつもの図を置いておきます

まとめ
めちゃくちゃ楽しかったです。普段運動全くしないのに総重量20kgぐらいの機材を運んだり、踊りながらVJしたりで2日間筋肉痛が取れませんでした。
次出演するのであれば「Rubyで動くVJ関連のなにかを作ってRubyKaigiでLTをしてから出る」という気持ちになっているのでKaigiEffectで手を動かして見ようと思います。
2024年ふりかえり
今年1年色々イベントをやったり行ったりしたのでその振り返りです。
1月
GMO 渋谷FUTURE 2024
GMO SONIC 2024の前座イベントとして、今年も会社の社食をクラブ仕様に魔改造してSteveAokiを呼ぶイベントが開催。そこでVJをした。
#GMO渋谷FUTURE2024 の第2部でVJやったりしてました
— yuchi / ゆーち (@F_YUUCHI) 2024年1月26日
今年も社食がフェス会場に変貌した最高の一晩でした!!! pic.twitter.com/xGyLxQJnih
アレイスピーカーの数、ちょっとした屋外フェスよりも多いんじゃないかという数だったり、ガチガチにトラス組んで照明とレーザーが吊られたりして今年はかなり狂気度が高かった。


SteveAokiのVJは専属の方が乗り込みでプレイしているのを横で見ていたが、仕込みの速さや演出のこだわりを強く感じられた。プロVJはすごい。
GMO SONIC 2024
GMO 渋谷FUTURE 2024の翌日にはさいたまスーパーアリーナまで行ってGMO SONIC 2024にスタッフ側とかではなく普通の参加者として楽しんだ。
会社名が冠についたフェスイベント、純粋にうれしい

Zedd、ダンスミュージックが好きになった10年近く前からずっと聞いているアーティストの1人だったので、生でパフォーマンス見れてかなり感動した
生ZEDD、本当にすごすぎて爆踊り pic.twitter.com/SVwCXbrs9c
— yuchi / ゆーち (@F_YUUCHI) 2024年1月27日
2月
キーボードマーケット トーキョー
自作キーボードの即売会イベントにコアスタッフとして参加 初開催だったのでかなり準備をしていたものが実際のイベントとして、来場人数が1000人を超えるイベントを開催でき、無事終了できた。

来年も3月22日(土)に規模を倍にして開催するのでぜひお越しください(絶賛準備中です)
3月
さなのばくたん。 -王国からの招待状-
毎年恒例な感じのヤツ
参加は4年目なので毎年恒例な感じになりつつあるイベントだが、毎回テーマが異なった演出でとても楽しい
bakutan.natorisana.com

今年はアフターパーティーとしてクラブイベントが開催されたのもあり、非常に満足度の高いイベントだった。 bakutan.natorisana.com
来年もチケットが無事ご用意されたので今から非常に楽しみ bakutan.natorisana.com
3月
Keysounds!!! #2を開催した
コロナ禍直前の2020年2月に開催したKeysounds!!!を復活させて秋葉原MOGRAで開催した。
自作キーボード × クラブイベントというニッチなイベントでしたが、パイクサイスの方にも協力していただき、持ち込みのLEDテープを用いた演出だったり、LED演出に連動してキーボードのLEDが光るようにするシステムの開発など面白い試みが行えたなと思っている。
オレンジでオレンジ色に光るキーボードとLEDテープ、最高っぽい #Keysounds pic.twitter.com/uVTrsyYyV5
— yuchi / ゆーち (@F_YUUCHI) 2024年3月24日
次回開催も若干考えつつあるが、多忙of多忙という感じでイベント開催するための時間的余裕が無い...
どこかで気合を入れて進めるタイミングを見極め中
4月
サカナクションのライブに行った
以前から「サカナクションのライブの音響はすごい」という噂を聞いて気になっていたが、コロナや活動休止などもありやっと行くことができた。
幕張メッセのホールの外周全部にアレイスピーカーが吊られているので音の遅延みたいなのが感じないし、台数の割にとても聞きやすくていいライブだった

5月
天下一キーボードわいわい会 Vol.6 で配信をやった
機材たくさん持ち込んで配信をした。機材多すぎてしんどすぎたので若干反省。

Pepabo Tech Conference #22 春のSREまつり の開催と配信をやった
社のSREの技術イベントの開催と配信をやった
主催としてバタバタ動きつつ、配信は大変なので分担すべきだった。
会社に自前のラック機材持ち込んでわちゃわちゃ配信やるのは楽しかった

Road to SRE NEXT@福岡 で配信をやった
ペパボの福岡オフィスでRoad to SRE NEXTが開催されたので、協賛として配信を行った
出張なので持っていける機材にも限りがあったのでミニマムでそこそこのクオリティーを出すのが難しかった。
出張あるある:荷物の8割が機材 pic.twitter.com/nOvdElidL5
— yuchi / ゆーち (@F_YUUCHI) 2024年5月23日
ただ、今回の配信で苦手意識のあったOBSと少し和解できた。

6月
The Naya Vol.5 でVJした
配信オンリーDJイベント The NayaでVJをした。 www.pikexi.se
個人宅の納屋の壁面と天井に張り巡らされたLEDテープと巨大な業務用プロジェクターを使った演出を行い、DJプレイを行っている様子を配信するスタイルのイベント
納屋着 pic.twitter.com/P3KXptwnfs
— yuchi / ゆーち (@F_YUUCHI) 2024年6月8日
自前のスイッチャーを持ち込んで面白い演出ができたし、VJもプロジェクションマッピング的なこともできて満足

異常な設営が無事終わり、まもなく配信始まります📡 https://t.co/6PAraglkap pic.twitter.com/xtMaABkGpa
— yuchi / ゆーち (@F_YUUCHI) 2024年6月8日

7月
新しい3Dプリンター買った
ものづくりが捗って最高

8月
SRE NEXT 2024 に登壇した
SREと配信って似ているよねっていう話を20分した
会社の名前背負って外部登壇みたいなのが初だったのでかなり緊張した

9月
名取さな 1st Live「サナトリック・ウェーブ」に行った
最高のイベント オタク棒振りながら喉壊す勢いで叫んでいた
10月
暴力的にカワイイ in お台場 2024 でLanPageさんの映像演出のお手伝いをした
LanPageさんのライブ演出でビデオシンセサイザーを使うことになり、オリジナルのプリセット作成やFOHに送るための映像周り諸々のお手伝いをした
暴カワ自体昔からずっと行っていたイベントだったので、今回パーティーを作る側として携わることができてとても楽しかった。

ビジュアル演出概論 #001 でLTした
前述の暴カワでビデオシンセを使うためのアレコレの話をLTした
いろんな映像演出をやっている方とお話できていいイベントだった
https://vj-kaigi-001.peatix.com/
天下一キーボードわいわい会 Vol.7 で配信をやった
前回の反省を活かして機材少なめで配信した。 失敗したなあと思える箇所もあったが、これぐらいの力の入れ具合で良い気がするなという妥協点みたいなところを見つけられた

NEXTLIGHT FESTIVAL vol.4 でVJした
いわゆるボカクラのイベント自体初めてだったので、声かけてもらった時「VJいけるか...?」と心配になってましたが、かなりクラブ寄りの音だし普通に楽しみながらVJできた
このイベントに間に合わせて自作MIDIコンを作ったりしていたのでその話は以下の記事から
12月
忙しくて特に公開できるものは無く...
IT健保寿司が美味しかったです。

まとめ
振り返ると音楽尽くしの1年でした。ここに書いてない遊びに行ってるクラブイベントも多く、振り返って自分で結構引くレベル。
来年はもっとイベントの演出周りのことやって行きたいと強く感じているので、それに付随する映像制作周りに知識をつけていきたい気持ちです。
自作キーボード関係も出してないLily58 Pro V2のリリースを進めなければという気持ちがあるのでお待ち下さい。
VJプレイ用のMIDIコントローラーを自作する
VJアドベントカレンダー2024 13日目の記事です。
昨日はMEMEMIYAさんの「VJを初めてやるが、ジャンルは何が良いのか?」という問いに対する個人的なおすすめでした。
最近自作のMIDIコントローラー(以下MIDIコン)を試作程度に作ったので、その経緯から基板/ケース設計、実際に現場で使用するに至るまでの記録です。
0から100まで作り方の解説した記事ではないことをご承知おきください。
この記事の前提事項
この記事では簡単な電気回路、基板設計、ファームウェア制作(プログラミング的要素)を含む多少専門性が高い記事となっています。
VJソフトの挙動についてはすべてVDMX上での話となります。
今のMIDIコントローラーに足りないところは何か
※MIDIコンを作る話に興味がある場合はこの章を読み飛ばしてください
私はVJをする際はAKAI APC40 MKIIを使用しています。
市販されているMIDIコントローラーの中でボタンとノブ数が多く、お酒を飲みながらもしっかりと操作ができるフェーダー大きさが電車での持ち運びにギリギリ許容できるサイズの筐体に詰め込まれています。
このコントローラーはAbleton Liveを用いたライブ演奏を行うために主軸を置かれて開発されたものであるため、VJ用として使用(マッピング)する時気になるところが出てきます。
- 筐体右側にあるボタン類の挙動
- 筐体右側にあるボタンの押しにくさ
筐体右側にあるボタン類の挙動

画像右側にあるボタン類の挙動がボタンによってすべて異なります。
14~16,19,23,25,28,32~34のボタンが1回押したらオン、再度押したらオフのトグル扱いをコントローラーのファームウェアレベルで行っています。
18,17,21,22,24,26,30,31のボタンが押してる間はオン、話したらオフの挙動(以下プッシュ型)となります。
これがVJソフトで使用したときにどのような問題になるかの例として、”ストロボ系のエフェクトなどの押している間のみ効果を適用したい処理”で不便となります。
押している間のみ効果を適用させたい処理に対してトグル扱いのスイッチに割り当て(アサイン)を行うと、「1回押してオン→指を離してもオンのまま、再度押してオフ」となり、短時間で連続で押すようなものには使いにくくなります。
筐体右側にあるボタンの押しにくさ
前述している通り、このコントローラーはAbleton Liveを用いたライブ演奏を行うために作られているコントローラーで、VJのような激しいボタンの連打は想定されていません。
スイッチ機構部はタクトスイッチ(CDJのボタンのあの感じ)が採用され、ボタン自体も小さいために指先により力をかける必要があるため連打には向いていません。
(タクタイルスイッチの押下圧は少し調べた限り0.98Nのものが多く、約100g程度の力が必要ということになります。)
右上にあるPLAY,RECORD,SESSIONボタンはサイズが大きく、押しやすいのですが右上という場所とトグル扱いの挙動ということもあり、ボタンを連打したいストロボ系のエフェクトとの相性は良くないです。
そのため、右側のボタンアサインが少なくなり、実質以下画像のような状態となっていました。

自作MIDIコンを作る
作るに至る経緯
自分はLily58シリーズという自作キーボードを以前から設計しており、基板設計やケース設計、マイコンの知識は多少あります。
以前にもMIDIコン自作の構想はありましたが、「酔っ払いながらある程度の力が加わる筐体」「現場で使用中に壊れてはいけない」ということもあり、作るのは避けてきました。
ただ、以前よりもケース設計の知見が溜まったことや、キーボード以外の新たな設計に挑戦してみたいというところから実際に設計を行いました。
MIDIコントローラーを自作すると以下のような利点があります
ブレッドボードでモックを作る
ブレッドボードを用いてファームウェアの挙動などの確認として試作をします。
使用するマイコンとファームウェアはRaspberry Pi Pico(RP2040)とCircuitPythonを使用します。
使い方などに関しては今回は割愛します。
以下のような回路図をブレッドボード上に作成

MIDIデバイスとして認識するコードを書き、Raspberry Pi Picoへ書き込みます。
adafruit_neopixelやusb_midiのライブラリは別途CircuitPythonのライブラリからコピーする必要があるため注意してください。
import board import digitalio import adafruit_neopixel import usb_midi from adafruit_midi import MIDI from adafruit_midi.control_change import ControlChange # LED Pin pixel_pin = board.GP2 #LEDの数 num_pixels = 3 pixels = adafruit_neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.2, auto_write=False) midi = MIDI(midi_out=usb_midi.ports[1], out_channel=0) #スイッチの設定 switch1 = digitalio.DigitalInOut(board.GP10) switch2 = digitalio.DigitalInOut(board.GP11) switch3 = digitalio.DigitalInOut(board.GP12) switch1.switch_to_input(pull=digitalio.Pull.UP) switch2.switch_to_input(pull=digitalio.Pull.UP) switch3.switch_to_input(pull=digitalio.Pull.UP) cc_numbers = [20, 21, 22] #スイッチのステータス toggle_state = [False, False, False] last_switch_state = [True, True, True] def update_leds(): for i in range(num_pixels): if toggle_state[i]: pixels[i] = (50, 50, 50) else: pixels[i] = (0, 0, 0) pixels.show() # 処理部 while True: for i, switch in enumerate([switch1, switch2, switch3]): current_state = switch.value if current_state == False and last_switch_state[i] == True: toggle_state[i] = not toggle_state[i] midi_value = 127 if toggle_state[i] else 0 midi.send(ControlChange(cc_numbers[i], midi_value)) update_leds() last_switch_state[i] = current_state
トグル挙動で無事に動くことが確認できました

基板設計をする
ブレッドボード上のRasPi Picoからタクトスイッチを押すことによりMIDI信号出すことが確認できたので、いよいよ基板設計を行います。
今回の設計思想として以下のようなことを考えていました。
- 試作設計のためサイズは小さめの筐体
- ボタンはある程度押しやすい大きさ
- ポテンショメーター(ノブ)有り
- RP2040かつType-Cコネクタ
- 3Dプリント製ケース
- ある程度の堅牢性がある設計
基板CADはKiCADを使用します。
ブレッドボードで作ったときの延長で部品を増やして回路図を作ります。

部品を並べて配線を引き、基板を設計します
今回実際に使いたいと思っていたVJ現場に間に合わせるためと、家に在庫として持っている部品を使った設計となったため、改めてみると雑加減が目立ちますね...

製造用のデータを書き出して、基板は中国の基板製造業者(JLCPCB)へ発注すれば1週間程度で届きます
ケース設計
基板が到着するまでの1週間でケース設計を行います。
3DCADはFusion360を使用して設計を行います。
KiCADからは3Dモデルの.stepファイルを書き出しができるため、書き出し後にFusion360にインポートをして設計を開始します。

「堅牢性」を意識し、プラスチック製品によくあるリブを入れつつ、今回は試作設計ということもあったので、こだわったデザインはせずに箱型そのままで設計しています。
設計が終わるとこのようなものができました。


APC40 MKⅡの筐体底面にも六角形のリブが入っています(かっこいい)

データが出来上がればケースは3Dプリンターでプリントします。 実際は1回でうまく組み上がることはなく、3回程度設計の調整をしてプリントをし直すということをやっています。 高速造形ができるBambuLab P1Sを使用していますが、2時間でプリントが終わるので試作サイクルの効率がかなり良かったと感じています。 普通の3Dプリンターでは倍の時間かかっていたと思います...。

組み立て
ここが作っていて一番楽しい瞬間です。
3DCADで実寸台で設計していたものが、そのまま手元に出来上がる楽しさのためにモノを作っていると言っても過言ではないですね。

実はこの写真の段階でVJ出演(昼)がある日の午前4時を過ぎていたため、LEDの実装やShift機能など考えていた機能は一部実装せずに「ファームウェアはとりあえず動く」ものを書いて現場に持っていきました。 (とても公開できるようなコードではないので割愛)
実際にVJで使う
作ったその日にVJ現場(NEXTLIGHT FESTIVAL vol.4)があったため、実際にAPC40 MKⅡと共にに持ち込みました

アサインはプッシュ方式で、主にストロボエフェクトにアサインを行いました。
実際に現場で使った感想としては、まだまだ筐体設計で改善できる点があると感じました。
スイッチのボタン自体も3Dプリントで作成しましたが、クリアランスの問題や、斜めから押したときにちゃんと押されない問題などがあり、素直に既製品のキャップを使うべきですね。
押下圧の問題もタクトスイッチを使っている以上、ボタンサイズを大きくしても根本的な解決にはなりませんでした。
今後設計するMIDIコントローラーのボタンには薄型メカニカルキーボードで使われるKailh Choc V2(押下圧約50g)などにしようと思います。
それ以上に「自作MIDIコンが現場で動いている」という満足感はありました(重要)
懸念していた「動作しなくなる」「壊れる」などの問題は発生しなかったため、イベント終わったときにはかなり安心しました。
今後とまとめ
イベント出演駆動開発でMIDIコントローラーを自作しましたが、試作の割にはそこそこ使えるものができました。
今後、APC40 MKⅡを置き換える自分の理想とするMIDIコントローラーの作成にかなり近づくことができたと感じたので、時間があるタイミングで少しづつだと思いますが設計を進めてみます。
制作の部分を解説はかなり端折ってしまいましたが、0から100まで書くと技術同人誌1冊出来上がってしまう量となるため今回は設計の流れの解説程度に留めました。
MIDIコン制作についてはこの記事では語りきれないぐらい話すネタができたため、どこかのイベントなどで話したいですね。
この記事を見た方も是非(?)自分だけのオリジナルMIDIコントローラーを作るのに挑戦してみてください。
スマートメーターから電力が取れるHEM-GW26Aを使ってPrometheus+Grafanaで電力を表示する
https://www.tlt.co.jp/tlt/products/hems/hiroba/hgw-01.htm
スマートホームデバイスとして対応したスマートメーター、家電、太陽光パネルコントローラーなどと接続することでブラウザから情報を見ることができる製品です。
メーカーページを見るとHEMSと蓄電池事業は撤退し、家の設備の1つとして使用することが想定されるものだが、発売から10年経ってない(2015年発売)のにアプリなどのサポートはすべて終わってて悲しい状況です。

この製品を少し前に安く中古が販売されていたのを購入してしばらく放置していましたが、久々に出して遊んでみた記録です。
賃貸で今使えるような機能としては電力計(スマートメーター)からの電力を見る程度ですが、セットアップしてブラウザで見るときちんと現在使用している電力量を見ることができました。

わざわざ画像として表示しているので、単純にページ内要素からスクレイピングをして電力の数値は取得するのは面倒そうです。

調べるとcurl経由で電力瞬間値を取得する方法を書いたQiita記事があったのでこれを参考にPrometheus+Grafanaで電力量を取得してグラフにしようと思います。
純粋なcurlで値を取得できれば/etc/prometheus/prometheus.ymlに書けば収集できそうですが、ヘッダ付与や16進数でのレスポンスなどがあるため、今回はGoでPrometheus Exporterを作成しました。
https://prometheus.io/docs/guides/go-application/
コード自体はGitHub Copilotを使ってあっという間に完成です。IPアドレスやMACアドレスは適宜読み替えてください。
処理内容としては、特定のIPアドレスに10秒おきにアクセスし、取得できた値を16進数から10進数に変換、それを9091ポートでPrometheusが取れるようにするといったものです。
これをサーバーのDockerなどで動かしてあげるとPrometheusから見れるようになると思います。

あとはGrafanaダッシュボードからPrometheusをソースにして設定すれば電力量のグラフが出るようになりました。

電化製品を動かしたときに顕著にグラフが跳ねるのが面白いですね。
家にいない時間帯はかなり低い値で変動なく推移するので在宅しているか否かが分かってしまうので防犯面からは取り扱いには注意したほうが良い値だと思います。
PrometheusやGrafanaでほぼリアルタイムの値が取得できているということは、規定の値(消費電力)を超えたらアラートを出してブレーカーが落ちる前に動かしている電化製品を止めるということもできそうですね。
しばらくはこれらの値を使って、「自分が考える最強のお家ステータスダッシュボード」を作ってみようと思います。
OpenTelemetryに入門する
この記事は🎄GMOペパボエンジニア Advent Calendar 2023 17日目の記事です
概要
最近社内やSRE関係のイベントなどでOpenTelemetryの話題を聞くようになったので「雰囲気で話を聞いている」を脱すべく色々調べた記録です。自分用のメモを公開用に編集したので文章がおかしいところがあるかもしれないですがお許しください。
OpenTelemetryは日々開発が進んでいるプロダクトです。最新の情報は各種公式ドキュメントを参考にすることをおすすめします。(この記事は2023年12月の情報を元に記事を書いています)
OpenTelemetryについて知る
OpenTelemetryはログやメトリクス、トレースのテレメトリデータを作成、管理するために設計されたObservability(可観測性)フレームワークおよびツールキットでベンダー依存ではなく共通の規格となっている。
https://opentelemetry.io/docs/what-is-opentelemetry/
Observability(可観測性)とは
ざっくり以下2点 - システムを詳細に分かってなくても何の問題が起こっているかが分かりやすくなる。 - 新たな問題のトラブルシュートが分かりやすくなる。
この状態にするにはアプリケーションコードがトレース、メトリクス、ログを出す必要がある。
https://opentelemetry.io/docs/concepts/observability-primer/#what-is-observability
OpenTelemtryの仕組み
OpenTelemetry対応させたアプリケーション上からOTel Collectorを通してGrafanaやJaegerなどに送るような流れになっている。
今までの各プラットフォームのAgentが担っていた箇所をOTel Collectorで置き換えるようなイメージ。設定次第で併用もできる。
引用: https://opentelemetry.io/docs/
実際に触ってみる
公式ドキュメントにはGoの1~6の数字をブラウザ上に出すサンプルコードが示されているのでそれを参考にブラウザでアクセスすると標準出力でトレース情報が吐き出されるようにします。
吐き出されたトレース情報
{ "Name": "roll", "SpanContext": { "TraceID": "1b256e3bcf583dcb2f693aa5b9f135be", "SpanID": "3314466bc6b8d377", "TraceFlags": "01", "TraceState": "", "Remote": false }, "Parent": { "TraceID": "1b256e3bcf583dcb2f693aa5b9f135be", "SpanID": "7655ef934c2b3460", "TraceFlags": "01", "TraceState": "", "Remote": false }, "SpanKind": 1, "StartTime": "2023-12-08T03:39:46.663242+09:00", "EndTime": "2023-12-08T03:39:46.664132+09:00", "Attributes": [ { "Key": "roll.value", "Value": { "Type": "INT64", "Value": 6 } } ], "Events": null, "Links": null, "Status": { "Code": "Unset", "Description": "" }, "DroppedAttributes": 0, "DroppedEvents": 0, "DroppedLinks": 0, "ChildSpanCount": 0, "Resource": [ { "Key": "service.name", "Value": { "Type": "STRING", "Value": "dice" } }, { "Key": "service.version", "Value": { "Type": "STRING", "Value": "0.1.0" } }, { "Key": "telemetry.sdk.language", "Value": { "Type": "STRING", "Value": "go" } }, { "Key": "telemetry.sdk.name", "Value": { "Type": "STRING", "Value": "opentelemetry" } }, { "Key": "telemetry.sdk.version", "Value": { "Type": "STRING", "Value": "1.21.0" } } ], "InstrumentationLibrary": { "Name": "rolldice", "Version": "", "SchemaURL": "" } } { "Name": "/", "SpanContext": { "TraceID": "1b256e3bcf583dcb2f693aa5b9f135be", "SpanID": "7655ef934c2b3460", "TraceFlags": "01", "TraceState": "", "Remote": false }, "Parent": { "TraceID": "00000000000000000000000000000000", "SpanID": "0000000000000000", "TraceFlags": "00", "TraceState": "", "Remote": false }, "SpanKind": 2, "StartTime": "2023-12-08T03:39:46.663201+09:00", "EndTime": "2023-12-08T03:39:46.664580041+09:00", "Attributes": [ { "Key": "http.method", "Value": { "Type": "STRING", "Value": "GET" } }, { "Key": "http.scheme", "Value": { "Type": "STRING", "Value": "http" } }, { "Key": "http.flavor", "Value": { "Type": "STRING", "Value": "1.1" } }, { "Key": "net.host.name", "Value": { "Type": "STRING", "Value": "localhost" } }, { "Key": "net.host.port", "Value": { "Type": "INT64", "Value": 8080 } }, { "Key": "net.sock.peer.addr", "Value": { "Type": "STRING", "Value": "::1" } }, { "Key": "net.sock.peer.port", "Value": { "Type": "INT64", "Value": 50016 } }, { "Key": "http.user_agent", "Value": { "Type": "STRING", "Value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" } }, { "Key": "http.route", "Value": { "Type": "STRING", "Value": "/rolldice" } }, { "Key": "http.wrote_bytes", "Value": { "Type": "INT64", "Value": 2 } }, { "Key": "http.status_code", "Value": { "Type": "INT64", "Value": 200 } } ], "Events": null, "Links": null, "Status": { "Code": "Unset", "Description": "" }, "DroppedAttributes": 0, "DroppedEvents": 0, "DroppedLinks": 0, "ChildSpanCount": 1, "Resource": [ { "Key": "service.name", "Value": { "Type": "STRING", "Value": "dice" } }, { "Key": "service.version", "Value": { "Type": "STRING", "Value": "0.1.0" } }, { "Key": "telemetry.sdk.language", "Value": { "Type": "STRING", "Value": "go" } }, { "Key": "telemetry.sdk.name", "Value": { "Type": "STRING", "Value": "opentelemetry" } }, { "Key": "telemetry.sdk.version", "Value": { "Type": "STRING", "Value": "1.21.0" } } ], "InstrumentationLibrary": { "Name": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp", "Version": "0.46.1", "SchemaURL": "" } }
標準出力されるだけではトレースするには難しいため、可視化するために外部のツールへ送信します。 今回はGrafana Agentを用いて先程のトレース情報をGrafana Cloudへ送り可視化してみます。
標準出力で出すコードをOTLPを用いてhttp経由で送信するように変更をします
// otel.go func newTraceProvider(res *resource.Resource) (*trace.TracerProvider, error) { ctx := context.Background() traceExporter, err := otlptracehttp.New( ctx, otlptracehttp.WithEndpoint("grafana-agent:4318"), otlptracehttp.WithInsecure(), )
Grafana Cloudへ送信するため使用するGrafana Agentの設定ファイルを作ります。
まずはGrafana Cloudのページ(https://grafana.com/orgs/[Organization Name])から今回使用するTempoの情報を確認します。

Password:の欄にあるGenerate now.からAPI Tokenを作成するとRead権限しかないAPI Tokenになって書き込みができないので注意が必要です。気づかず2時間近く溶かしました。

https://grafana.com/orgs/[Organization Name]/access-policiesから新たにTempoへのWrite付きのAPI Tokenを作成しましょう

必要な情報が揃ったらconfig.yamlを作成します。必要な箇所は置き換えてください。
# config.yaml traces: configs: - name: default receivers: otlp: protocols: http: endpoint: 0.0.0.0:4318 remote_write: - endpoint: [tempo-url].grafana.net:443 basic_auth: username: [UserID] password: [API Key]
Goで作成したアプリケーションとGrafana AgentをDockerComposeで起動できるようにDockerfileとdocker-compose.yamlを用意します。
FROM golang:1.21 WORKDIR /go-rolldice COPY . . RUN go mod tidy RUN go build -o app . CMD ["/go-rolldice/app"]
# docker-compose.yaml version: '3' services: go-rolldice: container_name: go-rolldice image: go-rolldice ports: - "8080:8080" build: . volumes: - .:/etc/go-rolldice/ environment: - OTEL_SERVICE_NAME = go-rolldice - OTEL_METRICS_EXPORTER = otlp grafana-agent: container_name: grafana-agent image: grafana/agent:latest ports: - "4318:4318" volumes: - ./grafana-agent/config.yaml:/etc/agent/agent.yaml command: -config.file=/etc/agent/agent.yaml
docker-composeで起動してlocalhost:8080/rolldiceへ数回アクセスし、GrafanaのExploreからTempoを選ぶと届いているトレース情報を確認することができます。


シンプルなアプリケーションなので複雑なトレース情報ではないですが、ちゃんとroll.valueが4のトレースデータが届いて見ることができました。

まとめ
公式のドキュメントを参考にOpenTelemetryの初歩的なところを触ってみました。
OpenTelemetryはどのように動いているか、実際のアプリケーションコードへ導入するにはどのように変えていくと良いかのイメージを少しつけることができました。
なにより使用される単語が少々特殊なものが多い印象だったのでそれらの意味を理解できただけで非常に良かったです(実際CNDT2023へ行く前に調べていたのでセッションを聞きながら「この前調べたやつだ!」と思っていました)
この記事がOpenTelemetryを初めて触る方の参考になれば幸いです。
天下一キーボードわいわい会 Vol.5を支えたハイブリッド配信技術
先月開催された天下一キーボードわいわい会 Vol.5で配信担当をしましたyuchiです。
1ヶ月ほど経ってしまいましたが、天キーvol.5は過去最高の物量と規模で配信を行っていたのでその裏側を解説したいと思います。
実際の配信アーカイブは現在もご覧いただけます。
天キー配信チーム
天キーvol.5配信チームとして自分、kai4562さん、daihukuさんの3人で配信を行いました。それぞれ機材を持ち寄っていただき、当日オペレーション協力をしていただき無事に事故なく配信を行うことができました。
今回用いた機材は会場で一部お借りしたものを除いてレンタル一切なしのすべて配信チームの私物です。
自分の持ち込んだケーブル類に関しては合計100mを超えていました
天キーの配信を支えていた機材群
— yuchi / ゆーち (@F_YUUCHI) 2023年11月5日
ケーブルは総延長100mを超えていました pic.twitter.com/dUTVOMEfoC
加えて全て手搬入をおこなったので同じビルに入っているテレビ局で使われてそうな箱を転がしながら会場へ入りました。

構成図
まずは今回使用した配信システムの構成図を見ていただいて簡単に解説していきます。

ATEM 2 M/E Constellation HD
今回配信機材のコアにATEM 2 M/E Constellation HDを使用しました。 この機材を買った理由などは別エントリーで詳しく書いたので合わせて読んでいただければ。
今回入力はカメラが3台、登壇者のスライドのPC、セッション間の幕間に出す写真を出すPCで合計5入力ありました。
機器の出力はHDMIですが、スイッチャーの入力はSDIのためすべてコンバーターを挟んでいます。
自由にルーティングが行える出力端子が今回非常に役に立ちました。 構成図で書かれているのは以下のように使っていました。
- OUT1 : スライドPC(IN 3)から来た映像を会場画面に出力
- OUT2: スライドPC(IN 3)から来た映像を登壇者足元に置かれるどのような映像が出ているかの確認モニター(返しモニター)に出力
- OUT3: カメラ映像(IN 1)からきた映像を録画用にHyperdeck Studio 12Gへ出力
- OUT4: 配信に使っている映像(M/E 1)をプレビューモニター兼録画としてSHOGUN 7へ出力
- OUT10: 配信用にスイッチングした映像(M/E 1)をYouTubeへ送るためにWebPresenter HDへ出力
元々自分が使っていたATEM Miniシリーズでこれを行おうとすると入力の前段にHDMIのスプリッターを入れるなどの手段がありますが、配信機材において機材やケーブル接点が増えることが映らないなどの事故リスクがあがることはもちろん、それぞれ出力の切り替えにケーブルの抜き差しや別途スイッチャーが必要など色々大変です。
カメラ
カメラは今回3カメラ体制で行いました。
セッション会場では登壇者の寄りと会場を含めた引きの映像を用意しました。
カメラはkaiさんに用意していただき、それぞれのカメラの上にはkaiさんが開発したタリーランプを載せてATEM Constellationシリーズでうまく動作するかの検証も兼ねて運用してもらいました。
キーボードは諸般の事情により展示していませんが、NeoPixelが光る実質キーボードのタリーランプを実運用しています #天キー pic.twitter.com/WrWMTWgx9t
— かい (@kai4562) 2023年11月4日
もう1カメラはメイン会場のオープニングとエンディングの様子を撮影してもらい、HDMIのトランスミッターで映像を伝送しました。
2スペースにまたがる会場
今回、DMM.comさんの会場を再びお借りして開催されましたが、1回目~3回目まで使っていた会場に加えて新たにもう1スペース使わせていただけることができ、それぞれで登壇者の様子を映す必要が出てきました。
構成図上だと点線から左側がその今回新たに加わった会場です。非常に広い会場で、それぞれのスペースの間は30m以上開いているため無線か有線どちらの映像伝送を用いるか悩みます。
結論から言うと今回は無線での伝送を選択しました。
SDIケーブルを引く方法は30m以上離れていたため、3CのSDIケーブル*1では伝送できない可能性があり、5Cを用意する必要があります。5Cの50mのケーブルを手で持ち込むのは非常に大変なのが容易に想像できるため不採用でした。
今回の使用したHDMIトランスミッター MARS300は5.2GHz帯を用います。WiFiの5GHz帯と似たように直進性能が高く、天キーのイベント会場のような人が多い場所で使用すると大きく減衰されてしまい、映像が来ないことも考えられます。
今回行った対策は会場にあったライトのスタンドを許可を得てお借りし、クランプでレシーバーを挟んで最大限高さを稼ぐ方法でした。
本番中もちょくちょく映像が来ないことが起こり、その度にスタンドの高さを上げて最終的には2.5m以上になっていたと思います。それほど人による減衰は大きかったです。

やってみての感想
この会場規模、機材量、チーム人数での配信は初めてだったので事前に会場入りの時間から撤収まで含んだオペレーションの進行台本を作ることや自宅での通しテクリハなどなど。それでも当日想定通り進まないのが配信です。

前半は配信を行いつつ、トラブル解消のため配信卓周辺であれやこれやとバタバタしていました。
また、連絡はDiscordを使用していましたが、すぐに気づくことができなかったり、リアルタイム性を求められることもありインカムやトランシーバーの導入は必須だなと感じました。
色々細かいミスや想定外のことがありましたが、終わったあとのビールは最高ですね。
まとめ
ハイブリッド配信かつリアル会場が複数ある場合機材やオペレーション、配信事故に繋がりそうなリスクが高く非常に大変です。
今回は大きな事故なく配信を無事に終えつつ、小さいミスに関しては次は起こさないようにするといった今後必ず役に立つ経験となりました。
また、配信チームとして協力してくださったkaiさん、Daihukuさん、配信画面デザインをしていただいたPekasoさん、天キー主催のゆかりさん他当日も様々な方にお手伝いいただきました。ありがとうございます。
天キーVol.6が開催された際は配信卓に座っていると思うので興味ありましたらお気軽にお声がけください。
*1:SDIケーブルには太さの規格があります。数字が低いほど細くしなやかで軽いですが数字が増えれば太く取り回しがしにくくなりますが、伝送距離が伸びます
Blackmagic Web Presenter HDのフェイルオーバーの挙動を調べた
スイッチャーを乗り換えてから配信はBlackmagic Web Presenter HDを使っています。
この機材は有線LANだけではなく、USB Type-C端子からスマートフォンのテザリング機能を使ってバックアップの回線を用意することができます。
USBテザリング機能があるモバイルルーターも使えるので絶対に落としたくないような現場では回線の冗長化を行っていました。幸いなことに今まで有線LAN側で問題が起こったことなく、実際に問題が発生したときにフェイルオーバーの挙動がどうなるのかが気になったので意図的にLANケーブルを抜いたときの挙動を調べてみました。
検証環境
- Blackmagic Web Presenter HD
実際に配信中にLANケーブルを抜いてみる
図のようにルーターとスイッチングハブを繋がっているLANケーブルを抜き、スイッチングハブとBlackmagic Web Presenter HDはリンクアップしている状態にしました。

結果としてはフェイルオーバーされることなく配信がストップしてしまいました。
次にWeb Presenter HDに刺さっているLANケーブルを抜いて挙動を確認してみます。

この場合は正しくスマートフォン側にフェイルオーバーされて配信が継続できました。生放送アーカイブを確認すると8秒程度の映像の欠落が発生していました。
Web Presenter HDのコンソールの録画のスクリーンショットです。00:01:00にLANケーブルを抜いてます。
わかりにくいですがON AIRの横のスマホマークが1分3秒ごろに青くなり回線の切り替えが行われたことを表しています。

逆にスマートフォン側で配信が行われている状態でLANケーブルを戻してもスマートフォン側で配信が継続しました。 この点はフェイルオーバー後気づかずに配信継続が行われて通信量制限にかからないように注意が必要ですね。
最後に有線LANが繋がっている状態でスマホ側の接続を切ると4秒程度の映像の欠落が発生しました。スマホ→有線LANの切り替えはすぐに行われるようです。
実際の配信アーカイブです。以下のタイミングで抜き差しを行っています。
- 00:01:00 有線LAN接続断
- 00:01:30 有線LAN差し込み(変化なし)
- 00:02:00 iPhone接続断
まとめ
フェイルオーバーされる条件は有線LANのリンクアップが切れたらということが分かりました。 有線LAN側の通信速度が著しく遅くなったり、ルーター側の電源停止やルーターとスイッチングハブの間のLANケーブルが切断されることが発生しても、Web Presenter HDがスイッチングハブと繋がっているとLANのリンクアップが継続されるためフェイルオーバーにはなりません。物理層レベルで接続が無くなることがフェイルオーバーの条件のように考えられます。
なのでコンソールのキャッシュが急増してすぐに戻らないようであれば有線LANを抜いてスマートフォン側に切り替わるようにする必要がありそうです。
誰かの参考になれば幸いです。