SETTINGS
Appearance
Language
About

Settings

Select a category to the left.

Appearance

Theme

Choose an overall theme for the entire blog. Each can have their own colours.

Colourscheme

Light or dark? Choose how the site looks to you by clicking an image below.

Light Dark
AMOLED

Language

Preferred Language

All content on blog.claranguyen.me is originally in UK English. However, if content exists in your preferred language, it will display as that instead. Feel free to choose that below. This will require a page refresh to take effect.

About

"blog.claranguyen.me" details

Domain Name: claranguyen.me
Site Version: 2.0.0
Last Updated: 2025/03/09
Christmas Deathmatch 2020 (Production Procedure)
Monday, December 21, 2020

Just a heads up: This post is unlisted. Only those who know the link can access it. Please be mindful of this before sharing the post to others.

Introduction

Since 2012, I've been doing yearly video projects where me, my brother, and my dad play Half-Life. I record and upload all of the footage to YouTube. The format has been almost the same every year. 1920x1080 footage. Has an intro and a proper ending which links to other videos in the series. This effective formula for content creation has held strong up until now. And I could've easily used it for the Christmas Deathmatch 2020 too. But, I could do better. So let's give the procedure an update.

Video/Audio Format

Despite the game coming out in 1998, the very nature of it being on PC means resolution is a non-issue. So, we'll go with ultrawide 2560x1080. For sound, an update that brought Half-Life to Linux back in 2013 removed EAX, and surround sound is completely broken. Luckily, there is MetaAudio, which brings these effects back. With this, 7.1 surround sound is restored.

Anyway, here's the specifications:

YouTube & Surround Sound

As mentioned in my Spy Hunter Video Production Procedure post, YouTube supports surround sound. It stores a proper discrete 5.1 surround sound track. If you upload a video with a manual stereo and surround track, it'll use both. It'll also generate a 5.1 surround sound track from a 7.1 track if supplied. So we'll upload a 7.1 + Stereo MKV. YouTube stores the original video uploaded and can reprocess it when a new feature is added. So if YouTube supports 7.1 in the future, the video doesn't have to be reuploaded.

Setup

Usually when I do projects like these, I try to figure out how to automate as much as possible. I wrote a post on the previous production procedure, where I generate clips with Adobe After Effects and have to use it for the endings instead of FFmpeg. As the years go by, I became aware of the more complex features of FFmpeg, like -filter_complex, which is the crux of this post.

Video Segmentation

The Christmas Deathmatch follows a format which demands that the recordings are split between 4 separate files, and then concatenated at the very end. These are:

  1. intro.mkv - Fake map loading cinematic
  2. class_sel.mkv - Fake class selection cinematic
  3. gameplay.mkv - The actual Half-Life 1 gameplay
  4. ending.mkv - Video ending showing previous/next videos

Every segment except for gameplay.mkv is generated by FFmpeg. I didn't intend on changing this format because it has worked effectively every year so far. Those 4 segments are compressed using the same encoders and same settings. They can then be concatenated (stitched together) into the final MKV deliverable that is then uploaded to YouTube.

Other Assets

In addition to those MKV files, a few other files are required. These are used to generate some of the MKV files above.

Lost? Here's visuals for the images and videos:

load_img.png
load_fg.png
final_frame.png
ending_text.png
shader_mask_2560x1080.avi
ending_fog_2560x1080.avi

Recording

The simplest part of the project is getting gameplay. Just play the game and record it. Well unfortunately it isn't that simple.

Thanks to Windows 10, as well as Valve removing Direct3D from Half-Life, recording solutions such as Dxtory and Fraps no longer work, as they can't detect and hook into the drawing pipeline to capture video. OBS can work, but it had its own issues that I did not have time to fix (it falls quickly with the absurdly high standards I have in video quality). That kinda sucks. However, Half-Life has a secret weapon... Demo Recording.

Demo Recording

Half-Life features Demo Recording, which means it's possible to record inputs and export at any resolution desired at any moment directly from the game. I can also export at any frame rate I want. These files are commonly 10-30 MB in size. Every year, I archive Christmas Deathmatch like this. So it's possible for me to go back to 2012 and re-export it in 2560x1080 60 FPS if I wanted. These files are saved as .dem files.

I wrote a plugin for AMX Mod X which forces all players to record the moment they join. This means I don't have to think. All matches, Christmas Deathmatch or not, are archived instantly from all POVs.

