Как правильно вызвать mkvmerge из Java-программы? - PullRequest
0 голосов
/ 31 октября 2018

У меня есть несколько сотен эпизодов аниме, для которых я хотел бы объединить имеющиеся у меня субтитры и видеофайлы. Я решил написать короткую программу на Java, чтобы пройтись по файлам и объединить их. Видеофайлы называются Bleach1.mkv, а субтитры - Bleach1.srt. Чтобы избежать возможных проблем с пробелами, файлы сохраняются в корне моего диска C. Код, который я написал ниже.

В соответствии с документацией для mkvmerge, соответствующий вызов командной строки будет выглядеть так: «mkvmerge -o remux_Bleach1.mkv Bleach1.mkv Bleach1.srt». Я подтвердил, и это на самом деле работает. Я запускаю программу Java из другой папки, поэтому я использовал абсолютные пути для каждого из файлов.

Команда в моем коде печатается как «[C: \ Program Files \ MKVToolNix \ mkvmerge.exe, -o C: \ Bleach \ remux_Bleach_1.mkv C: \ Bleach \ Bleach_1.mkv C: \ Bleach \ Bleach_1 .srt] "

Сообщение об ошибке, которое я получаю от mkvmerge: «Ошибка: имя файла назначения не указано».

Я не совсем понимаю, как передаются аргументы при использовании ProcessBuilder - что я делаю не так?

import org.apache.commons.io.FilenameUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.List;


public class Main {

    private static String mkvmergePath = "C:\\Program Files\\MKVToolNix\\mkvmerge.exe";

    public static void mergeVideoAndSubtitles(final File folder, String videoExtension, String subtitleExtension) {
        for (final File fileEntry : folder.listFiles()) {
            if (fileEntry.isDirectory()) {
                listFilesForFolder(fileEntry, videoExtension, subtitleExtension);
                // for each mkv file that is found
            } else if (FilenameUtils.isExtension(fileEntry.getName(), videoExtension)) {
                String parentFolderPath = fileEntry.getParentFile().getPath();
                String baseName = FilenameUtils.getBaseName(fileEntry.getName());
                String outputFileAbsolutePath = parentFolderPath + "\\remux_" + fileEntry.getName();
                String inputVideoAbsolutePath = fileEntry.getAbsolutePath();
                String inputSubtitleAbsolutePath = parentFolderPath + "\\" + baseName + "." + subtitleExtension;
                String param1 = "-o " + outputFileAbsolutePath + " " + inputVideoAbsolutePath + " " + 
                        inputSubtitleAbsolutePath;
//                String param2 = "--default-track \"und\"";
//                String param3 = "--language 0:und " + baseName + "." + subtitleExtension + "\"";
//                System.out.println(param1);
//                System.out.println(param2);
//                System.out.println(param3);
                BufferedReader br = null;
                String line;
                try {
                List<String> list = new ArrayList<String>();
                list.add(mkvmergePath);
                list.add(param1);

                ProcessBuilder build = new ProcessBuilder(list);
                    System.out.println(build.command());
                                        Process process = build.start();

                    InputStream is = process.getInputStream();
                    InputStreamReader isr = new InputStreamReader(is);
                    br = new BufferedReader(isr);

                    while ((line = br.readLine()) != null) {
                        System.out.println(line);
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }


            }
        }
    }

    public static void main(String[] args) {
        final File folder = new File("C:\\Bleach");
        mergeVideoAndSubtitles(folder, "mkv", "srt");
    }
}

1 Ответ

0 голосов
/ 14 апреля 2019

Я писал аналогичную программу на Go и столкнулся с той же ошибкой. Очевидно, пробелы в аргументах (например, --language 0: eng) вызывают эту проблему. Я попытался разделить их на отдельные аргументы, и это похоже на работу:

public static void main(String[] args) throws IOException {
    String mkvmerge = "C:\\Program Files\\MKVToolNix\\mkvmerge.exe";

    List<String> command = new ArrayList<String>();
    command.add(mkvmerge);

    command.add("--ui-language");
    command.add("en");
    command.add("--output");
    command.add("D:\\Dump\\test.mkv");
    command.add("--language");
    command.add("0:eng");
    command.add("--default-track");
    command.add("0:yes");
    command.add("--language");
    command.add("1:eng");
    command.add("--default-track");
    command.add("1:yes");
    command.add("--language");
    command.add("2:eng");
    command.add("D:\\Dump\\Game of Thrones\\Game.of.Thrones.S01.1080p.WEB-DL.DD5.1.H.264-SA89[rartv]\\Game.of.Thrones.S01E01.Winter.Is.Coming.1080p.WEB-DL.DD5.1.H.264-SA89.mkv");
    command.add("--sub-charset");
    command.add("0:UTF-8");
    command.add("--language");
    command.add("0:eng");
    command.add("D:\\Dump\\Game of Thrones\\Game.of.Thrones.S01.1080p.WEB-DL.DD5.1.H.264-SA89[rartv]\\Subs\\Game.of.Thrones.S01E01.Winter.Is.Coming.1080p.WEB-DL.DD5.1.H.264-SA89.srt");
    command.add("--track-order");
    command.add("0:0,0:1,0:2,1:0");

    ProcessBuilder builder = new ProcessBuilder(command);
    builder.redirectErrorStream(true);
    Process process = builder.start();

    BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
    String line = null;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
}

По какой-то причине это не относится к пробелам в путях. Это работает и в го.

...