Как вручную изменить продолжительность поля в Matroska/ MKV
У меня есть один файл MKV, который не имеет допустимой продолжительности. Я хочу изменить этот параметр длительности вручную. Я прошел через эту спецификацию matroska, определенную на http://www.matroska.org/technical/specs/index.html
Если посмотреть на спецификацию для matroska, она содержит только идентификационные магические числа, но не определяет длину данных.
Как разобрать этот заголовок matroska, чтобы я получил поле продолжительности и изменил это поле?
4 ответа
Тип поля Длительность - float. Согласно документации это может быть 4 или 8 октетов. Чтобы узнать, какой это размер, нужно взглянуть на часть поля размера данных. Часть размера данных использует систему, подобную UTF-8. Это объясняется здесь.
Прошу прощения за длинное вступление, но ваш случай описан в конце заметки
Формат EBML в матроске:
https://github.com/ietf-wg-cellar/ebml-specification/blob/master/specification.markdown
спецификация матроски:
https://www.matroska.org/technical/elements.html
- mkv состоит из блоков,
- каждый блок имеет следующую структуру - состоит из этих 3 разделов -ID, DATA_LENGTH, DATA
ID - раздел идентификации поля
- подсчитайте нулевые биты до первого 1, чтобы оценить длину этого раздела в байтах, следующая часть до конца этого раздела байтов является идентификатором элемента матроски:
пример
1f 43 b6 75
0001 1111 -> первый полубайт определяет блок из 4 байт для ID (первый 1 в двоичной форме находится на четвертой позиции слева), а ID равен 0xF43b675 - и это означает кластер, может в спецификации матроски искать полный идентификатор 0x1f43b675
44 89
0100 0100 -> первый полубайт оценивает 2-байтовую секцию для идентификатора (первая 1 в двоичной форме находится на второй позиции слева), а идентификатор равен 0x489 - и это означает продолжительность, в спецификации матроски соответствует 0x4489
ДЛИНА ДАННЫХ - после раздела ID следует спецификация размера, а также BML
считать нулевые биты до первого 1, чтобы оценить длину в байтах этого раздела, следующая часть до конца этого (байтового) раздела - это длина данных в байтах
01 00 00 00 00 17 ff 0d
0000 0001 - для первого байта длина секции 8 байт, длина связанных данных 0x17ff0d
1000 1000 - длина секции 1 байт, длина связанных данных 8 байт
Образец комплекса
00000000 4d 80 A5 47 53 74 72 65 M..GSTRE
00000008 61 6D 65 72 20 6D 61 74 Amer Mat 00000010
72 6F 73 6B 61 6D 75 78 Roskamux 00000018 20 76 65 73 69 6F 6E
Версия
00002020202020202020 20 20 3E 31 2E 31 2E 31 2E 31 2E 31 2E 31 2E 31 31 30 2е 34 00 1.10.4.
4d 80
0100 1100 - определите идентификатор длиной 2 байта 0xD80 - это означает приложение или библиотеку Muxing
a5
1010 0101 - определить блок длиной 1 байт, область данных имеет 0x25 байт
Данные - Блок данных
00000000 47 53 74 72 65 M..GSTRE
00000008 61 6D 65 72 20 6D 61 74 Amer Mat 00000010
72 6F 73 6B 61 6D 75 78 Roskamux 00000018 20 76 65 72 73 69 6F 6E
версии
00000020 20 3E 31 3E 31 3E 31 3E 31 3E 31 3E 31. 30 2е 34 00 1.10.4.
Примечание:
- строки заканчиваются нулем, завершающий ноль включен в размер
- числа в обратном порядке, замена не требуется, поэтому 1000000 вы видите как 0f 42 40
см. пример
Масштаб отметки времени: 00000000 2a d7 b1 83 0f 42 40
2a
0010 1010 - три байта для идентификатора, идентификатор равен 0xAD7B1
83
1000 0011 - длина один байт, длина данных 3
0f 42 40 - данные в виде целого числа BE - 1000000
Продолжительность:
00000000 44 89 88 41 22 85 дд 26 Д..А"..&
00000008 35 c5 b5 5..
44
0100 0100 - два байта для секции ID (1 вторая позиция слева),ID 0x489, в спецификации матроски ищите 0x4489
88
1000 1000 - один байт для секции длины (1 в первой позиции слева), длина данных 8 байт (остальные 7 байт)
41 22 85 dd 26 35 c5 b5
восемь байт данных, эти данные имеют тип double, и дают 606958.57462900004 — 10 минут и 6.958574629 секунд (а VLC плеер показывает это время).
В С++:__int64 durationRaw = 0x412285dd2635c5b5;
двойная продолжительностьMiliSeconds = (двойная*)&durationRaw;
Matroska использует EBML (https://en.wikipedia.org/wiki/Extensible_Binary_Meta_Language) в качестве основы. Элементы EBML используют целые числа переменного размера, поэтому просто изменить числа не так просто. Вы можете использовать FFmpeg для повторного мультиплексирования MKV, который перезапишет заголовок с правильной продолжительностью.
Вы можете использовать ffprobe для получения продолжительности файла.mkv:
$ ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mkv
5012.640000
Смотрите: https://trac.ffmpeg.org/wiki/FFprobeTips