Как я могу без потерь объединить два файла MP4 и сохранить информацию телеметрии (GoPro GPMF) с помощью FFmpeg?

Вопрос или проблема

Можно без потерь объединить два MP4 файла с помощью FFmpeg следующим образом:

ffmpeg -safe 0 -f concat -i list.txt -c copy output.mp4

с list.txt:

file 'C:\file1.mp4'
file 'C:\file2.mp4'

Однако, если входные файлы C:\file1.mp4 и C:\file2.mp4 содержат телеметрическую информацию, в output.mp4 она отсутствовать будет, как может подтвердить ffprobe. В моем случае,
C:\file1.mp4 и C:\file2.mp4 имеют данные телеметрии в формате GPMF™, используемые в камерах GoPro®.

Как я могу без потерь объединить два MP4 файла и сохранить телеметрическую информацию с помощью FFmpeg?


Вывод ffprobe для одного из входных файлов с телеметрической информацией:

C:\>ffprobe GX010013.MP4
ffprobe version 5.0.1-full_build-www.gyan.dev Copyright (c) 2007-2022 the FFmpeg developers
  built with gcc 11.2.0 (Rev7, Built by MSYS2 project)
  configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-sdl2 --enable-libdav1d --enable-libdavs2 --enable-libuavs3d --enable-libzvbi --enable-librav1e --enable-libsvtav1 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxvid --enable-libaom --enable-libopenjpeg --enable-libvpx --enable-mediafoundation --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-liblensfun --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-d3d11va --enable-dxva2 --enable-libmfx --enable-libshaderc --enable-vulkan --enable-libplacebo --enable-opencl --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libilbc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprint
  libavutil      57. 17.100 / 57. 17.100
  libavcodec     59. 18.100 / 59. 18.100
  libavformat    59. 16.100 / 59. 16.100
  libavdevice    59.  4.100 / 59.  4.100
  libavfilter     8. 24.100 /  8. 24.100
  libswscale      6.  4.100 /  6.  4.100
  libswresample   4.  3.100 /  4.  3.100
  libpostproc    56.  3.100 / 56.  3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'GX010013.MP4':
  Metadata:
    major_brand     : mp41
    minor_version   : 538120216
    compatible_brands: mp41
    creation_time   : 2022-07-16T20:36:19.000000Z
    firmware        : H21.01.01.42.00
  Duration: 00:08:54.55, start: 0.000000, bitrate: 59971 kb/s
  Stream #0:0[0x1](eng): Video: hevc (Main) (hvc1 / 0x31637668), yuvj420p(pc, bt709), 5312x2988 [SAR 1:1 DAR 16:9], 59702 kb/s, 59.94 fps, 59.94 tbr, 60k tbn (default)
    Metadata:
      creation_time   : 2022-07-16T20:36:19.000000Z
      handler_name    : GoPro H.265
      vendor_id       : [0][0][0][0]
      encoder         : GoPro H.265 encoder
      timecode        : 20:35:05:32
  Stream #0:1[0x2](eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 189 kb/s (default)
    Metadata:
      creation_time   : 2022-07-16T20:36:19.000000Z
      handler_name    : GoPro AAC
      vendor_id       : [0][0][0][0]
      timecode        : 20:35:05:32
  Stream #0:2[0x3](eng): Data: none (tmcd / 0x64636D74) (default)
    Metadata:
      creation_time   : 2022-07-16T20:36:19.000000Z
      handler_name    : GoPro TCD
      timecode        : 20:35:05:32
  Stream #0:3[0x4](eng): Data: bin_data (gpmd / 0x646D7067), 60 kb/s (default)
    Metadata:
      creation_time   : 2022-07-16T20:36:19.000000Z
      handler_name    : GoPro MET
      timecode        : 20:35:05:32
Unsupported codec with id 0 for input stream 2
Unsupported codec with id 98314 for input stream 3

https://github.com/gopro/gpmf-parser дает обзор структуры MP4 от GoPro:

MP4 файлы, содержащие телеметрию, будут иметь минимум четыре трека: Видео, аудио, временной код и телеметрию (GPMF). Пятый трек (‘SOS’) используется для восстановления файлов в HERO4 и HERO5 и может быть проигнорирован.

Структура файла:

  ftyp [тип ‘mp41’]
  mdat [все данные для всех треков перемешаны]
  moov [вся информация о заголовке/индексе]
    ‘trak’ подтип ‘vide’, имя “GoPro AVC”, данные видео H.264 
    ‘trak’ подтип ‘soun’, имя “GoPro AAC”, данные аудио AAC
    ‘trak’ подтип ‘tmcd’, имя “GoPro TCD”, начальный временной код (время суток в кадрах с полуночи)
    ‘trak’ подтип ‘meta’, имя “GoPro MET”, телеметрия GPMF

