
動画ファイルをintdashに取り込みたいみなさん、
こんにちは。ソリューションアーキテクトの伊勢です。
今回はMP4ファイルをintdashの計測データとして登録する方法をご紹介します。
はじめに
すでに保有している計測データファイルをintdashで可視化したいケースがあります。
例えば、システム構想段階でUXを試したいときなどです。

通常、intdashの計測データはエッジコンピューターからサーバーに送信されますが、サーバーにファイルの計測データを登録する機能もあります。
intdashのMeas Hubでは、タイプスタンプとデータ値が格納されたCSVファイルをアップロードして計測を作成できます。

time,DATA_1,DATA_2,DATA_3 2024-01-01T00:00:00.123456789Z,1,0.1,str1 2024-01-01T00:00:01.123456789Z,2,0.2,str2 2024-01-01T00:00:02.123456789Z,3,0.3,str3 2024-01-01T00:00:03.123456789Z,4,0.4,"str4,example" 2024-01-01T00:00:04.123456789Z,5,0.5,"str5 ""last data"""
この方法ではデータは数値または文字列の形式である必要があります。
今回は映像データを登録するため、SDKを使ってツールを実装します。1
データフロー
今回は、取り込んだ映像を他の計測と同期再生させてみます。
- 既存の計測からMP4としてダウンロード
- 映像編集ソフトで加工
- ツールでMP4ファイル(編集後)をアップロード
- Data Visualizerで可視化・同期再生

H.264とは
今回扱う映像データはH.264で圧縮されています。
前のフレームから変化した部分だけを扱い、データ量を低減する仕組みです。
- IDRフレーム/キーフレーム:すべての画素を持ち、単独でデコードできます。動画の基準点として定期的に差し込まれます。
- Non IDRフレーム/デルタフレーム:変化した部分だけを持ち、単独では表示できません。IDRフレームと組み合わせて利用されます。
H.264フレームは、1〜複数のNAL Unit(Network Abstraction Layer Unit)というバイナリ列で構成されます。
MP4ファイルとは
動画や音声をひとつのファイルにまとめて扱える形式です。
再生時には内部の映像や音声を取り出し、タイムスタンプに基づいて同期再生します。
H.264の格納形式とは
バイナリデータである映像フレームを区切る方法です。
AVCC形式:保存向き。フレームの先頭にフレームサイズを記録します。最新のMP4で利用されます。2
Annex B形式:ストリーム向き。フレームの先頭に境界を示すスタートコードを付与します。intdashなど伝送処理で利用されます。
Gstreamerとは
動画・音声を変換できるオープンソースのメディアフレームワークです。3
今回はMP4ファイルのAVCC形式からAnnex B形式へ変換するのに利用します
インストール
SDK入門②でインストールしたREST APIのクライアントライブリと、
SDK入門④でインストールしたGstreamerとPyGObjectライブラリを利用します。
やってみた
実施手順
それでは、前述の流れでMP4ファイルを取り込みます。
H.264フレームのタイムスタンプが各段階でどうなるかを示します。

MP4ファイルはAVCC形式のタイプスタンプ項目に1フレーム目起点の相対時刻を持ちますが、絶対時刻はありません。
そのため、ツールで改めて計測の基準時刻を与える必要があります。
MP4ファイルダウンロード
intdashのMedia Explorerで元計測の映像をMP4ファイルとしてダウンロードします。4 このとき、映像1フレーム目の時刻を覚えておきます。

MP4ファイルをダウンロードします。

映像編集
MP4ファイルを映像編集ソフトで編集します。
今回は文字をオーバーレイしてみます。
MP4ファイルを出力します。解像度・FPSは映像編集ソフトに依存します。
アップロード実行
対象エッジと基準時刻を指定してアップロードします。
今回は元の計測とは別のエッジとして作成します。
基準時刻は元計測の映像1フレーム目の時刻にします。5

全ての映像フレームがアップロードされ、計測が完了します。


計測再生
intdashのData Visualizerで元の計測を指定してプレイバック再生します。
- 映像(左)・GNSS・IMU:元の計測です。
- 映像(右):編集したMP4ファイルから取り込んだ計測です。
映像は元の計測がHD・15FPS、編集後がFullHD・30FPSですが、
計測データのタイムスタンプにより、問題なく同期再生されます。
サンプルプログラム
Gstreamerとデータ送信を非同期で実行しています。

- Gstreamer:H.264フレームをAVCC形式からAnnex B形式に変換します。
- Fetchステージ:GsteamerからAnnex B形式のフレームを取り出します。
Convertor
Gstreamerをラップします。
入力はMP4ファイルから呼ばれるため、特にメソッドはありません。
出力では、映像フレームをsizeごとに取得します。
while len(frames) < size: sample = await asyncio.to_thread(self.sink.emit, "pull-sample")
MeasurementWriter
計測の作成・完了、シーケンスの作成・置き換え、チャンク送信を行います。6
intdashのH.264フレームは以下のNAL Unit順で扱うため、Gstreamerから出力されるAUDNALU Type:9をスキップしています。
- IDRフレーム:SPS
NALU Type:7→PPSNALU Type:8→IDRNALU Type:5 - non-IDRフレーム:non-IDR
NALU Type:1
payload = MeasurementWriter.skip_aud(frame)
IDR/non-IDRを判定し、送信時のデータ型を指定してデータポイント、チャンクを生成しています。
is_idr = self.is_idr_frame(payload)
type_name = "h264_frame/idr_frame" if is_idr else "h264_frame/non_idr_frame"
store_data_point_group = StoreDataPointGroup(
data_id=StoreDataID(type=type_name, name=data_name),
data_points=[store_data_point],
)
store_data_chunk = StoreDataChunk(
sequence_number=self.sequence_number,
data_point_groups=[store_data_point_group],
)
UploadService
GstreamerパイプラインとFetchステージを並列起動しています。
self.convertor.start()
fetch_task = asyncio.create_task(self.fetch()) # H.264フレーム取得
エントリーポイント
MP4ファイルを読んでH.264(Annex B形式)に変換するGstreamerパイプラインを定義しています。
PIPELINE = """ filesrc location="{path}" ! qtdemux name=demux demux.video_0 ! h264parse config-interval=-1 ! video/x-h264,stream-format=byte-stream,alignment=au ! appsink name=sink sync=false emit-signals=true """
計測の基準時刻をRFC3339形式で指定します。
指定がないときは現在時刻を基準時刻にしています。
datetime.fromisoformat(basetime)
if basetime
else datetime.now(tz=timezone.utc),
おわりに
今回はintdash外のデータを取り込む一例を紹介しました。
MP4ファイルのタイムスタンプを利用して、intdashの時系列管理に統合できました。
既存の計測データでintdashへの格納や可視化を試せると、システム運用を具体的にイメージしやすくなります。
リンク
本シリーズの過去記事はこちらからご覧ください。
- SDK入門①〜社用車で走ったとこ全部見せます〜 :REST APIでデータ取得
- SDK入門②〜データ移行ツールの作り方〜:REST APIでデータ送信
- SDK入門③〜RTSPで映像配信するぞ〜:リアルタイムAPIでデータ取得
- SDK入門④〜YOLOで物体検知しちゃう〜:リアルタイムAPIでデータ送信
- SDK入門⑤〜iPadでData Visualizerを見る会〜:リアルタイムAPIでキャプチャデータ送信
- SDK入門⑥〜最速最高度で計測する日〜: AWS LambdaでREST APIデータ送信
- SDK入門⑦〜計測リプレイツールの作り方〜: REST APIでデータ取得、リアルタイムAPIでデータ送信