h_nari @ 熊本市のブログ。電子工作、プログラミング、ゲーム、TV、 政治、インターネットなどに日々の思い付きを、 うだうだ~と書いていきたい。
このブログにはコメント欄を設けておりません。 記事への御意見、ご質問はtwitter @h_nari宛に お願い致します。


アーカイブ


アマゾン・ベストセラー

メタ情報
RSS
Login

ドラレコ軌跡表示(2)

以前作成した ドラレコ軌跡表示プログラム の改良を続けている。 達成できた主な改良点は、
  1. 動画を表示できるようになった。 ドライブレコーダに記録されている30秒ごとの AVIファイルを結合し、画面に表示できる。 動画は最大10倍速で再生可能。
  2. 経路と動画の対応付け。 地図上の経路を右クリックし、 経路名と通過日時を表示、その地点から動画を再生できる。 再生中の動画の場所をマーカーで地図上に表示することもできる。 動画再生中は、マーカーは動き続ける。
  3. ドライブレコーダのSDカードを読み込むプログラムを Pythonのものから Electron + typescriptのものに変更。 読込み中の経路を地図に表示できる。
などである。

以下、この記事では、このプログラムに関連する 技術的話題をいくつか紹介していく。 ドライブレコーダのSDカードから GPSの経路情報を抜き出す話は 前の記事 を参照していただきたい。

技術的話題1 動画の再生

軌跡に合わせてドラレコの動画も表示したいのだが 通常の.mp4形式の動画ファイルにすると 長時間のドライブの動画はダウンロードに長い時間がかかる。 そこでYoutubuなどの動画配信ではどうしているのだろうか と調べたところで HLS(HTTP Live Streaming)というプロトコル があることを知った。

HLSを使って動画をストリーミング配信する という記事通りにやったところ、 ffmpegで変換でき、 hls.js というライブラリで表示できた。 表示は htmlの<video>要素で行われるので HTMLMediaElementとして再生を操作できる。

技術的話題2 動画と経路の対応付け

前の記事に詳しいが ドライブレコーダの AVIファイルには 動画の画像フレームと同数のGPSの情報がある。 つまりフレーム毎にGPSの緯度経度情報がある。 ドライブレコーダのAVIファイルは30秒ごとに分割されているため 表示用に複数のAVIファイルを結合するが、 それでも対応するフレームがわかれば、対応する緯度経度はわかるはずである。

はず、というのは実際には動画の結合や再エンコーディング時に動画の長さが 長くなったりするからである。が、ここでは 説明を簡単にするため、 動画の再生位置(時間)がわかれば緯度経度がわかるし、緯度経度がわかれば 時間がわかるものとする。

地図上の経路近くをクリックし、最近点の時刻を表示し、動画を再生するには 以下のようにする。

  1. クリックした位置の緯度経度を取得する。 これは leaflet Map.mouseEventToLatLng()でできる。
  2. 表示されている経路の各点の緯度経度とクリックされた点の緯度経度の距離を Map.distance()で求め、 もっとも最近点を求める。 決められた距離よりも近い点が無ければ最近点は見つからなかったものとする。
  3. 最近点が見つかった場合、 その経路の動画のURLを HLSプレーヤーにセットし、 <video>タグの HtmlMediaElement の currentTime 属性に フレーム数から計算した時間をセットする。

動画の再生画面に対応する場所を地図に示すには以下のようにする

  1. 地図上に場所を示すために leaflet では Marker とういうものが準備されている。 L.Marker(緯度経度)で作成、 map.addLayer(marker)で地図に表示される。 .setLatLng(緯度経度)で既にあるMarkerの位置を変更できる。
  2. ビデオの currentTimeを取得し、 その時刻の前後の緯度経度情報を決定する。 前後の情報を取得するのは、GPSの緯度経度情報が最短でも1秒間隔で、 トンネル等で長時間GPS情報が取得できない区間が存在するからである。 前後の情報から線形保管で位置を求めることで、1秒よりも短い間隔で 位置を更新したり、トンネル部分の位置更新も可能になる。
  3. Markerの位置更新後、その位置に map.panTo(緯度経度)で地図の中心を 移動させると、地図中央にMarkerを表示させ続けることができる。
  4. 上記の、ビデオのcurrentTimeからMarkerの位置を更新させる処理を setTimeout等を利用して設定した周期で呼び出し続ける。

動画伸びる問題

ドラレコの動画ファイルは30秒刻みのAVIファイルなので、 任意の部分をすぐに表示するには 全て結合しHLSプロトコル用のファイルに変換しなければならない。 これは ffmpeg コマンド1発でできるのだが、変換で動画が伸びてしまう。 例えば30秒の動画100本を変換すると 50分の動画になるはずが55分の動画に なったりする。

動画が長くなると、動画と位置がずれる。

原因は AVIファイルに含まれる音声トラックが動画トラックよりも長いせいではないかと想像するが、よくわからない。 音声トラックを出力しないように指定しても変わらない。 AVIファイルの音声トラックを全て取り除けば良いのかもしれないが、 数が膨大でやる気が起きない。

調べると、動画にはPTSとかDTSとかあるらしい。 (参考: ffmpeg を使うなら知っておきたい話 PTSとかDTSの話) PTSだけ、あとから付け直すということも可能らしいのだが、よくわからない。 とりあえず、次の記事を参考に OpenCVで画像を結合した。 (参考: OpenCVを使って複数動画を一発で連結する) 画像結合時の動画の伸びはなくなったが、HLS変換時に若干伸びている気がする。

最後に

ドライブの結果を地図上に航跡として見れるのは楽しい。 地図を凝視し、未だ通っていない道を発見し、走りたくなってくる。 現在は、それに加えて動画の再生までできる。 10倍速での再生が可能なので、4時間のドライブでも24分で再生できる。 ついつい何度も見てしまう。

動画はディスク容量の問題があるので、いずれ消すことになるとは思う。 まだまだ改良の余地は多いので、少しづつでもいじって行きたい。

プログラム操作の様子の動画