Как вручную изменить продолжительность поля в 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;

Итак, для вашего случая получите желаемое значение Duration, преобразуйте его в миллисекунды как двойное (8 байтов с плавающей запятой) и сохраните его двоичное представление в желаемом значении в блоке Duration.

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

Другие вопросы по тегам