如何从Java程序中正确调用mkvmerge?

如何从Java程序中正确调用mkvmerge?,java,mkv,Java,Mkv,我有几百集的动画,我想把字幕和视频文件合并成一个。我决定编写一个简短的Java程序来循环文件并合并它们。视频文件名为漂白剂1.mkv,副标题为漂白剂1.srt。为了避免任何潜在的空间问题,文件保存在我的C驱动器的根目录下。我写的代码如下 根据mkvmerge的文档,适当的命令行调用将是“mkvmerge-o remux_bleat1.mkv bleat1.mkv bleat1.srt”。我已经证实,这确实有效。目前我正在从不同的文件夹运行java程序,所以我对每个文件都使用了绝对路径 我的代码中

我有几百集的动画,我想把字幕和视频文件合并成一个。我决定编写一个简短的Java程序来循环文件并合并它们。视频文件名为漂白剂1.mkv,副标题为漂白剂1.srt。为了避免任何潜在的空间问题,文件保存在我的C驱动器的根目录下。我写的代码如下

根据mkvmerge的文档,适当的命令行调用将是“mkvmerge-o remux_bleat1.mkv bleat1.mkv bleat1.srt”。我已经证实,这确实有效。目前我正在从不同的文件夹运行java程序,所以我对每个文件都使用了绝对路径

我的代码中的命令输出为“[C:\ProgramFiles\MKVToolNix\mkvmerge.exe,-o C:\bleat\remux\u bleat\u 1.mkv C:\bleat\bleat\u 1.mkv C:\bleat\bleat\u 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");
    }
}
import org.apache.commons.io.FilenameUtils;
导入java.io.*;
导入java.util.ArrayList;
导入java.util.List;
公共班机{
私有静态字符串mkvmergePath=“C:\\Program Files\\MKVToolNix\\mkvmerge.exe”;
公共静态无效合并视频和字幕(最终文件夹、字符串视频扩展名、字符串字幕扩展名){
对于(最终文件条目:folder.listFiles()){
if(fileEntry.isDirectory()){
listFilesForFolder(文件条目、视频扩展名、字幕扩展名);
//对于找到的每个mkv文件
}else if(FilenameUtils.isExtension(fileEntry.getName(),videoExtension)){
字符串parentFolderPath=fileEntry.getParentFile().getPath();
字符串baseName=FilenameUtils.getBaseName(fileEntry.getName());
字符串outputFileAbsolutePath=parentFolderPath+“\\remux\uUx”+fileEntry.getName();
String inputVideoAbsolutePath=fileEntry.getAbsolutePath();
字符串inputSubtitleAbsolutePath=parentFolderPath+“\\\”+baseName+“”+subtitleExtension;
字符串param1=“-o”+输出文件绝对路径+“”+输入视频绝对路径+“”
输入路径;
//字符串param2=“--默认曲目\“und\”;
//String param3=“--语言0:und”+baseName+“+subtitleExtension+”\”;
//System.out.println(参数1);
//系统输出打印LN(参数2);
//系统输出打印LN(参数3);
BufferedReader br=null;
弦线;
试一试{
列表=新的ArrayList();
添加列表(mkvmergePath);
列表。添加(参数1);
ProcessBuilder build=新的ProcessBuilder(列表);
System.out.println(build.command());
Process=build.start();
InputStream=process.getInputStream();
InputStreamReader isr=新的InputStreamReader(is);
br=新的缓冲读取器(isr);
而((line=br.readLine())!=null){
系统输出打印项次(行);
}
}捕获(IOE异常){
e、 printStackTrace();
}
}
}
}
公共静态void main(字符串[]args){
最终文件夹=新文件(“C:\\漂白”);
合并视频和字幕(文件夹“mkv”、“srt”);
}
}

我在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);
    }
}
publicstaticvoidmain(字符串[]args)引发IOException{
字符串mkvmerge=“C:\\Program Files\\MKVToolNix\\mkvmerge.exe”;
List命令=new ArrayList();
添加命令(mkvmerge);
添加(“--ui语言”);
命令。添加(“en”);
add(“--output”);
添加(“D:\\Dump\\test.mkv”);
add(“--language”);
命令。添加(“0:eng”);
add(“--default track”);
命令。添加(“0:是”);
add(“--language”);
命令。添加(“1:eng”);
add(“--default track”);
命令。添加(“1:是”);
add(“--language”);
命令。添加(“2:eng”);
command.add(“D:\\Dump\\Game of.Thrones\\Game.so1.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”);
add(“--sub charset”);
添加命令(“0:UTF-8”);
add(“--language”);
命令。添加(“0:eng”);
command.add(“D:\\Dump\\Game of.shornes\\Game.so1.1080p.WEB-DL.DD5.1.H.264-SA89[rartv]\\Subs\\Game.of.shornes.S01E01.Winter.Is.Coming.1080p.WEB-DL.DD5.1.H.264-SA89.srt”);
添加(“--track order”);
添加(“0:0,0:1,0:2,1:0”);
ProcessBuilder=新的ProcessBuilder(命令);
builder.redirectErrorStream(true);
Process=builder.start();
BufferedReader=新的BufferedReader(新的InputStreamReader(process.getInputStream());
字符串行=null;
而((line=reader.readLine())!=null){
系统输出打印项次(行);
}
}
由于某些原因,这不适用于路径中的空间。
这在围棋中也适用。

完全不是答案:这是Java的笨拙和样板。我宁愿在这里使用一些python脚本,或者嘿:windows powershell脚本……可能会更好,但我尝试快速完成(显然失败了),我不知道如何编写powershell脚本(或python).