Из этого поста SO от Эндрю, необходимо добавить атрибуты: -map 0:v -map 0:a -map 0:3 -copy_unknown -tag:2 gpmd

Полная команда:

ffmpeg -safe 0 -f concat -i list.txt -map 0:v -map 0:a -map 0:3 -copy_unknown -tag:2 gpmd -c copy output.mp4

Обратите внимание, что https://community.gopro.com/s/question/0D53b00008BtrlQCAR/merge-files-and-keep-telemetry?language=en_US сообщает о некоторых проблемах:

ReelSteady Go отказывается читать данные.

Я предполагаю, что это связано с тем, что ffmpeg грубо объединяет поток gpmd, поскольку мы используем -copy_unknown, потому что ffmpeg не имеет представления, что такое gpmd.

Тем не менее, https://goprotelemetryextractor.com/free/ похоже, может правильно извлекать информацию GPX.


Бонусный скрипт для перечисления всех mp4 файлов в папке и создания list.txt:

@echo off
(for %%f in (*.mp4) do echo file '%%f') > list.txt

или чтобы убедиться, что mp4 файлы отсортированы в лексикографическом порядке:

@echo off
(for /f "delims=" %%f in ('dir /b /o:n *.mp4') do echo file '%%f') >  list_videos.txt

(/o:n указывает на сортировку по имени).

Пример вывода:

file '20240914_121500.mp4'
file '20240914_122513.mp4'
file '20240914_124099.mp4'
file '20240914_125165.mp4'

Ответ или решение

Конкатенация видеофайлов формата MP4 без потерь и сохранение телеметрической информации, такой как GPMF, требует особого подхода. Рассмотрим, как этого добиться с помощью FFmpeg.

1. Подход к решению задачи

Чтобы объединить два MP4 файла без потерь и сохранить GPMF телеметрию, можно использовать следующий подход:

  • Создать текстовый файл list.txt, содержащий пути к файлам, которые необходимо объединить.
  • Использовать специальный набор параметров в команде FFmpeg для того, чтобы указать, какие потоки нужно сохранить.

2. Создание файла списка

Для начала, создадим файл list.txt, который будет содержать пути к вашим MP4 файлам. В Windows это можно сделать с помощью следующей команды в командной строке:

@echo off
(for %%f in (*.mp4) do echo file '%%f') > list.txt

Это создаст файл list.txt с перечислением всех MP4 файлов в текущей директории. Если вам нужно отсортировать файлы по имени, используйте:

@echo off
(for /f "delims=" %%f in ('dir /b /o:n *.mp4') do echo file '%%f') > list_videos.txt

3. Команда для конкатенации

Теперь, чтобы объединить файлы и сохранить GPMF, воспользуйтесь следующей командой:

ffmpeg -safe 0 -f concat -i list.txt -map 0:v -map 0:a -map 0:3 -copy_unknown -tag:2 gpmd -c copy output.mp4

4. Объяснение параметров

  • -safe 0 — позволяет использовать абсолютные пути в файле списка.
  • -f concat — указывает формат для конкатенации файлов.
  • -i list.txt — указывает входной файл, содержащий список файлов для конкатенации.
  • -map 0:v — выбирает видеопоток из первого файла.
  • -map 0:a — выбирает аудиопоток из первого файла.
  • -map 0:3 — выбирает третий поток (телеметрические данные GPMF).
  • -copy_unknown — позволяет копировать неизвестные потоки.
  • -tag:2 gpmd — задаёт тег для потока, чтобы он был распознан как GPMF.
  • -c copy — указывает на копирование всех потоков без перекодирования.

5. Возможные проблемы

Важно отметить, что иногда, после слияния, могут возникнуть проблемы с распознаванием GPMF данных. Например, некоторые программы (такие как ReelSteady Go) могут не считывать объединенные данные корректно. Однако другие инструменты, такие как GoPro Telemetry Extractor, могут успешно извлекать информацию GPX.

Заключение

Этот подход позволяет эффективно объединить несколько MP4 файлов, сохраняя при этом важную телеметрию GPMF. Применяйте указанные команды и настройки в зависимости от ваших потребностей. Если возникнут дополнительные вопросы или потребуется помощь в проблемах, связанных с GPMF, не стесняйтесь обращаться к сообществам или соответствующим ресурсам.

Оцените материал
Добавить комментарий

Капча загружается...