Mac使用Java代码调用ffmpeg命令合成音视频

最近在用B站移动端帮助老婆大人找一些视频,并缓存到本地。结果老婆大人要求把视频拷出来,想保存下来。方便以后直接观看。

 

结果打开B站移动端APP的保存的视频地方,打算把视频拷出来,看一下视频能否正常播放。结果悲剧了。发现其文件格式如下。安卓移动端的路径如下:

进入安卓根目录,再进安卓Android文件夹下面的data文件夹,在里面找到tv.danmaku.bili的文件夹,再进入就能找到你所下载视频的文件夹了。

 

补充一下,下面的图是通过handshaker的软件,方面电脑直接查看或管理安卓文件。非常方便。个人非常推荐。

进入文件夹84810483下面,看到的文件价格如下,这是我下载的文件截图。addio.m4s这个文件的视频是音频文件,而video.m4s文件这是对应的视频文件。下面先来一波操作。先手动把文件修改一下。比如把addio.m4s变化成addio.mp3,那么对应的把video.m4s变成video.mp4。然后用播放器打开mp3文件。可以的正常播放。

我们再来打开mp4文件。哈哈,😁,悲剧了。没有声音。怎么办??????

 

然而作为程序员,怎么能不知道怎么办呢?这不是造火箭啊!!!!

 

打算偷个懒,去找个视频转换的软件来处理,把音频文件和视频文件合并,这样就大功告成了。然而理想很美好,现实很骨感啊!

 

这个时候我们的伟大的ffmpeg登场,如果读者不知道ffmpeg是什么,可以自行去百度。

 

下面就不废话了。直接给出答案。

 

简约的答案:前提示你的电脑上已经安装配置好ffmpeg。(如果没有安装,请接着看下面的ffmpeg安装。),然后用下面的命令。

 

ffmpeg -i audio.mp3 -i video.mp4 -vcodec copy -acodec copy output.mp4

 

执行上面的命令后会输出out的文件。然后用播放器打开,正常是图像和声音同步,完美。

当然,上面的已经解决了相对的少量的转换,如果像下面的这么多的文件,难道手动一个一个改文件名,然后用命令一个一个执行转换。那不是疯了。下面就有请答案2上场。答案2上场前先教大家安装ffmpeg。我的是Mac操作系统,只能暂时以此来说明,对应的window环境如何安装大家也可以百度一下。

 

Mac环境安装ffmpeg

 

1. lame 下载解压缩 https://pan.baidu.com/s/1cyrvJ3yMfQPO7eGHpcRtJw

密码:4q0w 进入目录后依次执行,为了避免权限问题直接加sudo

1.1 ./configure

1.2 sudo make

1.3 sudo make install

 

2. 下载解压缩

ffmpeg连接   https://pan.baidu.com/share/init?surl=zXad879R669zJLZ5gf6aGw

密码:f94b

进入目录后依次执行

2.1 ./configure --enable-libmp3lame

2.2 sudo make

2.3 sudo make install

 

安装好之后关掉终端,重新打开输入 ffmpeg -version 成功后的信息如下。

而如果不能识别ffmpeg命令。则是有可能是环境没有配置,我安装的时候就是出现了这个情况。

环境的配置如下:使用命令打开.bash_profile文件,添加路径。

sudo vim .bash_profile

添加:export PATH=/usr/local/bin:$PATH

保存,再用命令: source .bash_profile使配置修改生效。

 

接着下面回到答案2。如果有很多文件,我们使用代码来进行批量重名。因为涉及比较多的操作步骤。步骤如下:

步骤1:批量修改文件个属性。即修改文件的格式。

调用以下方法前

调用重名方法后:

从调用结果上面来看。结果是有效的。文件全部重新命名并且改了格式

方法如下:扫描文件和修改文件名字

 public static void scanFileAndReviseName(String dir,ExecutorService executor) {
        File file = new File(dir);
        if (file.isDirectory()) {//判断File对象对应的目录是否存在
            File[] ss = file.listFiles();//获得目录下所有的文件名
            for (File s : ss) {//循环遍历,依次输出
                if (s.isFile()) {
                    if (s.getName().equals("audio.m4s")) {
                        rename(s, "audio.mp3");
                    }

                    if (s.getName().equals("video.m4s")) {
                        rename(s, "video.mp4");
                    }
                } else {
                    scanFileAndReviseName(s.getAbsolutePath(),executor);
                }
            }
        }
    }
    public static boolean rename(final File file, final String newName) {
        // file is null then return false
        if (file == null) return false;
        // file doesn't exist then return false
        if (!file.exists()) return false;
        // the new name is space then return false
        // the new name equals old name then return true
        if (newName.equals(file.getName())) return true;
        File newFile = new File(file.getParent() + File.separator + newName);
        // the new name of file exists then return false
        return !newFile.exists()
                && file.renameTo(newFile);
    }