There's some differences in the DEM recording vs the original run. Notably, projectiles and the laser from the RPG are smoother in the original recording. It'll have a flickering effect when played back via DEM. I'm sure there's commands to smoothen it out (like there are in the Source Engine).

"How do I record my own demos?"

Without that plugin, you may be curious how to utilise Demo Recording in your gameplays. To record a run, simply open up the developer's console and type:

GoldSrc Console Command
record DEMO_NAME_HERE

This will create a DEMO_NAME_HERE.dem file in your game's mod directory. Whenever you hit the end of your desired recording, type the following command:

GoldSrc Console Command
stop

Finally, your replay can then be replayed via:

GoldSrc Console Command
playdemo DEMO_NAME_HERE

HLAE (Half-Life Advanced Effects)

I've been eyeing this for a few years. Quite simply, it's a collection of tools and commands which make it easier to produce video from .dem files. I simply force the game to run in 2560x1080 at 60 FPS. Then I have HLAE export every frame along with a sample stereo audio track. The result is a perfect 60 FPS video without any frame drops. The only consequence for this is that I have to replay each match after playing just to export the frames. It's quite time consuming. But I think it's worth it. It's also automatable with shell scripting.

Just to throw some numbers out... A 15 minute match takes around 48 minutes to export. Around 50,000 BMP files are created per match. Each frame is around 7.81 MB, meaning each match is over 390 GB in size. That's lengthy! For 14 matches, several terabytes of storage is needed. Luckily for me, storage is not a problem anymore. Throughout the project, a total of 1,046,815 images were generated, totaling 7.43 TB in size:

Generating Video Frames

A match was played and a .dem file has been created. We can now utilise HLAE to generate the video of the match in the form of BMP files... tens of thousands of them.

To start, open HLAE. It's a separate application. I run my Half-Life servers with mods, so the appropriate parameters for AMX Mod X have to be passed in as well. Overall, my configuration looks like this:

Upon booting up the game, the following commands need to be put into the developer's console:

GoldSrc Console Commands
mirv_movie_fps 60
mirv_movie_export_sound 1
mirv_movie_filename "PATH_TO_EXPORT_DIRECTORY"
mirv_movie_playdemostop 1

These will configure HLAE for 60 FPS and export the sound. On Windows, the PATH_TO_EXPORT_DIRECTORY should include drive letter and use backslashes (e.g. g:\Fraps\01_crossfire was what I used for the first match).

Finally, play the demo and record with HLAE. Chain the commands together by separating them with a ;. Otherwise, you will have to open up the console while the demo is playing and tell it to record. That's not fun or practical. Issue this as if it were a single command:

GoldSrc Console Commands
playdemo DEMO_NAME_HERE; mirv_recordmovie_start

Whenever the match ends, mirv_movie_playdemostop 1 should have automatically stopped the recording. In my case, it didn't for some reason. So I had to manually stop it via:

GoldSrc Console Commands
mirv_recordmovie_stop

If you do not stop the recording, and decide to just exit the game, your audio will be missing its header information and need to be recreated. I would rather have HLAE fill this information in itself.

With this done, we have what we need to create gameplay.mkv.

Making gameplay.mkv

gameplay.mkv is simple to generate and requires no editing at all, since it's just the gameplay of us killing each other. So let's render it out.

The BMP files are named as 00000.bmp, 00001.bmp, and so on. An audio file, sound.wav is also generated. Generating a video from these frames and audio is trivial with FFmpeg:

Bash Script Segment
ffmpeg \
	-r                 60                \
	-i                 "$1/all/%05d.bmp" \
	-i                 "$1/sound.wav"    \
	-map               0:v               \
	-map               1:a               \
	-c:v               libx265           \
	-preset            medium            \
	-pix_fmt           yuv420p10le       \
	-crf               17                \
	-c:a               flac              \
	-compression_level 12                \
	-shortest                            \
	"$1/gameplay.mkv"

This is not an FFmpeg tutorial. To summarise though:




Clara Nguyễn
Hi! I am a Vietnamese/Italian mix with a Master's Degree in Computer Science from UTK. I have been programming since I was 6 and love to write apps and tools to make people's lives easier. I also love to do photography and media production. Nice to meet you!


Blog Links
Post Archive