Originally published August 1, 2019 @ 9:25 pm
While ffmpeg
has multithreading capability, getting the best performance on multi-core systems calls for something more than just playing with the -threads
option.
I’ve seen suggestions to set the -threads
option to 1.5 the number of cores, which doesn’t make any sense. The most common choice for this option is the default 0
that means letting ffmpeg
figure out what to do. While the -threads
argument rages on, I decided to do some basic testing
The few tests below were ran on my Dell XPS 15 (9570) with an 8th-gen Intel Core i7-8750H processor having 6 cores and 12 threads. The laptop is running Windows 10 Pro with Ubuntu 18.04 LTS installed via Microsoft store. The ffmpeg
version is 4.1.3-static
.
For the first test, I picked an h264-encoded GoPro video just under 300MB in size and play time of about 2m 42s. The task was to split this video into multiple files of 15-second duration each. Thus, the first file will contain frames for 0-15s, the second file – 15-30s, and so on.
The first run is just a basic loop, running one ffmpeg
instance at a time with -threads
option set to 0
. This here is as if you were running the commands sequentially by hand, minus any delays due to you.
i=0; j=0 time while [ ${j} -le ${f_duration} ]; do ffmpeg -i "${f_path}" -threads 0 -ss ${j} -t 15 ${f_name}_${i}.${f_ext} 2>/dev/null 1>&2 (( i = i + 1 )) (( j = j + 15 )) done
I ran this a few dozen times, and the average execution time was 5m15.136s.
Now, for the second test, I decide to micromanage ffmpeg
a bit. I know I have six double-threaded cores, so, I fugured, I’ll run six ffmpeg
s at a time with the -threads
option set to 2
. This will leave ffmpeg
with no opportunity to make any decisions.
i=0; j=0 while [ ${j} -le ${f_duration} ]; do { ffmpeg -i "${f_path}" -threads 2 -ss ${j} -t 15 ${f_name}_${i}.${f_ext} & } 2>/dev/null 1>&2 pids+=($!) (( i = i + 1 )) (( j = j + 15 )) while [ $(ps -ef | grep -c "[f]fmpeg.*threads") -ge 6 ]; do sleep 5; done ; done for pid in ${pids[*]} do wait ${pid} 2>/dev/null 1>&2 done
Once again, I ran this process a couple of dozen times and the average processing time was 5m22.466s. And setting -threads
to 1.5
, as so many suggest, does nothing but increases execution time.
The conclusion here is obvious: ffmpeg
does a decent job identifying the available CPU resources and distributing the load correspondingly. Why so many people are reporting such different results? Probably because they’re using different versions of ffmpeg
on vastly different hardware. Also, they don’t really know how to analyze running processes and monitor system performance, and just run top
. And even then they don’t know how to correctly interpret performance data they’re seeing.
If you really want to get a sense of how ffmpeg
utilizes available system resources, I’d suggest you use htop
, atop
, or, better yet, install netdata
.
Experienced Unix/Linux System Administrator with 20-year background in Systems Analysis, Problem Resolution and Engineering Application Support in a large distributed Unix and Windows server environment. Strong problem determination skills. Good knowledge of networking, remote diagnostic techniques, firewalls and network security. Extensive experience with engineering application and database servers, high-availability systems, high-performance computing clusters, and process automation.