ffmpeg下载地址:http://www.ffmpeg.org/download.html

这里下载Windows版本的:ffmpeg-4.2.2-win64-static.zip

解压后bin目录下的内容(假设在D盘的bin路径下):
哔哩哔哩视频与音频文件流合并

public class App {
    // ffmpeg.exe全路径
    private static final String FFMPEG_PATH = "D:/bin/ffmpeg.exe";

    public static void main(String[] args) throws Exception {
        File rootDir = new File("C:"+File.separator+"哔哩哔哩"+File.separator+"xx视频");
        String outputDir = rootDir.getAbsolutePath() + File.separator + "out";
        // 开始处理文件
        renameAndCopyFile(rootDir, outputDir);
    }

    /**
     * 具体合成视频函数
     * 
     * @param videoInputPath    原视频的全路径
     * 
     * @param audioInputPath    音频的全路径
     * 
     * @param videoOutPath      视频与音频结合之后的视频的路径
     */
    public static void convetor(String videoInputPath, String audioInputPath, String videoOutPath) throws Exception {
        Process process = null;
        InputStream errorStream = null;
        InputStreamReader inputStreamReader = null;
        BufferedReader br = null;
        try {
            // ffmpeg命令
            String command = FFMPEG_PATH + " -i " + videoInputPath + " -i " + audioInputPath
                    + " -c:v copy -c:a aac -strict experimental " + " -map 0:v:0 -map 1:a:0 " + " -y " + videoOutPath;
            process = Runtime.getRuntime().exec(command);
            errorStream = process.getErrorStream();
            inputStreamReader = new InputStreamReader(errorStream);
            br = new BufferedReader(inputStreamReader);
            // 用来收集错误信息的
            String str = "";
            while ((str = br.readLine()) != null) {
                System.out.println(str);
            }
            process.waitFor();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                br.close();
            }
            if (inputStreamReader != null) {
                inputStreamReader.close();
            }
            if (errorStream != null) {
                errorStream.close();
            }
        }
    }

    // 遍历每个路径,找到entry.json文件所在路径
    public static void renameAndCopyFile(File rootDir, String outputDir) throws Exception {
        File dir = rootDir;
        if (dir == null) {
            return;
        }
        File[] files = dir.listFiles();
        if (files == null || files.length == 0) {
            return;
        }
        String fileName = null;
        for (File f : files) {
            if (f.isFile()) {
                fileName = f.getName();
                if ("entry.json".equalsIgnoreCase(fileName)) {
                    String jsonStr = FileUtils.readFileToString(f, "UTF-8");
                    if (jsonStr == null || jsonStr.isEmpty()) {
                        return;
                    }
                    Entry entry = getEntry(jsonStr);
                    // 文件名
                    String realFileName = entry.page_data.part;
                    realFileName = realFileName.replaceAll("\\s+", "-");
                    // 开始迭代查找视频和音频文件,并将数据拷贝到其他地方
                    List fileList = findVideoAudioFile(dir);
                    // 对文件进行合并
                    String videoInputPath = null;
                    String audioInputPath = null;
                    String videoOutPath = outputDir + File.separator + realFileName + ".mp4";
                    System.out.println(videoOutPath);
                    for (FileInfo info : fileList) {
                        if ("audio.m4s".equalsIgnoreCase(info.fileName)) {
                            audioInputPath = info.file.getAbsolutePath();
                        }
                        if ("video.m4s".equalsIgnoreCase(info.fileName)) {
                            videoInputPath = info.file.getAbsolutePath();
                        }
                    }
                    convetor(videoInputPath, audioInputPath, videoOutPath);
                }
            } else if (f.isDirectory()) {
                renameAndCopyFile(f, outputDir);
            }
        }
    }

    private static List findVideoAudioFile(File dir) {
        if (dir == null) {
            return new ArrayList();
        }
        File[] files = dir.listFiles();
        if (files == null || files.length == 0) {
            return new ArrayList();
        }
        List result = new ArrayList();
        String fileName = null;
        for (File f : files) {
            if (f.isFile()) {
                fileName = f.getName();
                if (fileName.endsWith("m4s")) {
                    result.add(new FileInfo(f));
                }
            } else if (f.isDirectory()) {
                result.addAll(findVideoAudioFile(f));
            }
        }
        return result;
    }

    public static class FileInfo {
        public File file;
        public String fileName;

        public FileInfo(File file) {
            this.file = file;
            if (file != null) {
                fileName = file.getName();
            }
        }
    }

    // 解析bilibili下的entry.json文件
    public static Entry getEntry(String jsonText) {
        return JSON.parseObject(jsonText, Entry.class);
    }

    public static class PageData {
        // 文件名
        public String part;
    }

    public static class Entry {
        // 是否已经下载完成
        public boolean is_completed;
        // 课程名/专辑名
        public String title;
        // 文件信息
        public PageData page_data;
    }
}

ffmpeg相关指令:http://ffmpeg.org/ffmpeg.html