すべての形式のページ ↓
グラフィックとメディア

Smacker / ZRB — カットシーンの動画

出典:coreprime/kbot @ 0ab97bf · GitHubで編集

Total Annihilationのイントロ、ミッションのブリーフィング、エンディングのムービーは、RAD Game ToolsのSmackerの動画です。2種類の拡張子で格納されています。

拡張子 使われる場所 備考
.smk 一般的なSmackerのツール RADの標準形式。
.zrb TAのdata/*.zrbのペイロード Cavedogは、気軽に取り出されないようにSmackerのファイルを.zrbに改名しました。バイナリの中身はバイト単位で同一です。

FFmpegはSmackerをネイティブにデコードでき、kbotはSmacker → MP4の変換エンジンとしてこれを使っています。逆方向に変換するものは何もありません。標準のFFmpegにはSmackerのエンコーダーもマルチプレクサーもなく、kbotにもSmackerのライターはありません。TA用のSMK2のムービーは、RAD Game ToolsのSmackerツールで作ります。

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で格納され、インターレースのフラグが立っているので、ゲームはこれを1行おきに黒い行を挟んだ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はインターレース(高さを2倍にし、1行おきに黒い行を挟んで表示)、0x04は倍化(高さを2倍にし、各行を繰り返して表示)です。0x02と0x04の両方が立っている場合、ムービーは格納された高さのまま表示されます。

フレームレートのデコード

FrameRateの符号によって、2つのエンコード方式のどちらかが選ばれます。

値 意味
> 0 1フレームあたりのミリ秒:fps = 1000 / FrameRate。
< 0 1フレームあたりの10万分の1秒: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がステレオ(なければモノラル)です。ゲームがトラックを使うのは、存在のビットが立っている場合だけです。レートの値は関係ありません。独立したフラグのテーブルはありません。ヘッダーの後に続く7つのワードは、フレームサイズのテーブルです。

Note

CavedogのZRBファイルは、スロット0にトラックが1つだけあります。ワードは0xD0005622で、存在、22,050 Hz、ステレオ、8ビット、圧縮を意味します。ほかの6つのスロットは0で埋められています。kbot zrb infoとMCPのzrb_infoツールは、存在するトラックだけを一覧表示します。


「データが暗号化されている」という誤解

MOD制作者の間では、.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のムービーは、1行おきに黒い行が入った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マルチプレクサーの両方がそこに一覧表示される場合だけです)。TA用のSMK2のムービーは、RAD Game ToolsのSmackerツールで作ってください。


典型的なサイズ

アセット 解像度 フレーム数 長さ ファイルサイズ
イントロのムービー(data/1.zrb) 640 × 240(表示は640 × 480) 599 約20秒 約7 MB
ほかのムービー(data/2.zrb〜5.zrb) 640 × 240(表示は640 × 480) — — 10–41 MB

注意点

Warning

AudioRateは詰め込まれたワードで、レートそのものではありません。ただの数値として読むと、製品版のワード0xD0005622は3,489,682,978「Hz」になってしまいます。レートは下位24ビットをマスクして取り出し、存在はビット0x40000000で調べてください。ヘッダーの後にさらに7つの「flags」ワードを読むツールは、実際にはフレームサイズのテーブルを読んでいます。

  • 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の改名は無害ですが、ゲームはdata/ディレクトリに.zrbがあることを前提にしています。.smkという名前のファイルをエンジン向けに配布しないでください。

関連項目

  • Bink:TA: KingdomsがSmackerの代わりに使う、後継のコーデック。
  • HPI:ZRBファイルを収めて配布されるラッパーのアーカイブ。
  • 用語集:frame rate(フレームレート)、signature(シグネチャ)。