Often times when developing a game, you’ll want to record a demo video to show to a publisher, show at E3, post on kickstarter, youtube, or other places to help generate interest or gain funding to keep your project going.
Unfortunately, the point in time that you need a video is often in the beginning of the project, when your game probably doesn’t run very fast, or might have performance spikes, making it difficult to get a high quality video capture.
Many times, developers will have to have a performance push to get the game up to speed for a demo video, spending time on “demo hacks”, which are often just throw away code for after the video is made. I’ve been through a couple of these myself and they are not fun, but they are an unfortunate necessity.
This article will explain a fairly simple technique for getting a full speed recording of your game engine with perfectly synchronized sound, no matter what speed your game actually runs at, saving you time and effort, not having to waste time on demo hacks just to get a presentable video.
Playable demos are a whole other beast, and you are on your own there, but if a video will suit your needs, you’ve come to the right place!
I’ve used this technique myself in a couple different games during development, and in fact included it as a feature of one PC game I shipped in the past, called “Line Rider 2:Unbound”, so this is also a technique for adding video recording to any game you might want to add it to.
Out of the box solutions
There are various “out of the box” ways to record a video of your game, but they have some downsides which make them not so attractive.
For instance, you can get fraps which will record any application’s audio and video and you could use that to record a video of your game. The downside here is that if your game lags, so does the video, so we still have that problem. Also, the act of recording competes with your game for resources, causing your game to run at an even lower FPS and making an even worse video. Fraps is also limited to specific platforms, and you may be working on an unsupported platform.
lastly, if you want to include this feature of video recording in a shipped product, you will have to license fraps for that use, which may be prohibitive to your project’s budget.
Other video recording software has the same or similar issues.
Rolling your own – Video
Making your own video recorder built into your game has some real easy to hit pitfalls that I want to talk about.
When considering only the video portion (not audio yet), our aim is to write all the frames to disk as individual image files (such as png, or raw uncompressed image files), and then after recording is done, use something like ffmpeg to combine the frames into a video. Writing a compressed image file (such as png or jpg) for each frame may save disk space, but may take longer for your computer to be able to process and write to disk. You will likely find that a raw file format is more performant, at the cost of increase disk space usage, but hard drives are cheap these days and everyone has huge ones. Also, at this point you probably want to use lossless image compression (such as png, or a raw image file) for your screen captures so that you don’t have compression artifacts in your screen captures. When you make a final video, you may choose a more highly compressed video format, and it may introduce it’s own artifacts, but you want to keep your source files as clean as possible so that you don’t introduce UNNECESSARY artifacts too early in the process.
If you dump each rendered frame to disk, the disk i/o can drag your game’s frame rate down to a crawl. You might think about having the disk write happen on another thread so the game isn’t limited by the disk i/o, but then you’ll have to keep a buffer of previous frames which will grow and grow and grow (since you are making frames faster than it can write to disk) until you run out of memory. It’s a losing battle for longer videos.
You could get a faster drive, configure a striped raid array, use a ram disk, or things like that, but why fix with hardware what you can fix in software? Save yourself and your company some cash.
Similarly to the fraps problem, when you record video, that will likely affect the frame rate of your game as well, making it run slower, making a lower quality video because frames will be skipped – assuming you are using variable frame rate logic – making it so that you either have to have a “laggy” looking video as output, or your video will actually appear to speed up in the places that you encountered lag while recording, which is very odd looking and definitely not demoable.
The solution (which might be really obvious to the astute reader) is to make your game run your game’s logic at a fixed rate, instead of making it be based on frame time. For instance, instead of measuring the time between frames and using that delta to control logic (making things move farther when more time has passed etc), you just make your game act as if the same amount of time has always passed between your frames, such as ~16ms for a 60fps recording, or ~33ms for a 30fps recording. IMPORTANT: make it only behave this way when in “recording mode”. You don’t need to sacrifice variable frame rate logic just to get the ability to record nice videos. Also, 30fps is fine for a video. The more FPS your video has, the larger the video file will be. Movie and TVs are something like 24 fps, so you don’t need a 60 fps video for your game demo, 30 or less is just fine.
This way, it doesn’t matter how long it took to render each frame, the game will generate a sequence of frames at whatever frame rate you would like your video to be in. While recording the demo video, the game may run slowly, and be difficult to control if it’s REALLY laggy, but at least the output video will be smooth and perfectly lagless. Later in this article I present a possible solution to the problem of difficulty playing the game while recording.
Are we done at this point? NO! We haven’t talked at all about audio, and as it turns out our audio is in a very odd state going this route.
Rolling your own – Audio
From the section above, we have a nice lagless video stream, but if we just recorded audio as it went, the audio would be out of sync with the frames. This is because we recorded audio in real time, but we recorded the frames in variable time.
You could try to sync the audio in the right places with each frame, but then you’d have to speed up and slow down portions of your audio to hit the right frame numbers, which would make your audio sound really weird as it sped up and slowed down and changed pitch.
Definitely not demoable! So what’s the solution?
The solution is that while you are recording your video frames, you also make an audio timeline of what audio was triggered at which frame numbers.
For instance, if on frame 20, the player swung his sword and on frame 25 hit an exploding barrel, causing it to explode, your timeline would say “at frame 20, play the sword swing sound effect. at frame 25, play the exploding barrel sound effect”.
I’ve found it really easy to capture an audio timeline by hooking into your game or engine’s audio system itself, capturing all sound events. It usually is not very difficult to implement this part.
After you have recorded all of your video frames, and have an audio timeline, the next step is to re-create the audio from the timeline, which means you need a way of doing “offline” audio mixing.
If you are using an audio library, check the documentation to see if it has an offline mode, many of them do, including the ever popular fmod. If your audio library can’t do it for you, there are various command line tools and audio libraries out there that can do this for you. I believe portaudio (port mixer?) can do this for you, and also another open sourced program called sox.
What you need to do is render each item in the audio timeline onto a cumulative audio stream. If your video were a 30fps video, and a 500ms sound effect happened at frame 93, that means that you know this sound effect started at 3.1 seconds in (frame 93 * 33.33 miliseconds per frame) and lasts until 3.6 seconds (since it’s 500ms long). So, you’d mix that into the output audio stream at the appropriate point in time, and then rinse and repeat with the rest of the audio timeline items until you had the full audio stream for the video.
When you are done with this stage, you have your video frames and your audio stream. With your video creation software (such as ffmpeg) you can combine these into a single video file which shows your game running perfectly at whatever frame rate you specified, and with perfectly synchronized audio. It’s a beautiful thing and definitely ready to demo to get some funding.
To recap, the steps for creating a perfect video recording of your game are:
- When in recording mode, make your game run at a fixed frame rate – no matter how long it really was between frames, lie to your game and tell it that 33.33ms have passed each frame for 30fps video or 16ms for 60fps video (or whatever other frame rate you want to run at)
- Write each rendered frame to disk as an uncompressed or lossless compression graphics file.
- While rendering each frame, build up a timeline of audio events that you can use to re-create the audio later.
- After all the frames are captured, render your audio timeline into an audio stream.
- After you have your audio stream and each video frame, use software such as ffmpeg to combine them into a perfect, lagless video.
- BLOW THE SOCKS OFF OF INVESTORS AND SECURE SOME FUNDING!
Bonus Points – Or making this feature a shippable feature of your game for players to use
At this point, the final product (the video) is as nice as it can possibly be. However, the process of actually recording the video can be cumbersome because even though you are making a nice and smooth 30fps video, during recording it may be running at 2fps (depending on your machine) making it very difficult to control the game. Also, in the final video it will appear that the user is traversing menus, inputting commands, and reacting at superhuman speeds.
A good way to handle this is instead of recording during play, what you do is record all the input that happens during the recording process. This way you have an input timeline that is tied to frame numbers, the same way the audio timeline is tied to frame numbers.
When the recording process is done, you then put up a nice dialog for the end user saying something like “Rendering video please wait….” with a progress bar, and then re-simulate the user input that occurred during the recording phase, and render all those frames to disk (well, screen capture them as image files just like usual, just dont display them to the end user).
Since building an input timeline is relatively cheap computationally, you should have no slow down during the “recording” phase of the video while you (or the end user) is actually playing the game.
The “Gotcha” here is that your game needs to be deterministic for fixed rate time steps (or at least everything that really matters needs to be deterministic, maybe not particles or something) which can potentially be a bit tricky, but the upside is if you actually make this happen, you can record light weight playbacks as “videos” and have users share these feaux-videos with each other to watch playbacks of gameplay that other players had. When you want to export these playbacks as real videos, you can put it through the regular video recording steps and spit out a full mpeg, suitable for sharing, uploading to youtube (from within the app perhaps even?) just like normal. But, until you need to use the video outside of your application, you have very small files users can share with each other to view “videos” of in game gameplay.
Final tip: if doing this in windows, I’ve found that in recent versions of windows, doing the screen capture using GDI functions instead of DirectX is actually WAY faster so use that if you can. I’m thinking this must be because windows already has a screen cap in memory to show those little icons when you mouse over the minimized application or something.
That’s all folks!
That’s all there is to it. With luck this will save some fellow engineers from having to crunch up some “demo hacks” to get performance up for an E3 demo video or the like. If you have any questions or comments, drop me a line (: