【问题标题】:ffmpeg hangs when run in a multi-threaded environmentffmpeg 在多线程环境中运行时挂起
【发布时间】:2016-05-12 09:24:34
【问题描述】:

我有一项服务需要对大量不同格式的视频进行转码。该服务产生五个线程,一个用于单个视频,每个线程使用以下命令运行 ffmpeg:

ffmpeg -i %%FILEPATH%% -vf scale=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 实例同时运行吗?是不是我当前使用的命令行中的某些东西导致了这种情况?

【问题讨论】:

  • 所以你有8个核心(真正的核心)?你如何再次测量挂起?您可以监视每个目标文件的磁盘活动吗?请注意,ffmpeg 向 stderr 写入了很多内容,因此您需要将错误流重定向到输出流,否则您会错过很多信息。
  • @UmNyobe 是的,我也尝试过重定向 stderr,但 ffmpeg 没有写入任何输出。我第一次注意到这是我的服务停止提取文件进行处理的时候。我检查了存储转码文件的输出目录,我注意到没有文件被更改。同样从顶部我看到我有 5 个 ffmpeg 进程正在运行。每个进程产生了大约 20 多个线程,其中只有一个使用了 100% 的 cpu。我让它运行了大约一个小时,然后回来,它仍然是一样的,输出文件大小保持不变,并且相同的确切线程正在使用 100% 的 CPU
  • @UmNyobe 澄清一下,当我说“单线程”时,我的意思是每个 ffmpeg 进程都有一个以 100% CPU 运行的线程
  • @UmNyobe 我重新检查了代码,似乎我错过了重定向调用。所以我更新了问题正文。
  • 你可以尝试以 100% 的使用率杀死这个进程,看看它是否有进展?是否也可以增加 ffmpeg 的详细程度(-loglevel debug)?

标签: java multithreading video ffmpeg freeze


【解决方案1】:

libx264 默认使用等于 1.5 * 逻辑内核的线程数(用于基于帧的多线程)。将它与五个实例相乘,你会得到很多线程,这只是用于编码视频流。

您可以尝试通过设置-x264opts threads=n 选项来减少每个实例上使用的线程数。

【讨论】:

  • 那会实现什么?
  • 这些线程是 CPU 密集型的。默认设置可能适用于单个命令,但由于您运行多个实例,因此您正在创建高 CPU 需求。减少单个线程数可能有助于您运行多个实例,同时避免死锁。在性能方面,您需要进行基准测试以查看发生了什么,因为太多的线程无论如何都会在 CPU 上等待。
  • 线程配置基于no。 CPU 核心数 stackoverflow.com/questions/13834692/…
猜你喜欢
  • 2013-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多