Данная статья предназначена для тех, кто заинтересован в сохранении воспроизводимости своих записей на случай внезапного системного сбоя. Далее будут описаны харатктерные особенности целых и поврежденных файлов, записанных в нескольких наиболее известных форматах как MP4, MOV, MKV, FLV, рассмотрены особенности изменений в структуре файлов при различных условиях записи.
Целые
MP4
Данная группа файлов была записана в штатных условиях без угрозы внезапной остановки записи.
Можно заметить, что файл состоит из четырех атомов корневого уровня ftyp, free, mdat, moov, в соответствии со структурой описанной в официальной спецификации формата медиаконтейнера MP4.
Все величины в таблице представлены в байтах. В первом столбце отображено начало блока памяти для каждого атома, во втором - размер данных занимаемых атомом. Таким образом, расположение каждого следующего атома в памяти складывается из размеров всех предыдущих атомов.
Содержимое moov атома имеет особо важное значение для воспроизведения видеоматериала, так как именно в этом месте находится описание информации о том как файл должен быть расшифрован. Для расшифровки файла, чтобы его воспроизвести необходимо установить однозначное соответствие между данными и способами их чтения. Поэтому необходимо знать количество потоков, какой формат данных содержат потоки, какие кодеки совместимы для декодирования. Следует обратить внимание на расположение moov атома в памяти файла. Обычно он расположен в конце файла, что не всегда полезно и безопасно при записи. По этой причине не рекомендуется вести запись в MP4 из-за угрозы получения невоспроизводимого файла в результате внезапного прекращения записи. Такая ситуация возможна при системных сбоях, потере питания и в случае непредвиденного завершения процесса записывающего ПО.
Метаданные извлекаются с помощью ffprobe следующим образом.
ffprobe -hide_banner video.mp4 2> mp4.txt
MOV
В структуре MOV нет особых различий со структурой MP4, файл все также состоит из четырех атомов корневого уровня, но вместе атома free используется атом wide равный ему по размеру. В таких атомах содержится информация о неиспользуемом пространстве памяти. Узнать подробнее про формат медиаконтейнера MOV можно в официальной спецификации формата медиаконтейнера MOV.
В MOV по аналогии с MP4 все метаданные находятся в moov атоме в конце файла.
Метаданные извлекаются с помощью ffprobe следующим образом.
ffprobe -hide_banner video.mov 2> mov.txt
MKV
Структура MKV уже была описана ранее в официальной спецификации формата медиаконтейнера MKV. Основное отличие от прошлых двух контейнерных форматов в том, что данные по умолчанию записываются небольшими фрагментами, вместо одного общего блока информации в случае с mdat для MP4 и MOV. Такая особенность позволяет избавиться от проблемы критического повреждения файлов в случае внезапного прекращения записи, так как метаданные содержатся в каждом отдельном фрагменте.
Метаданные извлекаются с помощью ffprobe следующим образом.
ffprobe -hide_banner video.mkv 2> mkv.txt
FLV
Структура MKV уже была описана ранее в официальной спецификации формата медиаконтейнера FLV. В хранении информации используется идентичный способ с MKV. Видео располагается в памяти фрагментами, но содержимое атомов отличается.
Метаданные извлекаются с помощью ffprobe следующим образом.
ffprobe -hide_banner video.flv 2> flv.txt
Поврежденные
MP4
Если запись была внезапно прервана есть довольно большая вероятность получить невоспроизводимый файл на выходе.
Подробнее узнать причину ошибки можно узнать посмотрев логи через ffprobe в консоли
ffprobe -v error video.mp4 2> mp4_error.txt
Лог ошибки выглядит следующим образом для файла
По ошибке “moov atom not found” можно понять, что метаинформацию извлечь не получится, так как не найден moov атом. Дело в том, что запись закончилась раньше, чем планировалось и moov атом физически не был записан в память. Последний доступный атом в данном случае будет mdat.
Соответственно, если попробовать достать любую метаинформацию файла, то вывод будет пустой
Например,
ffprobe -hide_banner video.mp4 2> mp4.txt
MOV
В MOV файлах будет наблюдаться похожая ситуация, но как и в прошлый раз разница будет только в названии и размере некоторых корневых атомов структуры. Сам файл воспроизводиться не будет.
ffprobe -v error video.mov 2> mov_error.txt
Moov атом здесь не наблюдается, как и в MP4, что не позволяет извлечь метаинформацию
ffprobe -hide_banner video.mov 2> mov.txt
MKV
Записанный в условиях внезапной остановки записи MKV файл пострадает меньше по сравнению с MP4 или MOV. Его можно будет воспроизвести, но нельзя перемотать и узнать продолжительность в некоторых плеерах. В этом можно убедиться после извлечения метаданных. Значению поля Duaration соответствует N/A, это значит, что оно не было определено. Также отсутствуют значения длительности для видео и аудио потоков и битрейт.
Вывод метаданных для поврежденного MKV файла будет сопровождаться сообщением об преждевременном окончании файла, но в данном случае это повлияет лишь на последний фрагмент в течение записи которого была прервана запись.
FLV
Поврежденный FLV файл воспроизводится, но так же не имеет определенного значения длины, записанного в поле Duration, как и поврежденный MKV файл, тем не менее информация о начальной отметке времени осталась. Что касается битрейта, то его все также нет. Дело в том, что значения полей Duration и Bitrate вычисляются в самом конце, а не пересчитываются каждый раз после окончания записи каждого отдельного фрагмента, так как это спровоцировало бы дополнительную нагрузку на систему.
Вывод поломанного FLV файла содержит несколько больше информации о повреждениях. Видно на каком именно пакете прервалась запись и к какому потоку он относился. В данном случае проблема была обнаружена в момент декодирования пакета в потоке видео с dts = 9734. Более вероятно возникновение ошибки именно в видео потоке, так как обычно объем видеоданных занимает в разы больше места, чем аудио, соответственно и времени на его расшифровку тратится пропорционально больше.
DTS (decoding time stamp) - время декодирования опорного кадра, который требуется для отображения текущего в базовых единицах. Может совпадать с PTS (presentation time stamp) если текущий кадр опорный. Как правило базовая единица задается в виде дроби с числом тактов в числителе и частотой тактового генератора в знаменателе. В итоге в процессе расшифровки декодировщик не может получить доступ к объекту в памяти, потому что его не существует и выполнение чтения заканчивается ошибкой.
Записанные с предварительными настройками
Предварительно настроенная запись отличается от обычной, тем что в качестве дополнительной настройки используется параметр faststart, который помогает предотвратить проблему критического повреждения MP4 и MOV файлов путем перемещения moov атома в начало файла. Для MKV и FLV данный параметр не имеет большого смысла, так как в их структуре отсутствует отдельный атом с общими метаданными, как moov.
MP4
Теперь подверженный повреждению файл в условиях внезапной остановки записи удалось оставить воспроизводимым и читаемым. На изображении снизу можно изучить структуру полученного после записи файла. На этот раз moov атом был записан в начале файла после ftyp. Раньше он располагался в самом конце после атома mdat.
Метаданные вновь читаются, причем значения для полей duration и bitrate определены, несмотря на то, что запись была прервана внезапно.
MOV
В структуре MOV файла произошли изменения в порядке записи корневых атомов, как и в MP4. Moov атом остался неповрежденным и расположен в начале файла. Воспроизведение файла не нарушено.
Дополнительно убедиться в целостности файла можно после извлечения метаданных
MKV
Для MKV файлов особого эффекта параметр “faststart” не имеет, файл имеет повреждения, полученные в результате внезапной остановки записи.
Файл возможно воспроизвести, но как и в прошлый раз без значений длительности и битрейта. Вывод метаданных сопровождается ошибкой.
FLV
Никаких особых изменений в лучшую сторону для flv файла использованный параметр не дал. Все старые проблемы остались.
Длительность в результате записи осталась нулевой, битрейт неизвестен, тем не менее файл воспроизводится.
Фрагментированные
Еще один вариант предварительной настройки записи, который позволяет добиться фрагментированной записи в файл вместо хранения всей информации в едином атоме.
empty_moov приведет к фрагментации вывода на 100%; без этого первый фрагмент будет мультиплексирован, как короткий фильм (с использованием moov), за которым следуют остальные медиафайлы во фрагментах
frag_keyframe вызывает фрагментированный вывод
MP4
Использовав дополнительные параметры, удалось сохранить воспроизводимость файла в условиях внезапной остановки записи. В структуре файла наблюдаются заметные изменения. Moov атом расположен в начале файла, далее следует последовательность из двух повторяющихся практически до конца атомов moof и mdat. В этих двух атомах содержится вся необходимая информация о каждом отдельном фрагменте видео. Moof атом - аналог moov для фрагмента записи, mdat - атом содержащий потоки. Завершается файл атомом mfra.
C извлечением метаданных нет особых в данном случае. В метаданных присутствует длительность, тем не менее в некоторых плеерах отсутствует возможность перемотки и не отображается длительность.
MOV
Что касается структуры MOV файла, то она так же сильно изменена и больше напоминает структуру MKV или FLV файлов из-за последовательности фрагментов, записанных в атомы moof и mdat.
Повреждений метаданных в данном случае не наблюдается.
MKV
Особого эффекта или изменений в худшую или лучшую сторону не наблюдается.
FLV
Особого эффекта или изменений в худшую или лучшую сторону не наблюдается.
Дополнительная информация
Мультиплексирование в obs осуществляется при помощи ffmpeg, соответственно все указанные в данном примере настройки имели бы следующий вид:
ffmpeg -i input <encoding parameters> -movflags +frag_keyframe+empty_moov out.[mp4/mov]
Пример создания фрагментированного MP4 файла (fMP4) из стандартного MP4 файла
ffmpeg -i video.mp4 -g 52 -c:a aac -c:v libx264 -f mp4 -movflags frag_keyframe+empty_moov fragmented_video.mp4
Альтернативный вариант предварительной настройки записи, который позволяет добиться фрагментированной записи в файл вместо хранения всей информации в едином атоме.
empty_moov приведет к фрагментации вывода на 100%; без этого первый фрагмент будет мультиплексирован, как короткий фильм (с использованием moov), за которым следуют остальные медиафайлы во фрагментах
separate_moof инициирует создание отдельного атома moof (фрагмента видео) для каждого потока. Обычно пакеты для всех потоков записываются в moof atom (что немного эффективнее), но с этой установленной опцией мультиплексор записывает одну пару moof/mdat для каждой потоков, что упрощает разделение дорожек.
frag_keyframe вызывает фрагментированный вывод
omit_tfhd_offset отменяет запись абсолютного значения base_data_offset в атомах tfhd. Это позволяет избежать привязки фрагментов к абсолютным позициям байтов в файле/потоках.
MP4
Следующие настройки позволяют создавать фрагментированный MP4 (fMP4), который вы сможете просмотреть во время преобразования. Однако для просмотра будут доступны только фрагменты, полностью закодированные на момент запуска файла. Чтобы просмотреть фрагменты, закодированные после этой точки, вам придется перезагрузить источник просмотра.
Аналогично прошлому примеру с фрагментацией файл состоит из последовательности атомов корневого уровня mdat и moof и имеет moov атом вначале.
Таким образом, данный способ наравне с предыдущим позволяет избежать повреждения метаданных файла в условиях внезапного прекращения записи, что фактически гарантирует возможность дальнейшего воспроизведения файла.
MOV
Эти настройки также применимы в случае с MOV файлами и на выходе дают сравнимый результат
Как результат здесь так же сохраненные метаданные и нормальная воспроизводимость файла
MKV
Особого эффекта или изменений в худшую или лучшую сторону не наблюдается.
FLV
Особого эффекта или изменений в худшую или лучшую сторону не наблюдается.
Дополнительная информация
Мультиплексирование в obs осуществляется при помощи ffmpeg, соответственно все указанные в данном примере настройки имели бы следующий вид:
ffmpeg -i input <encoding parameters> -movflags +frag_keyframe+separate_moof+omit_tfhd_offset+empty_moov out.[mp4/mov]
Вывод
Чтобы уменьшить вероятность утраты доступа к записанным видеофайлам лучше задуматься сразу над тем, как избежать негативных последствий при возникновении аппаратных или системных проблем на записывающем устройстве. Сделать это можно, выбрав один из более отказоустойчивых форматов записи, как MKV/FLV или, если выходной формат принципиально важен, то воспользоваться одним из методов предотвращения крашей в MP4/MOV из статьи. Восстанавливать убитый файл, гораздо труднее и не всегда возможно. Для тех, кто уже столкнулся с этой проблемой и еще ищет решения возможно будет полезна следующая статья, посвященная теме восстановления MP4/MOV файлов.
Полезные источники
Комментарии (4)
arteast
04.06.2022 08:35+4В случае с
movflags=faststart
ffmpeg боксmoov
записывает в самом конце записи, так же как и в случае без этого флага (внутри этого бокса находится информация о том, где именно находится каждый кадр видео и аудио и какую длительность имеет каждый кадр - соответственно, даже размер самого moov неизвестен до тех пор, пока запись не завершена). В случае с faststart перед записьюmoov
все записанные данные еще будут "подвинуты" в файле на размер этого самогоmoov
, т.е. файл будет еще раз прочитан и перезаписан целиком.Если под "внезапной остановкой" понимается "нажать q в ffmpeg" или что-то похожее в OBS, то
moov
будет штатно записан в обоих случаях. Если же понимать что-то более серьезное, тоmoov
не будет в обоих случаях, и файл будет невозможно проиграть. faststart хорош тем, что если уже потом, после записи, файл удалось прочитать или скачать частично, то имеющаяся часть будет работать нормально.Фрагментированный режим работы сохраняет метаданные дорожек (кроме длительности) сразу в
moov
, а данные и метаданные кадров сохраняет небольшими кусками, что действительно позволяет сохранить большую часть данных даже при аварийном завершении работы.
Am1GO
04.06.2022 11:12+3Для
mp4
/m4v
/mov
/3gp
иm4a
есть две утилиты (точнее, одна и её форк, который вполне можно считать отдельной):Для использования утилит необходимо иметь повреждённое видео (с телефона/коптера/другого видеорекордера), а также неповреждённое видео с того же аппарата, записанное с такими же настройками и, крайне желательно, такой же длительности.
В случае соблюдения упомянутых условий, восстанавливаемость видео (стоит попробовать обеими утилитами) достигала 100%, т.е. мне удавалось починить все
mp4
видео (в других форматах не пробовал), запись которых была прервана из-за зависания рекордера/креша коптера/других аппаратных проблем.
qw1
06.06.2022 15:10Как я понимаю, наиболее устойчивый к повреждениям контейнер — это ts, в котором вещают цифровое телевидение и twitch. Там можно с любого места смотреть. Но вот операция seek подтормаживает на большом файле, хотя и приемлемо для практического использования. Смена контейнера ts↔mp4 возможна без перекодировки, копированием потоков.
qw1
06.06.2022 15:14Рис. 32 Структура фрагментированного MP4 файла
Интересно, а что это за программа-браузер?
arteast
В случае с
movflags=faststart
ffmpeg боксmoov
записывает в самом конце записи, так же как и в случае без этого флага (внутри этого бокса находится информация о том, где именно находится каждый кадр видео и аудио и какую длительность имеет каждый кадр - соответственно, даже размер самого moov неизвестен до тех пор, пока запись не завершена). В случае с faststart перед записьюmoov
все записанные данные еще будут "подвинуты" в файле на размер этого самогоmoov
, т.е. файл будет еще раз прочитан и перезаписан целиком.Если под "внезапной остановкой" понимается "нажать q в ffmpeg" или что-то похожее в OBS, то
moov
будет штатно записан в обоих случаях. Если же понимать что-то более серьезное, тоmoov
не будет в обоих случаях, и файл будет невозможно проиграть. faststart хорош тем, что если уже потом, после записи, файл удалось прочитать или скачать частично, то имеющаяся часть будет работать нормально.Фрагментированный режим работы сохраняет метаданные дорожек (кроме длительности) сразу в
moov
, а данные и метаданные кадров сохраняет небольшими кусками, что действительно позволяет сохранить большую часть данных даже при аварийном завершении работы.