Все страницы форматов ↓
Графика и медиа

Smacker / ZRB — видеоролики

Источник: coreprime/kbot @ 0ab97bf · Редактировать на GitHub

Вступительный ролик, брифинги миссий и финальные ролики Total Annihilation — это видео RAD Game Tools Smacker. Они хранятся под двумя разными расширениями:

Расширение Где используется Примечания
.smk Обычные инструменты Smacker Стандартный формат RAD.
.zrb Полезная нагрузка TA в data/*.zrb Cavedog переименовала файлы Smacker в .zrb, чтобы отбить охоту к случайному извлечению. Двоичное содержимое побайтно идентично.

FFmpeg декодирует Smacker сам, и kbot использует его как движок преобразования Smacker → MP4. В обратную сторону не преобразует ничто: в стандартном FFmpeg нет ни кодировщика, ни мультиплексора Smacker, а в kbot нет модуля записи Smacker. Ролики SMK2 для TA делают инструментами Smacker от RAD Game Tools.

Tip

Попробуйте сами.

kbot zrb info     data/1.zrb               # header summary
kbot zrb to-mp4   data/1.zrb intro.mp4     # decode to a 640x480 MP4 (requires ffmpeg)
kbot zrb from-mp4 intro.mp4 out.zrb        # reports that no Smacker encoder exists

Из Go. Используйте formats/smacker:

import "github.com/coreprime/kbot/formats/smacker"

r, _ := smacker.OpenReader("data/1.zrb")
defer r.Close()
fmt.Println(r.Width(), r.Height(), r.FrameCount(), r.FrameRate())
_ = smacker.ConvertToMP4("data/1.zrb", "intro.mp4")

Что лежит в установке TA

$ ls $(kbot ctx path)/data/*.zrb
1.zrb  2.zrb  3.zrb  4.zrb  5.zrb

Каждый пронумерованный файл — это ролик: оригинальная вступительная сцена «ARM против CORE», брифинги миссий и т. д. Кадры хранятся в разрешении 640 × 240 с установленным флагом чересстрочности, поэтому игра показывает их в разрешении 640 × 480, где каждая вторая строка чёрная, с частотой 30 fps. kbot zrb to-mp4, инструмент MCP zrb_to_mp4 и видеоплеер студии (а также его миниатюры) показывают их точно так же.


Заголовок (не меньше 104 байт)

Заголовок Smacker содержит сигнатуру, геометрию, число кадров, параметры звука и размеры таблиц указателей. Прочитать его несложно, но тело декодируется через деревья Хаффмана на уровне битов, поэтому kbot не берётся за тело и использует FFmpeg.

typedef struct {
    uint32 Signature;        // 'SMK2' = 0x324B4D53 or 'SMK4' = 0x344B4D53
    uint32 Width;
    uint32 Height;
    uint32 Frames;
    int32  FrameRate;        // See below — sign-encoded
    uint32 Flags;
    uint32 AudioSize[7];
    uint32 TreesSize;        // Huffman tree section length
    uint32 MMapSize;
    uint32 MClrSize;
    uint32 FullSize;
    uint32 TypeSize;
    uint32 AudioRate[7];     // packed: rate in bits 0-23, flags in bits 24-31
    uint32 dummy;            // 4-byte reserved; the header ends here (104 bytes)
    // …followed by one entry per frame, plus one for the ring frame
    // when Flags bit 0 is set:
    uint32 FrameSizes[Frames (+1)];
    uint8  FrameTypes[Frames (+1)];
    uint8  HuffmanTrees[TreesSize];
} SmackerHeader;

Биты Flags: 0x01 — кольцевой кадр (один дополнительный кадр после последнего, для зацикливания), 0x02 — чересстрочность (показывается с удвоенной высотой, каждая вторая строка чёрная), 0x04 — удвоение (показывается с удвоенной высотой, каждая строка повторяется). Если установлены и 0x02, и 0x04, ролик показывается с той высотой, с которой хранится.

Как декодировать частоту кадров

Знак FrameRate выбирает одну из двух кодировок:

Значение Смысл
> 0 Миллисекунды на кадр: fps = 1000 / FrameRate.
< 0 Стотысячные доли секунды на кадр: fps = 100_000 / abs(FrameRate).
0 Частота не задана — kbot использует 15 fps.

Для 30 fps обычно встречается -3333 (≈ -100000/30).

Варианты сигнатуры

  • SMK2 — исходный формат Smacker. Его используют почти все ролики Cavedog.
  • SMK4 — расширенный формат с улучшенным сжатием из более новых инструментов RAD. TA 3.1c воспроизводит только SMK2.

kbot читает оба (и отмечает файл SMK4), FFmpeg декодирует оба.

Звуковые дорожки

До 7 звуковых дорожек. Каждое слово AudioRate[i] упаковывает частоту дискретизации (биты 0–23) и флаги дорожки (биты 24–31): 0x80 — сжатая, 0x40 — присутствует, 0x20 — 16 бит (иначе 8 бит), 0x10 — стерео (иначе моно). Игра использует дорожку, только если установлен её бит присутствия, какой бы ни была её частота. Отдельной таблицы флагов нет: семь слов после заголовка — это таблица размеров кадров.

Note

В файлах ZRB от Cavedog одна дорожка, в слоте 0: слово 0xD0005622 — присутствует, 22 050 Гц, стерео, 8 бит, сжатая. Остальные шесть слотов обнулены. kbot zrb info и инструмент MCP zrb_info выводят только присутствующие дорожки.


Миф о «зашифрованных данных»

Среди моддеров распространено мнение, что файлы .zrb — зашифрованный вариант Smacker. Это не так. Если переименовать 1.zrb в 1.smk, файл воспроизводится в любом инструменте, который понимает Smacker (инструменты RAD Bink/Smacker, FFmpeg, VLC). Единственной маскировкой Cavedog было само расширение.

# Equivalent — try both
ffplay data/1.zrb
cp data/1.zrb /tmp/intro.smk && ffplay /tmp/intro.smk

Цепочки преобразования

kbot zrb to-mp4 читает заголовок, а затем FFmpeg декодирует ролик в H.264 (CRF 18) и AAC так, как его показывает игра: с высотой отображения (чересстрочный ролик 640×240 превращается в 640×480, где каждая вторая строка чёрная), с квадратными пикселями, и останавливается на числе кадров из заголовка (кольцевой кадр не показывается).

Флаг Действие
--line-double Заполнять дополнительные строки чересстрочного ролика повтором каждой сохранённой строки, а не чёрным.
--stored-height Сохранить высоту кадра, с которой он хранится (640×240).

Видеоплеер студии использует то же преобразование, а его миниатюры сохраняют пропорции экрана 4:3 (128×96, строки удвоены).

Important

Пути MP4 → Smacker нет. В стандартном FFmpeg нет кодировщика Smacker (smackvid / smackaud) и мультиплексора, а в kbot нет модуля записи Smacker. Именно об этом и сообщают kbot zrb from-mp4 и инструмент MCP zrb_from_mp4 (FFmpeg они пробуют, только если тот перечисляет и кодировщик smackvid, и мультиплексор smk). Ролики SMK2 для TA делайте инструментами Smacker от RAD Game Tools.


Типичные размеры

Ресурс Разрешение Кадров Длительность Размер файла
Вступительный ролик (data/1.zrb) 640 × 240 (показывается 640 × 480) 599 ~20 с ~7 МБ
Остальные ролики (data/2.zrb–5.zrb) 640 × 240 (показывается 640 × 480) — — 10–41 МБ

Подводные камни

Warning

AudioRate — упакованное слово, а не частота. Если прочитать слово из оригинальных файлов 0xD0005622 как обычное число, получится 3 489 682 978 «Гц». Для частоты маскируйте младшие 24 бита, а присутствие проверяйте по биту 0x40000000. Инструменты, которые читают после заголовка ещё семь слов «флагов», на самом деле читают таблицу размеров кадров.

  • Smacker — это не Bink. RAD сначала выпустила Smacker, а потом Bink как его преемника. TA использует только Smacker, TA: Kingdoms перешла на Bink. Не открывайте файлы .bik через kbot zrb — используйте kbot bik.
  • Деревья Хаффмана SMK4 несовместимы с декодерами SMK2. FFmpeg справляется с обоими, но старые сторонние библиотеки могут и не справиться.
  • В роликах из комплекта игры хранится -3333 (100 000 / 3 333 ≈ 30,003 fps).
  • Высота хранения — не высота показа. Проверяйте флаги чересстрочности и удвоения: оригинальные ролики, воспроизведённые в 640×240, сплющены до половины высоты.
  • Переименование .zrb ↔ .smk безвредно, но игра ожидает .zrb в каталоге data/. Не отдавайте движку файлы с именами .smk.

См. также

  • Bink — кодек-преемник, который TA: Kingdoms использует вместо Smacker.
  • HPI — архив-обёртка, в котором поставляются файлы ZRB.
  • Глоссарий — frame rate (частота кадров), signature (сигнатура).