GoProのメタ情報をある程度維持したまま、分割保存されているファイルを結合したい

2023/09/09 22:00

※ 商品のリンクをクリックして何かを購入すると私に少額の報酬が入ることがあります【広告表示】

GoProのファイルは4GBごとに分割される

GoPro HERO9 Blackの場合は4GBごとにファイルが分割されます。 新しいGoProはもう少し大きなファイルになるようですが、結局分割されます。

標準のアプリを使って結合すると再エンコーディングが入るため、時間はかかるは画質は落ちるはであまり良くありません。

再エンコせずに結合だけするツールのGUI版を作っている

ffmpeg、便利なんですが複数ファイルを指定して結合するコマンドを作るのが面倒なんです。

以前、ターミナルにファイルをドロップするとffmpegで結合するCUIツールを作りました。

しかし、macの標準入力の限界が結構小さくて、ファイル数が多いと入力できませんでした。というのと、あらかじめFinderで並べておくとか、対象のファイルを自分で選択するなどだいぶ面倒でした。

そこで、SwiftでGUI版を作っています。

GUI版

ファイルの名前で分割されたファイルはわかるので、最初のファイルのサムネイルと、幾つファイルがあるのか、結合されるとファイルサイズはどのくらいあるのかなどを表示しています。

結合したい動画を選択して、実行すれば結合されます。

Lightroomで取り込もうと思ったら日時が1904年だった

作成日時を撮影日にしつつ、exifのCreate Dateも更新するようにしているのですが、Lightroomで取り込んだら1904年になってしまいました。いけてたはずだったんですが、どこかのタイミングでぶっ壊したのかな?

ISO8601DateFormatter でフォーマットした文字列を -metadata creation_time="(creationTime)" としてffmpegに渡しているのですが、どうもうまくいかないようです。ついでに Create Date も追加しましたが、こちらもダメでした。

  let creationTime = ISO8601DateFormatter().string(from: _creationDate)
  let commandArgs = "-f concat -safe 0 -i \(fileURL.path) -movflags use_metadata_tags -c copy -metadata creation_time=\"\(creationTime)\" -metadata create_date=\"\(creationTime)\" -y \(outputPath)"

-movflags use_metadata_tags をつけると良いという情報もありましたが、これもダメでした。

元のファイルのexif

複数ファイルが分割記録されているファイルの、1つ目のexifを見てみます。

  File Modification Date/Time     : 2023:09:07 07:17:03+09:00
  ...
  Create Date                     : 2023:09:07 07:11:41
  Modify Date                     : 2023:09:07 07:11:41
  ...

↑ この辺が日時に関連する情報かなと眺めていると

↓ Trackが分割されて情報がありそうで、

  Track Create Date               : 2023:09:07 07:11:41
  Track Modify Date               : 2023:09:07 07:11:41
  Track ID                        : 1
  Track Duration                  : 0:05:20
  Track Layer                     : 0
  Track Volume                    : 0.00%
  Matrix Structure                : 1 0 0 0 1 0 0 0 1
  Image Width                     : 3840
  Image Height                    : 2160
  Time Code                       : 3
  Media Header Version            : 0
  Media Create Date               : 2023:09:07 07:11:41
  Media Modify Date               : 2023:09:07 07:11:41
  Media Time Scale                : 24000
  Media Duration                  : 0:05:20

GPSの情報も延々出てきます。これは動画に対してどう移動したのかがわかるので、読み込めツールであればどういう軌跡をたどった記録なのか表示できるものです。

  GPS Measure Mode                : Unknown (0)
  GPS Date Time                   : 2023:09:06 21:52:53.115
  GPS Horizontal Positioning Error: 99.99
  GPS Latitude                    : 35 deg 18' 48.50" N
  GPS Longitude                   : 139 deg 32' 20.74" E
  GPS Altitude                    : 17.551 m
  GPS Speed                       : 0
  GPS Speed 3D                    : 0
  GPS Latitude                    : 35 deg 18' 48.50" N
  GPS Longitude                   : 139 deg 32' 20.74" E
  GPS Altitude                    : 17.551 m
  GPS Speed                       : 0
  GPS Speed 3D                    : 0
  GPS Latitude                    : 35 deg 18' 48.50" N
  GPS Longitude                   : 139 deg 32' 20.74" E
  GPS Altitude                    : 17.551 m
  GPS Speed                       : 0
  GPS Speed 3D                    : 0

