Raspberry Pi 3b+ Video Encoding with ffmpeg libx264 and h264_omx
Note that this is a live page that will be updated regularly.
Please give your corrections and suggestions at the bottom of the page.
Constructive comments only !
Introduction
This page describes how to use ffmpeg to encode videos using the h.264 codec on the Raspberry Pi 3b+.
There are two ffmpeg h.264 encoders available for the Raspberry Pi:
- Software (CPU) based h.264 encoder libx264
- Hardware (GPU) based h.264 encoder h264_omx
libx264 provides high quality output and offers most of the x264 options. The downside is that as it is software based (i.e. it uses the CPU) it encodes at about 0.53x, i.e. a one hour video takes nearly two hours to encode,
h264_omx uses the GPU (video card) rather than the CPU and so is very fast. It encodes at about 1.2x, i.e. a one hour video takes less than one hour to encode. The output from h264_omx is inferior to that of libx264. Also the only encoding option available with h264_omx is to set the video bit rate (e.g. -b:v 3000k).
So you have a choice between a high quality, slow h.264 encoder with lots of x264 options, i.e. libx264, or a fast h.264 encoder with really just one option (setting the video bit rate) that produces inferior single pass output, i.e. h264_omx .
Recommendation
The best combination of encoding speed and video quality was obtained by using h264_omx with 2 pass encoding. The h264_omx video quality results were significantly better than using with single pass h264_omx encoding.Example 2 pass h264_omx encoding:
ffmpeg -i inputfile -c:v h264_omx -b:v 3000k -pass 1 -an -y -f mp4 /dev/null && ffmpeg -i inputfile -movflags +faststart -c:v h264_omx -b:v 3000k -pass 2 -c:a aac -b:a 256k -ac 2 -ar 48000 -y outputfilename.mp4
Adjust the video bit rate -b:v 3000k and audio bit rate -b:a 256k to taste.
2 pass encoding with h264_omx was found to be significantly faster than 1 pass encoding with libx264
As long as you have the time and patience, and your CPU doesn't overheat, then libx264 does produce superior results to h264_omx
If you require the absolutely highest possible video encoding quality in a reasonable time frame, then it is recommended to use Handbrake or ffmpeg running on Linux with an recent i7 processor.
For most user cases though, 2 pass encoding with h264_omx will produce good quality video as long as you don't need to resize the video.
Assumptions
It is assumed that you are:
- Using Raspberry Pi 3b+ (not tested with earlier Pis)
- Raspbian (Raspbian Stretch with desktop)
- You have installed ffmpeg :
sudo apt-get install ffmpeg - You have installed VLC for video testing purposes:
sudo apt-get install vlc - You have a basic familiarity with ffmpeg and the Linux bash shell.
Note that as of late 2018 VLC comes with hardware h.264 decoding enabled, thereby making it simple to watch h.264 videos on the Raspberry Pi.
Single Pass Examples
These two examples encode the first minute of the input test video Mike06.mkv (an mpeg 2 DVD file simply ripped to MKV without any codec change using MakeMKV on an i7 Linux Mint PC).
Remove -ss 00:00:00 -to 00:01:00 to encode the full video.
h264_omx
ffmpeg -i Mike06.mkv -ss 00:00:00 -to 00:01:00 -c:v h264_omx -b:v 1500k -c:a aac -b:a 256k -ac 2 -ar 48000 -y mike06-h264_omx-1500.mp4
Adjust -b:v 1500k to change the video bitrate (quality).
libx264
ffmpeg -i Mike06.mkv -ss 00:00:00 -to 00:01:00 -c:v libx264 -crf 20 -preset medium -profile:v high -level:v 4.0 -c:a aac -b:a 256k -ac 2 -ar 48000 -y mike06-libx264-crf20.mp4
In the above 1 minute test video a 12.8 MB output file corresponded to:
-c:v libx264 -crf 20
and
-c:v h264_omx -b:v 1500k
The libx264 encoder produced better video quality than h264_omx even though the output file sizes were similar. The libx264 encoding time was however more than double that of h264_omx
In another test that had a very high quality h.264 encoded input file (1920x1080) with an original bit rate around 16 MB the libx264 encoder was encoding at around 7% of original speed with -crf 20 meaning that a 1 hour encode would take 14+ hours !
This is too long to be useful and was aborted well before completion.
Not Recommended.
Using 2 pass encoding with -b:v 16000k and h264_omx produced very watchable high quality video quality.
Strongly Recommended.
The best combination of encoding speed and video quality was obtained by using h264_omx with 2 pass encoding.
The h264_omx video quality results were significantly better than using with single pass h264_omx encoding.
Example 2 pass h264_omx encoding:
ffmpeg -i inputfile -c:v h264_omx -b:v 3000k -pass 1 -an -y -f mp4 /dev/null && ffmpeg -i inputfile -movflags +faststart -c:v h264_omx -b:v 3000k -pass 2 -c:a aac -b:a 256k -ac 2 -ar 48000 -y outputfilename.mp4
Adjust the video bit rate -b:v 3000k and audio bit rate -b:a 256k to taste.
Tips
Apart from varying the video bitrate here isn't much else you can change for the h264_omx encoder.
You can NOT use h264_omx with -crf
You can ONLY use h264_omx with -b:v
You can NOT use h264_omx with -crf
You can ONLY use h264_omx with -b:v
You can also change the video dimensions but at the expense of speed, however I have not tested this option myself.
For libx264, slower presets than the default -preset medium can be used, however the encoding times become VERY long and the CPU gets extremely hot.
Not Recommended.
Not Recommended.
Adding -movflags +faststart works for both encoders and enables videos to be instantly streamed without the need to first download the entire video.
Recommended.
Recommended.
While the video profile and level for libx264 can be set up to
-profile:v high -level:v 4.0
the h264_omx encoder automatically sets High@L4
So while you can control the video profile and level for libx264, these options are not available for the h264_omx encoder.
A reasonable range for the -crf for the libx264 seems to be 20 to 23.
You can go down to -crf 16 but at the expense of significantly longer encoding times than those for -crf 20
The libx264 encoding produced the better video quality results of the two encoders using single pass encoding.
A large increase in encoding speed (from 1.2x to 2.5x) can be obtained for the h264_omx encoder by using the MP3 encoder libmp3lame in place of the Advance Audio Codec encoder aac
For example:
ffmpeg -i Mike06.mkv -ss 00:00:00 -to 00:01:00 -c:v h264_omx -b:v 1500k -c:a libmp3lame -b:a 256k -ac 2 -ar 48000 -y mike06-h264_omx-1500-mp3.mp4
The problem with using MP3, is that for mp4 containers (which contain both video and audio) Apple devices expect the audio in an mp4 container to be encoded with AAC not MP3.
Consequently mp4 files encoded with mp3 audio will not have any sound on Apple devices.
Note this does not apply to the more general user case of using MP3 in audio only files (e.g. m4a).
Consequently mp4 files encoded with mp3 audio will not have any sound on Apple devices.
Note this does not apply to the more general user case of using MP3 in audio only files (e.g. m4a).
Using the MP3 encoder libmp3lame in combination with the libx264 encoder didn't improve upon the encoding speed using aac :
ffmpeg -i Mike06.mkv -ss 00:00:00 -to 00:01:00 -c:v libx264 -crf 20 -preset medium -profile:v high -level:v 4.0 -c:a libmp3lame -b:a 256k -ac 2 -ar 48000 -y mike06-libx264-crf20-mp3.mp4
In fact the encoding with the libx264 and libmp3lame combination was actually slower than using aac !
Your results may vary.
Try it !
Your results may vary.
Try it !
Example 2 Pass Encoding Outputs from h264_omx
The original input files Mike06.mkv-Mike10.mkv are all mpeg 2 files with a video bitrate of 2MB - 3MB.
These files consist of a language tutor teaching in front of a white board.
Other than the tutor's Hawaiian shirts there isn't much detail in the video.
There isn't much movement and the original video quality is just 'fair'.
ffprobe -i Mike06.mkv
Stream #0:0(eng): Video: mpeg2video (Main), yuv420p(tv, progressive), 720x576 [SAR 64:45 DAR 16:9], 25 fps, 25 tbr, 1k tbn, 50 tbc
Stream #0:1(eng): Audio: mp2, 48000 Hz, stereo, s16p, 224 kb/s (default)
The same ffprobe results are also obtained for Mike07.mkv-Mike10.mkv
In the below ffmpeg outputs, note how the h264_omx first pass encoding takes around 4x speed and the second h264_omx pass encoding around 1.5x speed, given an overall encoding time of around 55 minutes for a 60 minute video (i.e.60 / 4 = 15 mins + 60/1.5 = 40 =55 minutes) or 0.92x speed.
This compares with around 0.5x speed for a single pass libx264 for a modest overall improvement in video quality.
frame=90864 fps= 95 q=-0.0 Lsize= 927507kB time=01:00:34.52 bitrate=2090.5kbits/s speed= 3.8x
frame=90864 fps= 35 q=-0.0 Lsize= 1043451kB time=01:00:34.56 bitrate=2351.9kbits/s speed= 1.4x
Mike07.mkv
frame=114092 fps= 98 q=-0.0 Lsize= 1178330kB time=01:16:03.64 bitrate=2115.2kbits/s speed=3.93x
frame=114092 fps= 37 q=-0.0 Lsize= 1325673kB time=01:16:03.69 bitrate=2379.6kbits/s speed= 1.5x
Mike08.mkv
frame=97683 fps=107 q=-0.0 Lsize= 997178kB time=01:05:07.28 bitrate=2090.7kbits/s speed=4.29x
frame=97683 fps= 39 q=-0.0 Lsize= 1122635kB time=01:05:07.32 bitrate=2353.7kbits/s speed=1.55x
Mike09.mkv
frame=86881 fps=106 q=-0.0 Lsize= 1170912kB time=00:57:55.20 bitrate=2760.2kbits/s speed=4.26x
frame=86881 fps= 33 q=-0.0 Lsize= 1279450kB time=00:57:55.26 bitrate=3016.0kbits/s speed=1.31x
Mike10.mkv
frame=132565 fps=106 q=-0.0 Lsize= 1738525kB time=01:28:22.56 bitrate=2685.9kbits/s speed=4.25x
frame=132565 fps= 39 q=-0.0 Lsize= 1909932kB time=01:28:22.61 bitrate=2950.7kbits/s speed=1.57x
Very High Quality Input file
The very high quality h.264 encoded input file (1920x1080) with an original bit rate of around 16 MB (briefly described above), has the following attributes:ffprobe -i VS2017.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'VS2017.mp4':
Metadata:
major_brand : mp42
minor_version : 512
compatible_brands: isomiso2avc1mp41
creation_time : 2017-12-03T09:29:42.000000Z
encoder : HandBrake 1.0.7 2017040900
Duration: 00:42:30.28, start: 0.000000, bitrate: 16300 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1920x1080 [SAR 1:1 DAR 16:9], 15961 kb/s, 29.94 fps, 29.97 tbr, 90k tbn, 180k tbc (default)
Metadata:
creation_time : 2017-12-03T09:29:42.000000Z
handler_name : VideoHandler
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 328 kb/s (default)
Metadata:
creation_time : 2017-12-03T09:29:42.000000Z
handler_name : Stereo
This very high quality input file is taken from the 2017 Victoria Secret Shanghai show.
Given the high level of detail in the clothes, skin tones, makeup and rapid onstage movement, the Victoria Secret shows provide an excellent video encoding test.
The 2 pass h264_omx encoder produced very good results when encoding this very high quality Victoria Secret 2017 input file.
By contrast, the libx264 encoder was encoding at around 7% of original speed with a quality of -crf 20 meaning that a 1 hour encode would take 14+ hours !
This is too long to be useful and was aborted well before completion.
Not Recommended.
Using 2 pass encoding with -b:v 16000k and h264_omx produced very watchable high quality video quality.
Strongly Recommended.
More Content to Follow
ffmpeg -i input.mp4 -c:v h264_omx -b:v 16000k -c:a aac -b:a 256k -ac 2 -ar 48000 -y output.mp4
ffmpeg -i input -c:v h264_omx -b:v 16000k -pass 1 -an -y -f mp4 /dev/null && ffmpeg -i input -movflags +faststart -c:v h264_omx -b:v 16000k -pass 2 -c:a aac -b:a 256k -ac 2 -ar 48000 -y output.mp4
ffmpeg -i input -c:v libx264 -crf 20 -preset medium -profile:v high -level:v 4.0 -c:a aac -b:a 256k -ac 2 -ar 48000 -y output.mp4
ffmpeg -i VS2018-CRF16-veryslow-fastdecode-web-high4-HB.mp4 -c:v h264_omx -b:v 16000k -pass 1 -an -y -f mp4 /dev/null && ffmpeg -i VS2018-CRF16-veryslow-fastdecode-web-high4-HB.mp4 -movflags +faststart -c:v h264_omx -b:v 16000k -pass 2 -c:a aac -b:a 256k -ac 2 -ar 48000 -y VS2018-ICE-16MB.mp4
ffmpeg -i Wilt\ \(1989\).mkv -movflags +faststart -c:v libx264 -crf 20 -c:a aac -b:a 256k -ac 2 -ar 48000 -y Wilt-1pass-libx264-CRF20.mp4
frame=133046 fps= 27 q=-1.0 Lsize= 876248kB time=01:28:41.72 bitrate=1348.9kbits/s speed=1.07x
Hey thanks so much for sharing. I'm just starting to learn about this and found it very useful.
ReplyDeleteI'm trying to set up an IP camera to stream its video to Youtube live which I believe uses RTMP so the video needs to be encoded.
I'm wondering if a Raspberry Pi 3 B+ would be able to works as such encoder with h264_omx and handle this job.
Do you know if it's possible and feasible in real scenario achieving a good streaming viewing experience?
I'd really appreciate any input in the matter. Thank you!