我有一项服务需要对大量不同格式的视频进行转码。该服务生成五个线程,一个用于单个视频,每个线程使用以下命令运行 ffmpeg:
ffmpeg -i %%FILEPATH%% -vf 比例=X:Y -ab 128k -c:a aac -movflags faststart -strict -2 -ar 22050 -r 24 -c:v libx264 -crf 25 -y %%OUTPUT.MP4%%
其中 X 和 Y 是基于原始文件方向的所需尺寸,基本上是横向的 640:trunc(ow*a/2)*2
或 trunc(oh *a/2)*2:640
用于纵向。
这是我的 ffmpeg 信息:
ffmpeg version 2.4.3-1ubuntu1~trusty6 Copyright (c) 2000-2014 the FFmpeg developers
built on Nov 22 2014 17:07:19 with gcc 4.8 (Ubuntu 4.8.2-19ubuntu1)
configuration: --prefix=/usr --extra-version='1ubuntu1~trusty6' --build-suffix=-ffmpeg --toolchain=hardened --extra-cflags= --extra-cxxflags= --libdir=/usr/lib/x86_64-linux-gnu --shlibdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --enable-shared --disable-stripping --enable-avresample --enable-avisynth --enable-fontconfig --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librtmp --enable-libschroedinger --enable-libshine --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-opengl --enable-x11grab --enable-libxvid --enable-libx265 --enable-libdc1394 --enable-libiec61883 --enable-libzvbi --enable-libzmq --enable-frei0r --enable-libx264 --enable-libsoxr --enable-openal --enable-libopencv
libavutil 54. 7.100 / 54. 7.100
libavcodec 56. 1.100 / 56. 1.100
libavformat 56. 4.101 / 56. 4.101
libavdevice 56. 0.100 / 56. 0.100
libavfilter 5. 1.100 / 5. 1.100
libavresample 2. 1. 0 / 2. 1. 0
libswscale 3. 0.100 / 3. 0.100
libswresample 1. 1.100 / 1. 1.100
libpostproc 53. 0.100 / 53. 0.100
Hyper fast Audio and Video encoder
usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...
该服务是用 Java 编写的,运行在 Ubuntu Server 14.04 上,机器是 64 位八核服务器。
这是执行ffmpeg的代码块:
try
{
ProcessBuilder procBuilder = null;
String sArgs = String.format("ffmpeg -i %s -vf scale=%s:%s -ab 128k -c:a aac -movflags faststart -strict -2 -ar 22050 -r 24 -c:v libx264 -crf 25 -y %s",
originalPath,
outWidth,
outHeight,
targetPath
);
}
String[] arrArgs = sArgs.split("\\s+");
procBuilder = new ProcessBuilder(Arrays.asList(arrArgs));
procBuilder.redirectErrorStream(true);
procBuilder.redirectOutput();
Process process = procBuilder.start();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())))
{
String line = null;
while ((line = reader.readLine()) != null)
{
System.out.println(line);
}
errorCode = process.waitFor();
}
}
catch(Throwable ex)
{
}
我当前正在生成五个线程,每个线程运行一个针对单个视频文件的 ffmpeg 实例。这在大多数情况下工作得很好,但每隔一段时间线程就会开始挂起。我从顶部注意到 ffmpeg 无限期地卡在某些文件上,其中一个线程使用 100% 的核心 CPU,并且没有取得任何进展。不同的文件类型都会发生这种情况,因为我在 mkv、avi、wmv 和 mp4 文件上注意到了这一点。
我不确定是什么导致 ffmpeg 挂起,它不会在转码过程开始时发生,ffmpeg 开始很好地转换文件,但在中间的某个地方卡住了。
现在这不是文件的问题,因为当我在同一个文件上手动尝试相同的命令时,它运行良好。而且似乎只有当同时运行多个 ffmpeg 实例时才会发生这种情况,因为我现在将服务更改为仅运行单个线程,并且它已经运行了近一个月,没有出现任何问题。
是否需要使用一个选项来允许 ffmpeg 的多个实例同时运行?是我当前使用的命令行中的某些内容导致了此问题吗?
最佳答案
libx264
默认情况下使用等于 1.5 * 逻辑核心的线程数(用于基于帧的多线程)。将其乘以五个实例,您将获得很多线程,这仅用于编码视频流。
您可以尝试通过设置 -x264optsthreads=n
选项来减少每个实例上使用的线程数。
关于java - ffmpeg 在多线程环境中运行时挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37182653/