AVI files

The Mechwarrior 3 intro and campaign videos are found in the video directory on the CD. They can also optionally be installed to the hard drive.

Investigation (MW3)

They are AVI containers (*.avi). The video codec is known from the installation, but we can confirm that and gather more information using ffmpeg, specifically ffprobe. This is for campaign.avi, information on all English video files can be found in the appendix:

Input #0, avi, from 'Campaign.avi':
  Duration: 00:03:24.27, start: 0.000000, bitrate: 3320 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 3020 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 22050 Hz, 1 channels, u8, 176 kb/s

The video streams are encoded using Intel's Indeo codec (version 5, FourCC IV50). They are all 640x480 at 15 frames per second, although the bitrates vary from 3020 kb/s to 1260 kb/s. The audio streams are raw pulse-code modulation (PCM) at 22050 Hz, so uncompressed.

For the German version, these have the metadata "Sound Forge 4.0 Audio" attached, which was a German sound editing program, probably used by the localisation team.

These codecs were no doubt chosen because they could be decoded with very little CPU, not because of their quality. This is especially true if they had to be streamed from the CD. Codecs have come far since then, with ubiquitous hardware support. Indeo has at least one vulnerability, meaning the codec is unlikely to be installed on modern systems. Realistically, the best option is to re-encode at least the video using existing software (ffmpeg). Installing the old codec is obviously inadvisable, and reverse engineering the codec is complicated and unnecessary.

The file checksums between the US versions 1.0, 1.1, and 1.2 are exactly the same (on the CD - I don't think the patch affects the video files, simply based on the size, but haven't checked).

Re-encoding

TL;DR:

for f in *.avi
do
    ffmpeg \
        -i "$f" \
        -codec:v "libx264" \
        -preset "medium" \
        -crf "30" \
        -codec:a "aac" \
        -b:a "64k" \
        "${f%.*}.mp4"
done

To compress the audio, there are several options. If supported, advanced audio coding (ACC) is excellent at low bitrates, and for mainly speech, using 64 kb/s is fine without any concerns of quality loss. The command line options are -codec:a aac -b:a 64k1. AAC is patented and not all game engines support it. This is generally problematic for good audio codecs. A viable alternative is to not alter the audio and just copy it using -codec:a copy, as raw PCM support is ubiquitous.

As mentioned, I definitely wanted to re-encode the video because of known Indeo vulnerabilities. H.264/x264 is widely supported. Quality-wise, it's a bit trickier than the audio, because it's more subjective in comparisons. The original video is highly compressed, with visible compression artefacts - please keep this in mind, the re-encoded file can't be better than the original. So personally, I find the video re-encoded with a low bitrate fine. In fact, choosing a low bitrate smooths some of the original, block-y compression artefacts out (the smoothing could be done via processing at higher bitrates). But you can decide for yourself, in a minute I'll show how to compare the re-encoded to the original. And worst case, files can be re-encoded from the original again.

