ドライブレコーダーの動画ファイルからGPSデータを抜き出して動画編集する(2) 作製編

アプリ
スポンサーリンク

こん○○は、よふかしわーくすの、よふかしさんです

前回、ドラレコからGPSデータを抜き出して動画編集する(1) 解析編では
ドラレコのmovファイルに埋め込まれたGPSデータが
どのような構造になっているのかを解析しました

今回はその結果をベースに、AviUtlで動画とGPSデータを合成することを検討します


スポンサーリンク

AviUtlでどうやってGPSを合成するか?

結論から言うと、VSD for GPSというプラグインがあります
よふかしさんも10年以上使ってる便利なプラグインです

X(旧Twitter)では2017年時点で開発終了?ということでGitHubにてソースコードが公開されました
なんですが、何気に2025年に入っても微妙にメンテされている様ですw
2025年1月現在時点での正規リリースの最新版である、r1011を使用していくことにします

DL~使い方まで、公式ページで詳しく解説されているのでここでは割愛…

※追記
色々あって、VSD for GPSを含めた、AviUtlのインストール~初期設定方法を記事にしました


VSD for GPSにどうやって読み込むか?

これまでによふかしさんがVSD for GPSを使うときは
市販のGPSロガーを使用し、LAP+というツールでログを保存した、
dp3形式のファイルで動画編集してました

dp3のデータ構造も以前に解析済みなので、ドラレコのGPSログを変換するツールを作ってもよいのですが、
もっと汎用的なファイル形式ないかな?と、まずはVSD for GPSが対応しているファイル形式を調べました
こんな感じ

モータスポーツ用の器材の形式が多いですが、一般的なファイル形式も扱っている様です
Readerのjsファイルを作る方法もありますが、汎用的でないので今回はパス
ちょっと調べた結果、今回はgpx形式が一番合っていそうということでこれに決定して進めてみます


gpxファイル形式を理解する

ひとまず、Wikiをみる

GPX(ジーピーエックス、GPS eXchange Format)は、GPS/GNSS装置やGPS/GNSSソフトウェアなど、アプリケーション間でGPS/GNSSのデータをやりとりするためのデータフォーマットである。GPXは、XML Schemaベースでデザインされており、ウェイポイント軌跡、ルートなどを記述する。

とりあえず、XMLで記述するということだけわかった

Official GPX web siteをみるとDeveloper向けにDocumentationが書かれているが
スペシャリストになりたい訳ではないので軽くスルーすることにした

公式以外のサンプルファイルないかな?と思って探したところ
大東文化大学のサイトがヒット
雰囲気は掴んで、なんとなくわかった気になる

ところで
今回は正しいgpxファイルを作成する必要はなくて、VSD for GPSで読めさえすればよく
最小限の情報が書かれたXMLを作成すればよい訳である
なので
理解もそこそこに、ドラレコのGPSログをgpxファイル形式に変換することに着手した


VSD for GPSで読めるgpxを考える

ということで、まずはVSD for GPSのgpxファイルのReaderファイルである、gpx.jsを見てみる

// GPX リーダ

LogReaderInfo.push({
	Caption:	"GPX (*.gpx)",
	Filter:		"*.gpx;*.gpx.gz",
	ReaderFunc:	"Read_gpx"
});

function Read_gpx( Files ){
	
	Log.Time		= [];
	Log.Speed		= [];
	Log.Altitude	= [];
	Log.Longitude	= [];
	Log.Latitude	= [];
	
	var	Cnt			= 0;
	var Buf			= '';
	
	// 一旦全ファイルを Buf に溜める
	for( var i = 0; i < Files.length; ++i ){
		// kml を普通に open
		var file = new File();
		try{
			file.Open( Files[ i ], "zrb" );
		}catch( e ){
			MessageBox( "ファイルが開けません: " + Files[ i ] );
			return 0;
		}
		
		do{
			Buf += file.ReadLine();
		}while( !file.IsEOF())
		
		file.Close();
	}
	
	// Google My Tracks のバグ? 回避
	var bMyTracks = Buf.match( /Google My Tracks/ );
	var Points;
	
	if( Points = Buf.match( /<trkpt[\S\s]*?<\/trkpt>/g )){
		Points.forEach( function( Point ){
			// <trkpt lat="35.12345" lon="135.12345">
			// <speed>0.0</speed>
			// <time>2012-04-28T21:27:50.328Z</time>
			// <ele>128.1</ele>
			// </trkpt>
			
			// 時間
			if( !Point.match( /<time>(\d+)-(\d+)-(\d+)T(\d+):(\d+):([\d\.]+)(Z|([-+]\d+):(\d+))/ )){
				return;
			}
			Log.Time[ Cnt ] = Date.UTC(
				RegExp.$1, RegExp.$2 - 1, RegExp.$3,
				RegExp.$4 - ( RegExp.$7 == 'Z' ? 0 : RegExp.$8 ),
				RegExp.$5 - ( RegExp.$7 == 'Z' ? 0 : RegExp.$8 >= 0 ? RegExp.$9 : -RegExp.$9 ),
				~~RegExp.$6, ~~( RegExp.$6 * 1000 ) % 1000
			);
			
			// long, lat
			if( !Point.match( /lat="(.*?)"/ )) return;
			Log.Latitude [ Cnt ] = +RegExp.$1;
			if( !Point.match( /lon="(.*?)"/ )) return;
			Log.Longitude[ Cnt ] = +RegExp.$1;
			
			// Speed がある場合は Array 作成
			if( Point.match( /<speed>([\d\.]+)/ )){
				Log.Speed[ Cnt ] = 3.6 * RegExp.$1;
			}
			
			// ele がある場合は Array 作成
			if( Point.match( /<ele>([\d\.]+)/ )){
				Log.Altitude[ Cnt ] = +RegExp.$1;
			}
			++Cnt;
		});
	}else{
		return INVALID_FORMAT;
	}
	
	if( bMyTracks ) SmoothLowFreqLog();
	return Cnt;
}

