use library redirects for ffmpeg output
This commit is contained in:
parent
e6ccb9b66c
commit
a003f84e70
|
@ -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<Process> startCallback;
|
||||
private Consumer<Integer> 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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue