FFmpeg is a command-line tool that converts multimedia files between formats. You can use it to create streamable VOD assets to use with Wowza Streaming Engine™ media server software.
Note: FFmpeg is updated frequently. Download the current version and read current documentation at ffmpeg.org. The examples in this article are based on FFmpeg version N-89980-ge752da5464, which is in the 4.1 branch.
Basic encoding example
Multipass encoding example
Analyze VOD encodings using FFprobe
Here's a code example that converts a 59.940-fps, interlaced NTSC .mp4 file to a 29.970-fps, progressive, deinterlaced .mp4 file. Each option is explained below the example. For information about additional options, see the current FFmpeg documentation at FFmpeg.org.
ffmpeg -i inputfile.mp4 -pix_fmt yuv420p -deinterlace -vf "scale=640:360" -vsync 1 -threads 0 -vcodec libx264 -r 29.970 -g 60 -sc_threshold 0 -b:v 1024k -bufsize 1216k -maxrate 1280k -preset medium -profile:v main -tune film -acodec aac -b:a 128k -ac 2 -ar 48000 -af "aresample=async=1:min_hard_comp=0.100000:first_pts=0" -f mp4 -y outputfile.mp4
- -i inputfile.mp4 – Specifies that the source file being converted is inputfile.mp4.
- -pix_fmt yuv420p – Specifies the color space as yuv420p, which is supported by browser-based players.
- -deinterlace – Deinterlaces the content. Never deinterlace content that is already progressive.
- -vf "scale=640:360" – Scales, or resizes, the source video to 640x360 for browser-based playback.
- -vsync 1 – Destroys all PTS/DTS timing in the source file and re-creates the PTS/DTS time stamps. Frames can be duplicated and dropped to maintain a constant frame rate and help keep video and audio synchronized.
- -threads 0 – Allows FFmpeg to use all available cores on your hardware.
- -vcodec libx264 – Uses the H.264 codec library. You can also specify the video codec with the -c:v option.
- -r 29.970 – Specifies the frame rate of the output file as 29.970 fps. This works with the -vsync 1 option and ensures that keyframes are evenly spaced.
- -g 60 – Specifies the keyframe interval, or group of pictures (GOP), as 60.
- -sc_threshold 0 – Enforces the GOP value in the codec. If you don’t include this then the keyframe interval and segment sizes will vary, and keyframes won’t be aligned for adaptive bitrate switching. Alternatively, you can use the codec-specific option -x264opts no-scenecut.
- -b:v 1024k – Specifies a video bitrate of 1024 kbps. Bitrates can be represented in bytes, such as 1024000.
- -bufsize 1216k – Specifies how much data the player should buffer before playing content—1216k.
- -maxrate 1280k – Specifies the maximum bitrate as 1280 kbps.
- -preset medium – Defines how many reference frames to use. The more reference frames used, the more complex the encoding process. When creating streaming VOD assets, don't use any value greater than medium, which is the default preset for x264 encoding and limits reference frames to three.
- -profile:v main – Sets the video encoding profile. Some audio codecs also have a profile, which is why it's important to use the :v flag with the -profile option. When encoding content in the yuv420p color space, use the baseline, main, or high profile. The default profile for x264 is high.
- -tune film – This is the default and recommended setting for encoding content. Valid tuning options include film, animation, grain, stillimage, psnr, ssim, fastdecode, zerolatency. Don't use the animation value as it will double the number of reference frames defined by the -preset option. The film value is the default setting for x264.
- -acodec aac – Uses the internal FFmpeg AAC codec for the audio processing.
- -b:a 128k – Specifies the bitrate of the audio as 128k. As with the video bitrate, the audio bitrate can also be specified in bytes (128000).
- -ac 2 – Specifies the number of audio channels. Stereo audio is recommended for best compatability. Wowza Streaming Engine doesn't support more than two audio channels.
- -ar 48000 – Specifies the audio frequency. Limit the frequency to 8000, 16000, 22050, 44100, or 48000.
- -af "aresample=async=1:min_hard_comp=0.100000:first_pts=0" – A filter that helps keep audio and video tracks in sync.
- -f mp4 – Defines the container type. Changing a file extension does not change the container.
- -y outputfile.mp4 – Overwrites the output file. Required for two-pass encoding.
To use two-pass encoding, simply run the command twice, adding the -pass 1 option to the first command and -pass 2 to the second command. Add the -pass option between the video and audio options (between the -tune and -acodec) as shown in the following examples:
ffmpeg -i [inputfile] -pix_fmt yuv420p [deinterlace] -vf "scale=[video-resolution]" -vsync 1 -threads 0 -vcodec libx264 -r [video-framerate] -g [video-framerate*2] -sc_threshold 0 -b:v [calculated-bitrate] -bufsize [calculated-buffer] -maxrate [calculated-maximum-bitrate] -preset [preset-value] -profile:v [profile-value] -tune film -pass 1 -acodec aac -b:a 128k -ac 2 -ar 48000 -af "aresample=async=1:min_hard_comp=0.100000:first_pts=0" -f mp4 -y [outputfile].mp4
ffmpeg -i [inputfile] -pix_fmt yuv420p [deinterlace] -vf "scale=[video-resolution]" -vsync 1 -threads 0 -vcodec libx264 -r [video-framerate] -g [video-framerate*2] -sc_threshold 0 -b:v [calculated-bitrate] -bufsize [calculated-buffer] -maxrate [calculated-maximum-bitrate] -preset [preset-value] -profile:v [profile-value] -tune film -pass 2 -acodec aac -b:a 128k -ac 2 -ar 48000 -af "aresample=async=1:min_hard_comp=0.100000:first_pts=0" -f mp4 -y [outputfile].mp4
Streaming VOD requires:
- A constant frame rate, to help ensure that all frames are aligned properly.
- A constant keyframe interval, also known as a group of pictures (GOP). This is important so that segments are equally sized for HLS and MPEG-DASH. It also enables bitrate switching when delivering adaptive bitrate streams.
- A bitrate-based encode, to ensure that all segments are close the same size, which helps to prevent buffering.
If you have a VOD asset that Wowza Streaming Engine has trouble streaming, use the following FFprobe commands to troubleshoot.
See keyframes are equally spaced:
ffprobe -select_streams v -show_frames -show_entries frame=pict_type -of csv $inputfile | grep -n I | cut -d ':' -f 1
See frame timing:
ffprobe -show_entries packet=pts_time,duration_time,stream_index,codec_type $inputfile > $inputfile.log
If your frame timing is inconsistent then the distance between frames will be off. This can affect both segment duration and keyframe placement.