実際は4万行以上のデータがありました。 gistに貼り付けました が、途中で切れてしまっていそうです。

結合されたファイルのexif

  File Size                       : 8.3 GB
  File Modification Date/Time     : 2023:09:07 11:48:11+09:00
  ...
  Create Date                     : 0000:00:00 00:00:00
  Modify Date                     : 0000:00:00 00:00:00

メディアの作成日? Media Create Dateはゼロになってしまっています。TrackやMediaは結合したファイル数分あります。つまり、Track IDが3まであるんですが、Media Durationは3つとも11分。結合後の時間も11分なので、なんか間違ってそうです…

  Media Create Date               : 0000:00:00 00:00:00
  Media Modify Date               : 0000:00:00 00:00:00
  Media Time Scale                : 24000
  Media Duration                  : 0:11:01

そして、末尾にもう一度 Creation TimeCreate Date が登場してしまっている!

これは、 -movflags use_metadata_tags の影響? movflagsを指定しないようにしたら、このCreation TimeとCreate Dateは出力されなくなりました。んんー?

  Handler Type                    : Metadata Tags
  Creation Time                   : "2023-09-07T02:48:11Z"
  Create Date                     : "2023-09-07T02:48:11Z"
  Encoder                         : Lavf59.27.100
  Image Size                      : 3840x2160
  Megapixels                      : 8.3
  Avg Bitrate                     : 100 Mbps
  Rotation                        : 0

ちなみに、ファイルの作成日時は別でいじっています。今まではこれを見てくれていた気がするのだが。Lightroomがmp4のCreate Dateをちゃんと見るようになったとか?

  var outputFile = URL(fileURLWithPath: outputPath)
  var values = URLResourceValues()
  values.creationDate = _creationDate
  values.contentModificationDate = _creationDate
  do {
      try outputFile.setResourceValues(values)
  } catch {
      // ...
  }

GoProのMedia情報をいじれそうなライブラリ GPMF

これは思いの外大変だぞ、つまり誰かライブラリを作ってるだろう、ということでちょっと探してみました。

詳細は見ずに、このライブラリが関係するんじゃないか? というところで力尽きました。

今回は、只見線の撮影でGoProを使ったので、GoProのメタ情報を残したまま、結合したものを残したいのです。

頑張るべきか、諦めるべきか、それが問題だー。

GPSはストリームとして入っていそう

超頑張ろうかなと思ったのだけれど、GPSの情報はストリームとして入っているようなので、コピーし損ねているストリームをコピーすれば良いんじゃないか? と思うような情報に辿り着きました。

以下のようなオプションを追加してみました。

  -map 0:v -map 0:a -map 0:3 -copy_unknown -tag:2 gpmd

参考: ffmpeg concat and preserve metadata streams

はい。これでGPSの情報は残りました。

※ Lightroomでは動画の位置情報を表示させることはできませんでした。本稿の後半で別macアプリを使って確認しています

exiftoolを使ってみる

GPS情報が入ったストリームはコピーできましたが、日時はダメでした。

さて、手動でexiftoolなら日時を変更できるか試してみます。

  $ exiftool -CreateDate="2023:09:09 05:17:15+09:00" GPFC0356.mp4

これで、Create Dateが変更されました。んー、CreateDateに対応するffmpegのキーはcreation_timeで良いはずなんだけど、なんなんだろう。

結局、ffmpegでファイルをコピーした後にexiftoolで日時を変更する処理を追加してしまいました。

TimeZoneは効かない

2023:09:09 05:17:15+09:00 を指定して設定、Lightroomで読み込もうとしてみても、9月9日のフォルダに取り込もうとする。

記録されているexifを見てみると、+09:00が捨てられて記録されている模様。

JSTで記録されているのを、UTCに変換してみよう。

  let dateFormatter = DateFormatter()
  dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
  dateFormatter.timeZone = TimeZone(identifier: "UTC")
  let utcDateStr = dateFormatter.string(from: _creationDate)

