@@ -0,0 +1,1709 @@
+package com.annimon.tsvc.tasks;%0A%0Aimport com.annimon.tsvc.model.FFmpegOptions;%0Aimport java.io.File;%0Aimport java.io.OutputStream;%0Aimport java.util.ArrayList;%0Aimport java.util.List;%0Aimport java.util.Scanner;%0Aimport javafx.concurrent.Task;%0A%0A/**%0A * Video processing task.%0A * %0A * @author aNNiMON%0A */%0Apublic final class FFmpegTask extends Task%3CBoolean%3E %7B%0A    %0A    private final FFmpegOptions fFmpegOptions;%0A%0A    public FFmpegTask(FFmpegOptions fFmpegOptions) %7B%0A        this.fFmpegOptions = fFmpegOptions;%0A    %7D%0A    %0A    @Override%0A    protected Boolean call() throws Exception %7B%0A        deleteOutputIfExists();%0A        %0A        final List%3CString%3E args = new ArrayList%3C%3E(10);%0A        args.add(%22ffmpeg%22);%0A        args.addAll(fFmpegOptions.buildOptionsAsList());%0A        %0A        final ProcessBuilder pb = new ProcessBuilder(args);%0A        pb.redirectErrorStream(true);%0A        updateMessage(%22Starting ffmpeg%22);%0A        final Process ffmpeg = pb.start();%0A        final Scanner out = new Scanner(ffmpeg.getInputStream());%0A        while (out.hasNextLine()) %7B%0A            if (isCancelled()) %7B%0A                // Send stop key to ffmpeg%0A                updateMessage(%22Stopping ffmpeg%22);%0A                OutputStream ostream = ffmpeg.getOutputStream();%0A                ostream.write(%22q%5Cn%22.getBytes());%0A                ostream.flush();%0A                break;%0A            %7D%0A            final String line = out.nextLine();%0A            updateMessage(line);%0A        %7D%0A        ffmpeg.waitFor();%0A        updateMessage(%22FFmpeg stopped%22);%0A        return true;%0A    %7D%0A%0A    private void deleteOutputIfExists() %7B%0A        final File destFile = new File(fFmpegOptions.getOutput());%0A        if (destFile.exists()) destFile.delete();%0A    %7D%0A%7D%0A

Add FFmpeg processing task