步骤2. 按照最外面的文件名称,再次重命名文件,如对应的295,296,分别要改成295.mp3,295.mp4,296.mp3,296.mp4, 这是为了方便后面的皮批量合成视频。

 public static void useParentName(String dir) {
        File file = new File(dir);
        if (file.isDirectory()) {
            //判断File对象对应的目录是否存在
            File[] ss = file.listFiles();//获得目录下所有的文件
            for (File s : ss) {
                //循环遍历,依次输出
                if (s.isFile()) {
                    String name = getParentFileName(s.getAbsolutePath());//抽取父类的文件名
                    String audio = name+ ".mp3";
                    String video = name+ ".mp4";
                    if (s.getName().equals("audio.mp3")) {
                        System.out.println(s.getAbsoluteFile() + " && 文件名字:" + s.getName());
                        rename(s, audio);
                    }
                    if (s.getName().equals("video.mp4")) {
                        System.out.println(s.getAbsoluteFile() + " && 文件名字:" + s.getName());
                        rename(s, video);
                    }
                } else {
                    useParentName(s.getAbsolutePath());
                }
            }

        }
    }
    public static String getParentFileName(@NotNull String path){
        String name = "";
        String[] sArray=path.split("/") ;
        if (sArray.length>5){
            name = sArray[5]; //根据日志文件的格式视情况来获取
        }
        return name;
    }

运行后的效果图如下:可以看到里面的文件夹名字和外边的集数对应上了。

步骤3.我们需要把文件移到和249平行的目录下面。这里就涉及到在Java里面调用命令。经过我自己验证后,是可以在java里面这样执行命令的。效果图如下

该方法如下:

 public static void moveFile(String source,String dest) {
        Process process = null;
        String command = "mv " + " " + source+ " " + dest;
        System.out.println(" ***** cmd "+ command);

        List<String> processList = new ArrayList<String>();

        try {
            process = Runtime.getRuntime().exec(command);
            BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line = "";
            while ((line = input.readLine()) != null) {
                processList.add(line);
            }
            input.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        for (String line : processList) {
            System.out.println(line);
        }
    }

步骤4. 调用ffmpeg命令来执行合成文件,因为合成文件是个耗时操作,因为需要建立一个线程,放到线程里面去执行。执行后的效果如下

使用了如下的方法,代码如下

ExecutorService executor = Executors.newFixedThreadPool(30);

MixFile("/Users/lulanqin/Desktop/84810483/",executor);///Users/lulanqin/Desktop/84810483 是自己放文件的地方

//执行混合音视频的方法

 public static void MixFile(String dir,ExecutorService executor) {
        File file = new File(dir);
        if (file.isDirectory()) {
            //判断File对象对应的目录是否存在
            File[] ss = file.listFiles();//获得目录下所有的文件
            for (File s : ss) {
                //循环遍历,依次输出
                if (s.isFile()) {
                    if (s.getName().contains("mp3")) {
                        String temp = s.getAbsolutePath();
                        int index = temp.lastIndexOf(".m");
                        if (index>0){
                            String sbu = temp.substring(0,index);
                            String sound1 = sbu+".mp3";
                            String video1 = sbu+".mp4";
                            String out = sbu+"_1.mp4";
                            executor.submit(new MyRunnable(sound1,video1,out));
                        }
                    }
                }
            }
        }
    }

//执行的线程

 public static class MyRunnable implements Runnable{
        String sound1,video1,out;
        public MyRunnable( String mp3, String mp4, String outPut) {
            this.sound1 = mp3;
            this.video1 = mp4;
            this.out = outPut;
        }

        @Override
        public void run() {
            transFormMp4Video(sound1,video1,out);
        }
    }

//最核心的方法,启动命令来合成视频并输出视频。

 public static void transFormMp4Video(String mp3, String mp4, String outPut) {
        StringBuilder stringBuilder = new StringBuilder();
        try {
            String cmd = "ffmpeg -i " + mp3 + " -i " + mp4 + " -vcodec copy -acodec copy " + outPut + "";
            Process process = Runtime.getRuntime().exec(cmd);
            process.waitFor();
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line = "";
            while ((line = reader.readLine()) != null) {
                stringBuilder.append(line).append("\n");
            }
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值