为什么ffmpeg的批处理会冻结系统?

时间:2019-09-03 19:13:27

标签: java ffmpeg parallel-processing batch-processing executorservice

我需要从50多个mp4源文件中分割较小的视频块,以获得5000多个记录。每条记录可能会导致50多个源文件中的2个或3个较小的块。

确定要拾取哪个源文件的逻辑用Java编写,然后使用Runtime.getRuntime().exec()ExecutorService将其馈送到newFixedThreadPool上的private static boolean processqueue(ArrayList<String> cmds) { final ExecutorService pool; int threadsnum = Runtime.getRuntime().availableProcessors()-2; pool = Executors.newFixedThreadPool(threadsnum); for(final String cmd: cmds){ pool.execute(new Runnable() { public void run() { System.out.println(cmd); try { Runtime.getRuntime().exec(cmd); } catch (IOException e) { e.printStackTrace(); pool.shutdown(); } } }); } pool.shutdown(); // wait for them to finish for up to one minute. try { if(!pool.awaitTermination(1, TimeUnit.MINUTES)) { pool.shutdownNow(); } //Wait a while for tasks to respond to being cancelled if(!pool.awaitTermination(1, TimeUnit.MINUTES)) System.err.println("Pool did not shutdown properly"); } catch (InterruptedException e) { e.printStackTrace(); pool.shutdownNow(); //Preserve interrupt status Thread.currentThread().interrupt(); return false; } return true; } ,如下所示:

cmd

字符串ffmpeg -y -ss 00:00:00 -t 00:08 -i E:/tmp/fin12.mp4 -acodec copy -vcodec copy E:/tmp/Intermed/0136f.mp4 值是基于 split merge 要求的其中之一:

用于拆分:

ffmpeg -y -i E:/tmp/Inter/0136c0.mp4 -i E:/tmp/Inter/0136c1.mp4 -i E:/tmp/Inter/0136f.mp4 -i E:/tmp/Jingle.mp4 -i E:/tmp/wm1280.png -filter_complex "[0:v][0:a][1:v][1:a][2:v][2:a][3:v][3:a]concat=n=4:v=1:a=1[vv][a];[vv][4:v]overlay=x=0:y=H-overlay_h[v]" -map "[v]" -map "[a]" E:/tmp/final/0136.mp4

用于合并:

java.io.IOException: Cannot run program "ffmpeg": CreateProcess error=1455, The paging file is too small for this operation to complete
at java.lang.ProcessBuilder.start(Unknown Source)

首次尝试时,仅处理250条记录。并且,在随后尝试进行余额记录处理时,它抛出异常。但是,又处理了300条记录:

ExecutorService

而且,此代码经常冻结。为什么storeTranscriptonInDB: handler: index.storeTransciptInDB events: - s3: bucket: ${self:provider.environment.S3_TRANSCRIPTION_BUCKET} rules: - suffix: .json 不保留队列以处理所有记录并正常退出?我在做什么错了?

注意:我通过传递从命令行执行的相关参数,从Windows批处理脚本调用Java类。

1 个答案:

答案 0 :(得分:1)

您正在开始执行,但没有等待执行结束,因此您的线程池仅启动与命令一样多的进程。我不确定其余的try / catch正在尝试做什么。我建议您使用CountdownLatch。这是一个示例:

public static void main(String[] args) {
    List<String> cmds = Lists.newArrayList("sleep 1", "sleep 2", "sleep 3");

    final ExecutorService pool;
    int threadsnum = Runtime.getRuntime().availableProcessors() - 2;
    pool = Executors.newFixedThreadPool(threadsnum);


    CountDownLatch latch = new CountDownLatch(cmds.size());


    for (final String cmd : cmds) {
        pool.submit(() -> {
            try {
                System.out.println("to be executed: " + cmd);
                Runtime.getRuntime().exec(cmd).waitFor();
                latch.countDown();
            }
            catch (IOException e) {
                Thread.currentThread().interrupt();
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

    }

    try {
        latch.await(10, TimeUnit.SECONDS);
        if (latch.getCount() > 0) {
            System.out.println("Waited long enough. There are " + latch.getCount() + " threads still running");
        }
    }
    catch (InterruptedException e) {
        e.printStackTrace();
    }
    finally {
        pool.shutdown();
    }
    System.out.println("Completed.");

}