diff --git a/common/src/main/java/ctbrec/recorder/FFmpeg.java b/common/src/main/java/ctbrec/recorder/FFmpeg.java index b6bb9ebc..bd1e4a19 100644 --- a/common/src/main/java/ctbrec/recorder/FFmpeg.java +++ b/common/src/main/java/ctbrec/recorder/FFmpeg.java @@ -1,67 +1,43 @@ package ctbrec.recorder; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStream; +import java.lang.ProcessBuilder.Redirect; import java.nio.file.Files; import java.util.Arrays; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadFactory; import java.util.function.Consumer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import lombok.extern.slf4j.Slf4j; -import ctbrec.io.DevNull; -import ctbrec.io.ProcessStreamRedirector; import ctbrec.recorder.download.ProcessExitedUncleanException; +@Slf4j public class FFmpeg { - - private static final Logger LOG = LoggerFactory.getLogger(FFmpeg.class); - - private static ScheduledExecutorService processOutputReader = Executors.newScheduledThreadPool(2, createThreadFactory("FFmpeg output stream reader")); - private Process process; private boolean logOutput = false; private Consumer startCallback; private Consumer exitCallback; private File ffmpegLog = null; - private OutputStream ffmpegLogStream; - private ProcessStreamRedirector stdoutRedirector; - private ProcessStreamRedirector stderrRedirector; private FFmpeg() {} - private static ThreadFactory createThreadFactory(String name) { - return r -> { - Thread t = new Thread(r); - t.setName(name); - t.setDaemon(true); - t.setPriority(Thread.MIN_PRIORITY); - return t; - }; - } - public void exec(String[] cmdline, String[] env, File executionDir) throws IOException { - LOG.trace("FFmpeg command line: {}", Arrays.toString(cmdline)); - process = Runtime.getRuntime().exec(cmdline, env, executionDir); - afterStart(); + log.trace("FFmpeg command line: {}", Arrays.toString(cmdline)); + // process = Runtime.getRuntime().exec(cmdline, env, executionDir); + + var builder = new ProcessBuilder(cmdline); + // builder.environment().(); + builder.directory(executionDir); + setupLogging(builder); + process = builder.start(); + + notifyStartCallback(process); } - private void afterStart() throws IOException { - notifyStartCallback(process); - setupLogging(); - } public void shutdown(int exitCode) throws IOException { - LOG.trace("FFmpeg exit code was {}", exitCode); - ffmpegLogStream.flush(); - ffmpegLogStream.close(); - stdoutRedirector.setKeepGoing(false); - stderrRedirector.setKeepGoing(false); + process.destroy(); + log.trace("FFmpeg exit code was {}", exitCode); notifyExitCallback(exitCode); if (exitCode != 1) { if (ffmpegLog != null && ffmpegLog.exists()) { @@ -72,28 +48,27 @@ public class FFmpeg { } } - private void setupLogging() throws IOException { + private void setupLogging(ProcessBuilder builder) throws IOException { if (logOutput) { if (ffmpegLog == null) { ffmpegLog = File.createTempFile("ffmpeg_", ".log"); } - LOG.trace("Logging FFmpeg output to {}", ffmpegLog); + log.trace("Logging FFmpeg output to {}", ffmpegLog); ffmpegLog.deleteOnExit(); - ffmpegLogStream = new FileOutputStream(ffmpegLog); + + builder.redirectOutput(Redirect.to(ffmpegLog)); + builder.redirectErrorStream(true); } else { - ffmpegLogStream = new DevNull(); + builder.redirectOutput(Redirect.DISCARD); + builder.redirectError(Redirect.DISCARD); } - stdoutRedirector = new ProcessStreamRedirector(processOutputReader, process.getInputStream(), ffmpegLogStream); - stderrRedirector = new ProcessStreamRedirector(processOutputReader, process.getErrorStream(), ffmpegLogStream); - processOutputReader.submit(stdoutRedirector); - processOutputReader.submit(stderrRedirector); } private void notifyStartCallback(Process process) { try { startCallback.accept(process); } catch(Exception e) { - LOG.error("Exception in onStart callback", e); + log.error("Exception in onStart callback", e); } } @@ -101,7 +76,7 @@ public class FFmpeg { try { exitCallback.accept(exitCode); } catch(Exception e) { - LOG.error("Exception in onExit callback", e); + log.error("Exception in onExit callback", e); } } @@ -110,7 +85,7 @@ public class FFmpeg { try { shutdown(exitCode); } catch (IOException e) { - LOG.error("Error while shutting down FFmpeg process", e); + log.error("Error while shutting down FFmpeg process", e); } return exitCode; }