For a tutorial on how to record an X11 desktop (Linux/Unix/BSD) with FFmpeg see:
The first thing that you will need to do (after you have FFmpeg installed) if you want to record your Windows® desktop is to install a DirectShow filter/driver that is designed specifically for this purpose. I can recommend two filters: UScreenCapture and Screen Capture Recorder. There are subtle differences between the two. By default:
- Unless explicitly declared Screen Capture Recorder will process 30 frames per second by default while UScreenCapture will only do 10. In FFmpeg it is necessary to declare FPS (-r option) before the input (-i option) in order to correctly process the desired frame rate. If you have trouble getting UScreenCapture to use a higher frame rate check this tutorial.
- UScreenCapture is free proprietary software. It is part of the Unreal Media Server. Screen Capture Recorder is open source software (contact author about license details).
Now you can use FFmpeg to display your available DirectShow capture sources: From a command line type “ffmpeg -list_devices true -f dshow -i dummy”. At the end of the output you will see a number of devices listed under “DirectShow video devices” and “DirectShow audio devices”.
Using FFmpeg to Record:
Some options that you may want to consider:
- Real-Time Buffer: If you have problems with buffer overflow and/or skipped frames you may want to set the real-time buffer option. Example: -rtbufsize 1500M
- Video Quality: If you do not want to lose any video quality two good encoder options are the huffyuv video codec or libx264 with the “-crf 0” or “-qp 0” options. Example: -crf 0 -vcodec libx264.
- Audio Quality: For lossless audio compression use the pcm_s16le audio codec. This is the most commonly used PCM/WAV format (signed 16-bit little endian). You can also use the flac codec, but in my experience pcm is less buggy. It is probably also a good idea to record with a single audio channel (mono) since most likely you will be recording from a single audio input (microphone). This will reduce the size of the output file. If you want to use a frequency other than the default (generally 44,100 Hz) you can specify the audio rate option. Example: -acodec pcm_s16le -ac 1 -ar 44100
Use the ffmpeg command and optionally set the real-time buffer:
ffmpeg -rtbufsize 1500M
Set the format to “dshow”.
ffmpeg -rtbufsize 1500M -f dshow
To avoid a few frame rate problems if want something other than the default it is a good idea to set it before declaring the video input:
ffmpeg -rtbufsize 1500M -f dshow -r 30
Now choose the video input source. This should be typed exactly (letter casing does not matter on Windows® systems) as displayed in the list of DirectShow devices (Image 1-1):
ffmpeg -rtbufsize 1500M -f dshow -r 30 -i video=”UScreenCapture”
If you want to capture audio as well add a colon (:) and set the audio input source. Just like the video capture source this should be typed exactly as displayed in the list of DirectShow devices. Note from the picture above that on my system there is no closing brace in the microphone name:
ffmpeg -rtbufsize 1500M -f dshow -r 30 -i video=”UScreenCapture”:audio=”Microphone (Realtek AC’97 Audio”
Specify the video and audio encoders. It is not important which comes first (Note that -vcodec and -acodec can be substituted by -c:v and -c:a respectively).
Video: Remember to use “-crf 0” or “-qp 0” if you want lossless compression with libx264 (Note: crf stands for “Constant Rate Factor” and qp I believe stands for “Quantization Parameter”). According to the FFmpeg documentation qp is recommended over crf but I am unsure of the difference. If you want more information on crf vs qp this document may be helpful. Note: I am not sure if it is important when this option is declared:
ffmpeg -rtbufsize 1500M -f dshow -r 30 -i video=”UScreenCapture”:audio=”Microphone (Realtek AC’97 Audio” -crf 0 -vcodec libx264
A nice feature of the huffyuv format is that it uses all I-frames. This makes editing the video much more simple in some cases. It allows cropping of the video at any frame without the need for re-encoding. There is also a way use I-frames only with libx264 by setting the keyframe interval to 1 using the option x264opts. However, this may result in a greater chance of buffer overflow:
ffmpeg -rtbufsize 1500M -f dshow -r 30 -i video=”UScreenCapture”:audio=”Microphone (Realtek AC’97 Audio” -crf 0 -vcodec libx264 -x264opts keyint=1
For other supporting encoders you can force I-frames only by adding “-force_key_frames expr:1” after the video codec:
-vcodec libxvid -force_key_frames expr:1
ffmpeg -rtbufsize 1500M -f dshow -r 30 -i video=”UScreenCapture”:audio=”Microphone (Realtek AC’97 Audio” -crf 0 -vcodec libx264 -acodec pcm_s16le -ac 1 -ar 44100
Notes On Encoding AAC Audio:
FFmpeg has a few different AAC encoders: aac, libvo_aacenc, libfaac, and libfdk_aac. However, the official build only supplies aac and libvo_aacenc. If you want to use one of the other encoders you will either have to compile FFmpeg yourself or find an unofficial download that includes them. libfdk_aac is considered to be the best and libvo_aacenc the worst. libvo_aacenc is more limited than the other encoders as it can only use constant bitrate (CBR). aac can use variable bitrate (VBR) but the encoder is disabled by default. You must add “-strict experimental” or “-strict -2” to the command line to use it:
-strict experimental -acodec aac
If you want to output VBR with aac use the audio quantizer switch (-q:a or -qscale:a) which receives a floating point value. The audio bitrate switch (-ab or -b:a) will create a reference bitrate for the quantizer. By default it is 128k and a quantizer value of about 1.1 will place the average bitrate (ABR) close to that. The following examples demonstrate how the quantizer’s value is affected by the reference bitrate:
-strict experimental -acodec aac -q:a 0.47 (ABR will be about 64k)
-strict experimental -acodec aac -q:a 1.1 (ABR will be about 128k)
-strict experimental -acodec aac -q:a 0.47 -b:a 256k (ABR will be about 113k)
-strict experimental -acodec aac -q:a 1.1 -b:a 256k (ABR will be about 212k)
Choosing a Video Container Format (e.g. File Extension):
Finally specify the output filename and container (e.g. .avi, .mp4, .mkv, etc.). Note: Some container formats will not work correctly with certain codecs:
ffmpeg -rtbufsize 1500M -f dshow -r 30 -i video=”UScreenCapture”:audio=”Microphone (Realtek AC’97 Audio” -crf 0 -vcodec libx264 -acodec pcm_s16le -ac 1 -ar 44100 “out video.avi”
In my experience I have had problems with buffer overflow, frame rate and audio synchronization on different systems. This may be due to higher screen resolutions or limited resources. If you are having similar problems some of these suggestions might help:
Audio and Video Out of Sync:
Set Async to Match Video Frame Rate:
This option seems to work the best for me to fix audio sync problems. Use -async and set its value to the same as the desired video frame rate:
-r 30 -vcodec libx264 -crf 0 -acodec pcm_s16le -ac 1 -ar 44100 -async 30
Setting Pixel Format:
Adding the pixel format option before the video and audio codecs may help with audio synchronization issues. Screen Capture Recorder and UScreenCapture both seem to process frames in rgb24 by default:
-crf 0 -pix_format rgb24 -vcodec libx264 -acodec …
Windows Resolution and Themes:
It may be possible to avoid buffer overflow by disabling any desktop themes that use transparency (e.g. Aero) or reducing the display resolution. This will free up some system resources.
Intra frames, a.k.a. key frames or I-frames, are larger than other types. Some encoders output in key frames only which requires a larger load on the encoder. If the encoder allows it, reducing the amount encoded into the video will probably greatly help. You can use the -x264opts switch to change the I-frames interval with the libx264 encoder:
-vcodec libx264 -x264opts keyint=100:min-keyint=80
Otherwise you can use the -force_key_frames expr:expr switch. But this is much more complicated.
Using HuffYUV FFmpeg Variant:
If you are having problems with the huffyuv encoder you can alternatively try the FFmpeg variant ffvhuff. This, however, will probably not solve problems with buffer overflow.
Using MPEG4 Encoder (Xvid):
If you are having trouble solving problems with any lossless encoders then I recommend trying to encode into the Xvid (MPEG-4 Part 2 ASP) format using the mpeg4 encoder. Unfortunately there will be some quality loss because the pixel format will be downscaled to yuv420p. Quality loss can be minimized by setting the video quantizer value (-q:v or -qscale:v) to “0”:
-vcodec mpeg4 -vtag xvid -q:v 0
Re-Processing Output Video to Correct Audio Synchronization:
If you are unable to prevent audio synchronization problems then as a last resort you can try running the output video file through some other video software which can re-sync. Below are some software options and the steps to do this.
So far this is the only solution I have found for reprocessing the video. I am currently checking out Mencoder to see if it is possible.
- Start VirtualDub and the output video file.
- In the menu bar: Select “Video” then “Direct stream copy”. Also Make sure that “Direct stream copy” is selected under “Audio”. This copies the video and audio streams without the need to re-encode.
- Again under “Video” select “Frame Rate”.
- Under “Source rate adjustment” select “Change so video and audio durations match” and press “OK”.
- If you want the output frame rate to be the same as input: Under “Frame rate conversion” select “Convert to fps:” and input the source frame rate in the adjacent field. (Note: You may need to do this step separately after you synchronize the audio)
- Go back to the menu bar and select “File” -> “Save as AVI”. Choose a file name and press “Save”.
Problems with this method: Depending on the change in frame rate the resulting video could end up “choppy”.
Re-encoding Video with FFmpeg or Mencoder:
In my testing I have been able to resync audio by simply re-encoding the video. This leads me to believe that though scanning the files shows that the video is encoded at 30fps it is actually not:
ffmpeg -i video_in.avi -vcodec libx264 -crf 0 -acodec copy video_out.avi
mencoder -ovc x264 -x264encopts crf=0 -oac copy -o video_out.avi video_in.avi