使用Java和FFempeg批量转码B站缓存下来的列表视频,成MP4格式

文章讲述了如何利用Java的FileIO和ffmpeg命令行工具,将B站缓存的分离式音视频文件批量合并成MP4格式。作者首先手动合并了一个视频作为基础,然后通过Java编程自动化处理多个视频文件,解决了目录结构复杂和文件数量多的问题,最后实现了将生成的MP4文件集中到一个固定目录的功能。
摘要由CSDN通过智能技术生成

一、需求

  用手机从B站上缓存了一个列表的视频,但是它的音视频文件是分开的,而且只能用B站APP打开。想转成mp4格式在电脑上播放。
在这里插入图片描述

二、现有办法

  单个视频倒也好办,到该目录下cmd运行下面这行代码:

ffmpeg -i video.m4s -i audio.m4s -codec copy output.mp4

  马上就可以完事。
在这里插入图片描述

三、困惑

  但问题在于,一个列表的视频有二十多个,一个一个打开似乎太啰嗦,而且小破站放缓存文件的方式很阴间:
在这里插入图片描述
在这里插入图片描述
  点进一个视频的目录后,还要再进一个叫80的子目录才能看到源文件。点来点去实在麻烦,而且点开六七个后退出来找下一个,面对这一大堆以九位数字命名的目录,很可能找不到自己上一个是点了哪个文件夹。

四、思路

  于是我想,能不能用Java的File IO流来帮我们做点事。把这个过程自动化一下。
  我们已经知道如何手动处理单个音视频合并。如果我们用Java运行bat文件,bat文件的命令包括移动到指定目录和执行ffmpeg(上面那行代码),这不就是相当于上面手动运行cmd的效果了吗?

cd D:\Videos\545686540\c_341980251\80
ffmpeg -i video.m4s -i audio.m4s -codec copy output.mp4

  那么如何扩展到多文件呢?只要我们能得到其他源文件的路径,就能如法炮制,得到mp4文件。如果能把该路径自动化写出来,那这整个过程不就自动化了吗?
  我们观察到所有源文件的路径中只有c_341981036这一部分是不同的,那我们就重点解决它。
  正好Java File类提供给了我们一个方法file.list(),可以得到当前目录下的子文件和子文件夹,这正是我们需要的:

File file = new File(headPath);
        String[] list = file.list();

  然后遍历该数组,数组元素和两头两尾固定的路径拼接一下,就得到了一个完整的路径。至此核心问题已经解决。

五、动手

编写相关代码跑一个看看:
在这里插入图片描述

  这样做之后,已得到了所有视频的mp4文件,随便打开一个文件夹看一下:
在这里插入图片描述

  确实已经生成了mp4文件。不过生成的mp4文件分散在各个子目录里面,如果要去手动复制出来了话依然很繁琐。我们不妨在生成bat文件的时候就指定一个固定的输出目录:

"ffmpeg -i video.m4s -i audio.m4s -codec copy D:\\Videos\\createdMp4\\output" + i +".mp4"

  这样我们就得到了一打开就是mp4文件的文件夹。理想很美好,实际上我这么做,只得到两个mp4文件代码就不干活了,也不报错,就在那卡着,状态还是运行状态。不管他,就让它分散在自己的子目录里,我们换个办法,用IO流把文件复制一份到指定目录:

    public static void copy(int i) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(mp4Path + "\\output.mp4"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\Videos\\createdMp4\\output" + i + ".mp4"));
        byte[] bytes = new byte[1024];
        int num = 0;
        while ((num = bis.read(bytes)) != -1){
            bos.write(bytes,0,num);
        }
        bos.close();
        bis.close();
    }

在这里插入图片描述
  至此,需求得到解决。

附:源代码
package com.serein.freedom;

import java.io.*;

/**
 * 需求:批量合并m4s音视频。每个视频的路径:d:\\a\\c_xxxxx(随机数)\\80\\video.m4s   d:\\a\\c_xxxxx(随机数)\\80\\audio.m4s
 * 思路:1.读取到某一条视频的信息
 *      2.运行命令行工具:ffmpeg -i video.m4s -i audio.m4s -codec copy output.mp4
 *      3.放到循环执行,遍历所有文件。(功能已经做完了)(做到这一步相当于是半自动洗衣机)
 *      4.优雅的把mp4文件取出来,放到一个文件夹中,最好文件名是有顺序的。(全自动洗衣机)
 */
public class Test1 {
    static String batPath = "";
    static String mp4Path = "";
    static String headPath = "D:\\Videos\\545686540\\";

    public static void main(String[] args) throws Exception {
        //得到缓存列表视频直接父目录 下所有的子目录
        File file = new File(headPath);
        String[] list = file.list();
        for (int i = 0; i < list.length; i++) {
            batPath = headPath + list[i] + "\\80\\test.bat";
            mp4Path = headPath + list[i] + "\\80";
//            黑窗口最多同时打开15个
//            当视频不长“嗖”一下就搞定时没关系,当任务量大单个视频长的时候,用此方法可以当甩手掌柜,自己完全不用管事。
            if (i % 15 == 0){
                Thread.sleep(2000);
            }
            createBat();
            run_cmd("cmd /c" + batPath);
            copy(i);
            System.out.println("正在处理第 " + i + "个视频");
        }
    }

    /**
     * 复制文件集中到指定目录
     */
    public static void copy(int i) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(mp4Path + "\\output.mp4"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\Videos\\createdMp4\\output" + i + ".mp4"));
        byte[] bytes = new byte[1024];
        int num = 0;
        while ((num = bis.read(bytes)) != -1){
            bos.write(bytes,0,num);
        }
        bos.close();
        bis.close();
    }

    /**
     * 创建bat文件
     */
    public static void createBat() throws IOException{
        //在当前目录创建bat文件
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(batPath));
        //把命令写入bat文件
        bufferedWriter.write("cd " + mp4Path);
        bufferedWriter.newLine();
        bufferedWriter.write("ffmpeg -i video.m4s -i audio.m4s -codec copy output.mp4");
        bufferedWriter.newLine();
        //执行完后退出黑窗口
        bufferedWriter.write("exit");
        bufferedWriter.close();
    }

    /**
     * 运行bat文件
     * 感谢_Line_老哥,提供了Java打开批处理文件的办法。
     */
    public static void run_cmd(String strcmd) throws IOException, InterruptedException {
        Runtime rt = Runtime.getRuntime();
        Process ps = null;
        //该对象的exec()方法指示Java虚拟机创建一个子进程执行指定的可执行程序
        // 并返回与该子进程对应的Process对象实例。
        ps = rt.exec(strcmd);
        //等待子进程完成再往下执行。
        ps.waitFor();
        //销毁子进程
        ps.destroy();
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值