My recommendation is to use a fairly quick encoding to test things out, and a low quality factor. Something like -codec:v libx264 -preset medium -crf 28. It's worth reading the ffmpeg H.264 encoding guide if you wish to change these parameters. Choose a slower preset should deliver the same quality at a lower bitrate, at expense of encoding time. Choosing a lower crf value will increase the bitrate, which in theory increases quality. Given the source material, that probably won't do much those. Once you're happy with the parameters, I'd suggest using a slower preset for the final encoding, like veryslow, since processing power is cheap and these videos are short and have a tiny resolution (generally, the preset doesn't affect quality very much).

For a container format with maximum compatibility, I've chosen MPEG-4 (*.mp4), although if supported by your use-case, the open standard Matroska (*.mkv) is an excellent choice.

1

libfdk might be slightly higher in quality, and if your build of ffmpeg was compiled with libfdk support you could try using the libfdk_aac codec. That also enabled the use of variable bit rate. However, I don't think it's worth the effort. The input isn't exactly high quality in the first place, and the built-in AAC encoder is pretty good.

Comparing results

The MPV media player can play two (or more) videos side-by-side, which is great for comparing the encoded video.

mpv --lavfi-complex="[vid1][vid2]hstack[vo]" intro.avi --external-file=intro.mp4

In-game use

The introduction is played when the game is loading. The campaign videos are played when the campaign is started, and between missions.

Appendix 1: Modern codec performance

It's interesting to see just how far codecs have come. For those settings, the average reduction in size is 86% for the US version and almost 89% for the German version!

video/v1.0-us

FilenameOriginalCompressedReduction
intro.avi78.36 MiB5.47 MiB93.0%
Campaign.avi80.85 MiB12.45 MiB84.6%
c1.avi14.50 MiB1.36 MiB90.6%
c1m1.avi8.75 MiB0.97 MiB88.9%
c1m2.avi5.96 MiB0.77 MiB87.0%
c1m3.avi5.21 MiB0.74 MiB85.7%
c1m4.avi9.17 MiB1.16 MiB87.4%
c2.avi10.79 MiB1.67 MiB84.6%
c2m1.avi4.77 MiB0.65 MiB86.4%
c2m2.avi10.41 MiB1.22 MiB88.3%
c2m3.avi6.31 MiB0.75 MiB88.2%
c2m4.avi7.68 MiB0.79 MiB89.7%
c3.avi5.48 MiB1.62 MiB70.5%
c3m1.avi5.93 MiB1.06 MiB82.1%
c3m2.avi6.24 MiB1.02 MiB83.6%
c3m4.avi7.45 MiB1.12 MiB84.9%
c3m5.avi9.49 MiB1.08 MiB88.6%
c3m6.avi5.73 MiB0.84 MiB85.3%
c4win.avi23.98 MiB1.49 MiB93.8%

Average reduction: 86.5%

video/v1.0-de

FilenameOriginalCompressedReduction
intro.avi76.00 MiB5.33 MiB93.0%
Campaign.avi77.76 MiB11.35 MiB85.4%
c1.avi13.45 MiB1.36 MiB89.9%
c1m1.avi10.88 MiB0.97 MiB91.1%
c1m2.avi7.44 MiB0.77 MiB89.6%
c1m3.avi6.50 MiB0.74 MiB88.5%
c1m4.avi11.38 MiB1.16 MiB89.8%
c2.avi13.32 MiB1.67 MiB87.5%
c2m1.avi5.95 MiB0.65 MiB89.1%
c2m2.avi12.86 MiB1.22 MiB90.5%
c2m3.avi7.86 MiB0.75 MiB90.5%
c2m4.avi9.46 MiB0.79 MiB91.6%
c3.avi6.88 MiB1.62 MiB76.5%
c3m1.avi7.38 MiB1.06 MiB85.6%
c3m2.avi7.75 MiB1.02 MiB86.8%
c3m4.avi9.27 MiB1.13 MiB87.9%
c3m5.avi11.80 MiB1.08 MiB90.9%
c3m6.avi7.15 MiB0.84 MiB88.3%
c4win.avi23.98 MiB1.50 MiB93.8%

Average reduction: 88.7%

Appendix 2: English video file information

Input #0, avi, from 'Campaign.avi':
  Duration: 00:03:24.27, start: 0.000000, bitrate: 3320 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 3020 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 22050 Hz, 1 channels, u8, 176 kb/s
Input #0, avi, from 'c1.avi':
  Duration: 00:00:58.00, start: 0.000000, bitrate: 2096 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 1236 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 22050 Hz, 2 channels, s16, 705 kb/s
Input #0, avi, from 'c1m1.avi':
  Duration: 00:00:46.00, start: 0.000000, bitrate: 1595 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 1275 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 22050 Hz, 1 channels, u8, 176 kb/s
Input #0, avi, from 'c1m2.avi':
  Duration: 00:00:31.67, start: 0.000000, bitrate: 1577 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 1263 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 22050 Hz, 1 channels, u8, 176 kb/s
Input #0, avi, from 'c1m3.avi':
  Duration: 00:00:27.73, start: 0.000000, bitrate: 1577 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 1258 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 22050 Hz, 1 channels, u8, 176 kb/s
Input #0, avi, from 'c1m4.avi':
  Duration: 00:00:48.33, start: 0.000000, bitrate: 1591 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 1268 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 22050 Hz, 1 channels, u8, 176 kb/s
Input #0, avi, from 'c2.avi':
  Duration: 00:00:56.67, start: 0.000000, bitrate: 1596 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 1265 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 22050 Hz, 1 channels, u8, 176 kb/s
Input #0, avi, from 'c2m1.avi':
  Duration: 00:00:25.27, start: 0.000000, bitrate: 1584 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 1270 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 22050 Hz, 1 channels, u8, 176 kb/s
Input #0, avi, from 'c2m2.avi':
  Duration: 00:00:54.40, start: 0.000000, bitrate: 1605 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 1275 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 22050 Hz, 1 channels, u8, 176 kb/s
Input #0, avi, from 'c2m3.avi':
  Duration: 00:00:33.33, start: 0.000000, bitrate: 1587 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 1270 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 22050 Hz, 1 channels, u8, 176 kb/s
Input #0, avi, from 'c2m4.avi':
  Duration: 00:00:39.80, start: 0.000000, bitrate: 1618 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 1286 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 22050 Hz, 1 channels, u8, 176 kb/s
Input #0, avi, from 'c3.avi':
  Duration: 00:00:29.27, start: 0.000000, bitrate: 1570 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 1264 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 22050 Hz, 1 channels, u8, 176 kb/s
Input #0, avi, from 'c3m1.avi':
  Duration: 00:00:31.47, start: 0.000000, bitrate: 1579 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 1260 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 22050 Hz, 1 channels, u8, 176 kb/s
Input #0, avi, from 'c3m2.avi':
  Duration: 00:00:33.20, start: 0.000000, bitrate: 1575 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 1252 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 22050 Hz, 1 channels, u8, 176 kb/s
Input #0, avi, from 'c3m4.avi':
  Duration: 00:00:39.53, start: 0.000000, bitrate: 1580 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 1260 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 22050 Hz, 1 channels, u8, 176 kb/s
Input #0, avi, from 'c3m5.avi':
  Duration: 00:00:50.07, start: 0.000000, bitrate: 1590 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 1270 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 22050 Hz, 1 channels, u8, 176 kb/s
Input #0, avi, from 'c3m6.avi':
  Duration: 00:00:30.40, start: 0.000000, bitrate: 1582 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 1266 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 22050 Hz, 1 channels, u8, 176 kb/s
Input #0, avi, from 'c4win.avi':
  Duration: 00:01:12.20, start: 0.000000, bitrate: 2786 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 2481 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_u8 ([1][0][0][0] / 0x0001), 22050 Hz, 1 channels, u8, 176 kb/s
Input #0, avi, from 'intro.avi':
  Duration: 00:03:02.47, start: 0.000000, bitrate: 3602 kb/s
  Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 640x480, 2764 kb/s, 15 fps, 15 tbr, 15 tbn, 15 tbc
  Stream #0:1: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 22050 Hz, 2 channels, s16, 705 kb/s