所有格式页面 ↓
图形与媒体

Bink——横扫千军:王国的过场视频

来自 coreprime/kbot @ 0ab97bf · 在 GitHub 上编辑

《横扫千军:王国》把初代游戏的 Smacker(.zrb)过场动画换成了 RAD Game Tools 更新的 Bink 编解码器,以 .bik 存储。任务开场、阵营简报和结尾动画都以 Bink 1 文件的形式发布在 movies/ 下。

扩展名 使用者 说明
.bik 横扫千军:王国的 movies/*.bik RAD Bink 1。签名是 BIK 加一个修订版本字节(TA:K 中为 BIKf)。

Bink 不是 Smacker——它是一种独立的、更晚出现的编解码器,有自己基于 DCT 的视频比特流和自己的音频(Bink Audio,DCT 或 RDFT)。kbot 原生解析容器的文件头,但把像素解码交给 FFmpeg,后者自带 Bink 1 解码器(binkvideo、binkaudio_dct/binkaudio_rdft)。

Tip

自己试试。

kbot bik info   movies/takmission14_ph.bik          # header summary
kbot bik to-mp4 movies/takmission14_ph.bik out.mp4  # decode to MP4 (requires ffmpeg)

在 Go 中调用。 使用 formats/bik:

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

r, _ := bik.OpenReader("movies/takmission14_ph.bik")
defer r.Close()
fmt.Println(r.Width(), r.Height(), r.FrameCount(), r.FrameRate())
_ = bik.ConvertToMP4("movies/takmission14_ph.bik", "out.mp4")

横扫千军:王国安装目录中有什么

$ ls $(kbot ctx path)/movies/*.bik
takmission01_ph.bik  takmission14_ph.bik  takx21_dh.bik  …
$ ls $(kbot ctx path)/movies/gui/*.bik
snort4.bik  snort6.bik  …          # tiny UI stingers, often a few KB

典型的任务过场动画是 640 × 350、15 fps,带一条 16 位立体声音轨(约 22 kHz)。movies/gui/ 中的片段要小得多,有时尺寸是奇数(例如 124 × 101)——见下面的坑点。


文件头布局(Bink 1)

所有字段都是小端序。kbot 读到音轨表为止(含音轨表);逐帧索引和压缩的比特流留给 FFmpeg 处理。

typedef struct {
    char   Signature[4];   // 'B','I','K', revision  (revision 'f' in TA:K)
    uint32 FileSize;       // total file size minus 8
    uint32 Frames;         // video frame count
    uint32 LargestFrame;   // size in bytes of the biggest frame
    uint32 FramesCopy;     // duplicate frame count (ignored)
    uint32 Width;
    uint32 Height;
    uint32 FPSNum;         // frame rate numerator
    uint32 FPSDen;         // frame rate denominator
    uint32 VideoFlags;     // bit 0x00100000 = alpha plane, 0x00020000 = grayscale
    uint32 NumAudioTracks;
    // if NumAudioTracks > 0:
    uint32 AudioMaxSize[NumAudioTracks];   // per-track max packet (ignored)
    struct { uint16 SampleRate; uint16 Flags; } AudioInfo[NumAudioTracks];
    uint32 AudioTrackID[NumAudioTracks];
    // followed by:
    uint32 FrameOffsets[Frames + 1];       // LSB of each offset is the keyframe flag
} BinkHeader;

帧率

fps = FPSNum / FPSDen。TA:K 的过场动画使用 15 / 1。由于它是一对有理数,值可能带小数,所以 kbot 把它保存为浮点数。

音频标志(16 位的 Flags 字)

位 含义
0x4000 16 位采样(否则为 8 位)
0x2000 立体声(否则为单声道)
0x1000 DCT 编解码器(否则为 RDFT)

Note

SampleRate 就是存储的原值——TA:K 发布的是 22254 Hz,而不是整齐的 22050。kbot 原样报告。


转换只能单向解码

kbot bik to-mp4 会调用 FFmpeg:

ffmpeg -i in.bik \
       -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2" \
       -c:v libx264 -preset fast -crf 18 \
       -c:a aac -b:a 192k \
       -y out.mp4

没有 from-mp4:不存在任何开源的 Bink 编码器,只有 RAD 的专有工具能生成 .bik 文件。Smacker 实际上也是如此——原版 FFmpeg 同样没有 Smacker 编码器或封装器(见 Smacker/ZRB)。

Warning

奇数尺寸。 有几个 movies/gui/*.bik 片段的尺寸不能被 2 整除(例如 124 × 101)。采用 yuv420p 的 H.264 要求宽和高都是偶数,因此转换器用 pad 滤镜把尺寸补到下一个偶数,而不是重新缩放——不会重采样任何像素,只是加上一行/一列黑边。


坑点

  • Bink 不是 Smacker。 不要用 kbot zrb 处理 .bik(也不要用 kbot bik 处理 .zrb);两者的签名和编解码器完全不同。
  • 不支持 Bink 2(KB2)。 TA:K 早于 Bink 2,因此每个发行文件都是 Bink 1(BIK*)。kbot 会以明确的错误拒绝 KB2*。
  • 加密的 Boneyards 短片。 boneyards/metagame/*.bik 下有少数几个文件(例如 ftuimovie2.bik)带着 .bik 扩展名,但不是 Bink 容器——它们是在线元游戏界面所用的、经过扰乱/混淆的载荷。kbot 会把它们作为无效文件拒绝,而不是去猜测。

另见

  • Smacker / ZRB——Bink 所取代的初代 TA 过场视频格式。
  • HPI——发布这些文件的外层压缩包。