Вопрос или проблема
Можно без потерь объединить два 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, не стесняйтесь обращаться к сообществам или соответствующим ресурсам.