あれ?UTCにしたら午前9時前は前日になってしまう?もしかして…

ムキー。SDカードからのコピー、再エンコーディングしなくても遅いんじゃー。と叫びながらやり直しました。

最初は少し面倒だけど、便利

公式アプリで結合したら繋ぎ目でプチッというノイズが入るので助かります、というようなコメントをCLIツールを紹介したYouTubeのコメントでもらったりしています。

このGUI版はだいぶ便利なんじゃないかと思っているので、世の人が使えるようにしても良いかなと思うんですが、macアプリの配布はデベロッパーアカウントを取らないといけなかったりするのでどうしようかなと。

特に、CLIツールを使おうという人はある程度頑張ってくれる人だと思うので、別途ffmpegやexiftoolのインストールが必要なのは気にならないと思うのですが、GUI版はちょっと違うかもしれない。いうあたりまで考えると、どうしたもんかなー

とりあえず自分の分は ~/Library/Developer/Xcode/DerivedData/ からそれっぽいフォルダ(今回は GoProFileMergeAndCopy-fzxbctwhwftjssfaelmtbixcyafy だった)の中の Build/Products/Debug/ にある GoProFileMergeAndCopy.app をデスクトップにコピって使っている。毎回Xcodeを起動するの面倒なんで

軌跡を表示するアプリ「軌跡」で確認

無料のmacアプリでgpxを読み込んでルートを表示できるアプリがありましたので、確認してみました。

gpxを取り出す準備

goで書かれたツールは古く、インストールさえ困難になっていました。

Python3で良い感じにしてくれるツールがあったので、これを使ってgpxを取り出します。

gopro2gpxのREADMEに書かれている通りにインストールをします。と言いつつ、その前にvenvを作ります。

  $ python3 -m venv ~/envs/gpx
  $ source ~/envs/gpx/bin/activate
  $ pip install gopro2gpx
  (ここまで、仮想環境の用意)

  $ pip install git+https://github.com/juanmcasillas/gopro2gpx
  $ rehash

これで、gopro2gpxコマンドが使えるようになりました。rehash使えなくて、gopro2gpxも見つからなかったら、ターミナルを起動し直して、 source ~/envs/gpx/bin/activate すれば良いです。

設定ファイルにffmpegとffprobeのパスを設定します。私はbrewでffmpegをインストールしているので、以下のように設定しました。

  $ cat ~/.config/gopro2gpx.conf
  [ffmpeg]
  ffmpeg = /opt/homebrew/bin/ffmpeg
  ffprobe = /opt/homebrew/bin/ffprobe

結合前のファイル(複数のファイルのうちの4GBのファイル1つ)を指定して実行すると、pgxとklmファイルが生成されます。

$ gopro2gpx -s -vvv GX010374.MP4 ORG374
$ gopro2gpx -s -vvv GX010374.MP4 ORG374

結合前のファイルからも生成します。

$ gopro2gpx -s -vvv GPFC374.MP4 GPFC374

4つファイルが出来上がりました。

  $ ls
  GPFC374.gpx GPFC374.kml     ORG374.gpx      ORG374.kml

軌跡で見てみる

軌跡 アプリでgpxファイルを読み込みます。

まずは、結合前のmp4ファイルから取り出したorg374.gpxを読み込んでみます。

只見線の会津西方付近まで進んでいます。

結合前。進行方向(左下)は会津西方まで

次に、連結したmp4ファイルから取り出したgpxファイルを読み込んでみます。

同じところから始まって会津宮下まで進んでいます。実際の動画も会津宮下駅に到着するところまでなので、あっていそうです!

結合後。進行方向(左下)は会津宮下まで

まとめ

ちょっとおかしくなっているところはありますが、GPS情報を保ったまま再エンコ無しで最速取り込みできるようになりました。

GUIのGoPro動画結合ツールでGPXの生成まで行うようにするかどうかは今後考えます。とりあえず動画ファイルに必要な情報が残っていれば後からどうにでもなりますので。

Prev Entry

Next Entry