ふんふん
trkptタグを作って、time、lat、lon、speed、eleを書けばよい模様
latはlatitudeで緯度、lonはlongitudeで経度、eleはelevationで高度
ドラレコにはeleがないので、それ以外を記述すればよさそう
Gに関してはVSD for GPS内で計算してくれるので、time、lat、lon、speedの4つを変換すればよい

先の大東文化大学が公開しているサンプルを見てイメージを固める
http://www.ic.daito.ac.jp/~mizutani/gps/data/2013_aug26_toyara.gpx


gpxのデータ定義

gpx.jsからリバースすると、timeとspeedはわかったが、latとlonが何形式かわからなかった
色々調べたり試した結果、結論としては下記となっていた

  • time:UTC時間(YYYY-MM-DDThh:mm:ss.sssZ)
  • lat、lon:DD形式
  • speed:m/s

GPSのログは下記の通り

  • time:JST時間(YYMMDDhhmmss)
  • lat、lon:DMM形式
  • speed:km/h

これらを変換すると下記の様になる

  • time:JST – 9(UTC形式)
  • lat、lon:DMM形式で3539.5073の場合
    • 39.5073 / 60 = 0.658455
    • 35 + 0.658455 = 35.658455(DD形式)
  • speed:60[km/h]の場合
    • 60 / 3.6 = 16.66666667 [m/s]


正式なgpxとは異なるが、VSD for GPSにミニマムで読み込ませるためには
下記の様に記述すればよい

<trkpt lat="35.658455" lon="139.741416667">
    <time>2025-01-23T12:34:56.000Z</time>
    <speed>16.66666667</speed>
</trkpt>

gpx.jsから理解した結果、上記サンプルの通り
本来のgpxに必要なヘッダ等の情報はなくてもVSD for GPSで読める
dp3はバイナリデータだったので、XML形式のgpxの方がぱっと見てもわかりやすくてよい感じ

これらの仕様に基づいて、簡易的にPythonコードを組んで
GPSデータをVSD for GPSが読めるgpxに変換することを試す


VSD for GPSに合わせたgpxに変換するPythonコード

ひとまず、簡易的なPythonコードで作成したgpxデータをVSD for GPSでLoad
これ自体はうまくいったのだが、動画編集で合成したところ、表示される車速やGPSの軌跡が変だった

具体的には、一定期間無反応になり、動作したと思ったら、
パラララ…と瞬間的に連続で値が変化したあと、また一定期間無反応になる…

日時情報は、
YYYY-MM-DDThh:mm:ssZ、ではなく
YYYY-MM-DDThh:mm:ss.sssZ、というように
謎のインデックス情報を基に小数点以下の時間も入れていたのであるが…

第一回の記事でも書いた通り、
動画は29fps、GPSは10Hzで、HDRviewerではGPSデータを線形補間して表示することがわかっていた

VSD for GPSも市販のGPSロガーで5Hzのログを読み込ませたとき
30fpsでも60fpsでもうまく線形補間して表示してくれる仕様になっていることは知っている

つ ま り

ドラレコのGPSログが線形補間の邪魔をしていることになる

改めて、変換したgpxデータを確認したところ

lat、lon、speedは2Hzでしか更新されていなかった…

えぇ………

というわけで
生GPSログのlat、lon、speedが変化した時だけgpxに出力する仕様にPythonコードを改修したところ

期待する動作になりました!!!!1

こんな感じ(動画部分は黒塗り)


終わりに

  • ドラレコのGPSログをVSD for GPSで最低限読み込めるgpx形式に変換
  • AviUtlでGPSログを合成した動画編集

ができるようになりました
ちょっと整理したあとになるかと思いますが
動画からGPSデータを抜き出すツールを、exeで公開しようかなぁと考えてます

60秒毎のmovデータを効率的に繋げて編集するためのコードも作ってあるので
それもセットで検討したいなと思ってます

※追記
順次Downloadページで公開していきます

公開日時:2025/01/10 23:59:00

コメント

タイトルとURLをコピーしました