先日来、OSMO Actionで撮影した動画にWahoo ELEMNT BOLTのデータを表示する、ということをやっている。元々、ELEMNT BOLTはCANYON用のマウントで搭載していて、これは下部にGo Proなどのアクションカメラのマウントもあるので、そこにOSMO Actionを装着した次第。OSMO Actionは記録する画質が2.7K以上で無いとRock Steadyという映像ブレ補正技術が効かず、2.7Kでは内蔵バッテリーで実測80分程度しか録画出来ないため、サドルバッグに入れたモバイルバッテリーまで1.5メートルのUSB-C to USB-Cなケーブルを引っ張り、タイラップでケーブルを固定している。
撮影した動画にELEMNT BOLTから出力したFITファイルのデータを表示するのに、まずはGarminのVIRB Editを試してみた。
で、何が不満だったかというと、ギアが表示出来ないことと、動画とFITのタイミングを合わせるのが「地図上の位置」で行う点。自分が乗ってるCANYONはSRAM Force eTAP AXSにパワーメーターを追加しているが、シフターが無線なので現在ギアがいくつかということは、サイコンの画面でないと確認出来ない。なので、動画中でも「あー、この時、2-10までギア変えたのか」とか知りたい。タイヤの周長をL(mm)、ケイデンスをC(bpm)、フロントギア/リアギアの歯数をF/Rとすると、60CFL/1000000R(km/h)なので、ギアから計算される速度とサイコンの実測値の違いを確認したりもしたい。
じゃあ作るかということで、まずFITにfileコマンドして、まあバイナリだよねhexdumpするかなるほどFITというシグネチャが入ってるのね、まで数分。んでちょっとググって、FIT SDKを見つけてきて、ざーっと目を通す。んー、大して面倒じゃないけど、誰かパーサを書いてないかなぁ、とググる。最初に見つけたパーサは使い勝手が悪く、fit parserの検索結果を総当たりして見つけたのが、PyPIにあったfitdecode。FITファイルを食わせてとりまイテレータでメッセージ部分をダンプしてみると、問題無さそう。じゃあこいつで、というところまで小一時間。
ダンプは出来るようになったものの、フィールド名がunknownだったりするので、それを要・不要分けてdict
の配列に突っ込むか否かを処理したり、FIT SDKには無い形式で保存されてるデータを変換したりをparseint()
という関数にまず実装。ELEMNT BOLTのイメージを動画に合成するのに、PillowでPNGを出力してffmpegでオーバーレイする作戦にしたものの、Pillowが遅くてどうしたもんかなぁ、あ、ワークアラウンドがあるやん、で高速化に成功。でも、まだ遅いなぁ、ループ内に無駄な処理が多いからそれを直して、っと、はい、合成できた、までは結構時間がかかった。
githubに公開したやつは、ここまでを実装してある。手元のバージョンでは地図を表示出来るようにしてあるけれど、公開する前にちゃんとオブジェクティブに書き直したいわぁ…。