使用Java和FFempeg批量转码B站缓存下来的列表视频,成MP4格式
文章目錄
- 一、需求
- 二、現(xiàn)有辦法
- 三、困惑
- 四、思路
- 五、動(dòng)手
- 附:源代碼
一、需求
??用手機(jī)從B站上緩存了一個(gè)列表的視頻,但是它的音視頻文件是分開(kāi)的,而且只能用B站APP打開(kāi)。想轉(zhuǎn)成mp4格式在電腦上播放。
二、現(xiàn)有辦法
??單個(gè)視頻倒也好辦,到該目錄下cmd運(yùn)行下面這行代碼:
ffmpeg -i video.m4s -i audio.m4s -codec copy output.mp4??馬上就可以完事。
三、困惑
??但問(wèn)題在于,一個(gè)列表的視頻有二十多個(gè),一個(gè)一個(gè)打開(kāi)似乎太啰嗦,而且小破站放緩存文件的方式很陰間:
??點(diǎn)進(jìn)一個(gè)視頻的目錄后,還要再進(jìn)一個(gè)叫80的子目錄才能看到源文件。點(diǎn)來(lái)點(diǎn)去實(shí)在麻煩,而且點(diǎn)開(kāi)六七個(gè)后退出來(lái)找下一個(gè),面對(duì)這一大堆以九位數(shù)字命名的目錄,很可能找不到自己上一個(gè)是點(diǎn)了哪個(gè)文件夾。
四、思路
??于是我想,能不能用Java的File IO流來(lái)幫我們做點(diǎn)事。把這個(gè)過(guò)程自動(dòng)化一下。
??我們已經(jīng)知道如何手動(dòng)處理單個(gè)音視頻合并。如果我們用Java運(yùn)行bat文件,bat文件的命令包括移動(dòng)到指定目錄和執(zhí)行ffmpeg(上面那行代碼),這不就是相當(dāng)于上面手動(dòng)運(yùn)行cmd的效果了嗎?
??那么如何擴(kuò)展到多文件呢?只要我們能得到其他源文件的路徑,就能如法炮制,得到mp4文件。如果能把該路徑自動(dòng)化寫(xiě)出來(lái),那這整個(gè)過(guò)程不就自動(dòng)化了嗎?
??我們觀察到所有源文件的路徑中只有c_341981036這一部分是不同的,那我們就重點(diǎn)解決它。
??正好Java File類提供給了我們一個(gè)方法file.list(),可以得到當(dāng)前目錄下的子文件和子文件夾,這正是我們需要的:
??然后遍歷該數(shù)組,數(shù)組元素和兩頭兩尾固定的路徑拼接一下,就得到了一個(gè)完整的路徑。至此核心問(wèn)題已經(jīng)解決。
五、動(dòng)手
編寫(xiě)相關(guān)代碼跑一個(gè)看看:
??這樣做之后,已得到了所有視頻的mp4文件,隨便打開(kāi)一個(gè)文件夾看一下:
??確實(shí)已經(jīng)生成了mp4文件。不過(guò)生成的mp4文件分散在各個(gè)子目錄里面,如果要去手動(dòng)復(fù)制出來(lái)了話依然很繁瑣。我們不妨在生成bat文件的時(shí)候就指定一個(gè)固定的輸出目錄:
"ffmpeg -i video.m4s -i audio.m4s -codec copy D:\\Videos\\createdMp4\\output" + i +".mp4"??這樣我們就得到了一打開(kāi)就是mp4文件的文件夾。理想很美好,實(shí)際上我這么做,只得到兩個(gè)mp4文件代碼就不干活了,也不報(bào)錯(cuò),就在那卡著,狀態(tài)還是運(yùn)行狀態(tài)。不管他,就讓它分散在自己的子目錄里,我們換個(gè)辦法,用IO流把文件復(fù)制一份到指定目錄:
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音視頻。每個(gè)視頻的路徑:d:\\a\\c_xxxxx(隨機(jī)數(shù))\\80\\video.m4s d:\\a\\c_xxxxx(隨機(jī)數(shù))\\80\\audio.m4s* 思路:1.讀取到某一條視頻的信息* 2.運(yùn)行命令行工具:ffmpeg -i video.m4s -i audio.m4s -codec copy output.mp4* 3.放到循環(huán)執(zhí)行,遍歷所有文件。(功能已經(jīng)做完了)(做到這一步相當(dāng)于是半自動(dòng)洗衣機(jī))* 4.優(yōu)雅的把mp4文件取出來(lái),放到一個(gè)文件夾中,最好文件名是有順序的。(全自動(dòng)洗衣機(jī))*/ 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"; // 黑窗口最多同時(shí)打開(kāi)15個(gè) // 當(dāng)視頻不長(zhǎng)“嗖”一下就搞定時(shí)沒(méi)關(guān)系,當(dāng)任務(wù)量大單個(gè)視頻長(zhǎng)的時(shí)候,用此方法可以當(dāng)甩手掌柜,自己完全不用管事。if (i % 15 == 0){Thread.sleep(2000);}createBat();run_cmd("cmd /c" + batPath);copy(i);System.out.println("正在處理第 " + i + "個(gè)視頻");}}/*** 復(fù)制文件集中到指定目錄*/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();}/*** 創(chuàng)建bat文件*/public static void createBat() throws IOException{//在當(dāng)前目錄創(chuàng)建bat文件BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(batPath));//把命令寫(xiě)入bat文件bufferedWriter.write("cd " + mp4Path);bufferedWriter.newLine();bufferedWriter.write("ffmpeg -i video.m4s -i audio.m4s -codec copy output.mp4");bufferedWriter.newLine();//執(zhí)行完后退出黑窗口bufferedWriter.write("exit");bufferedWriter.close();}/*** 運(yùn)行bat文件* 感謝_Line_老哥,提供了Java打開(kāi)批處理文件的辦法。*/public static void run_cmd(String strcmd) throws IOException, InterruptedException {Runtime rt = Runtime.getRuntime();Process ps = null;//該對(duì)象的exec()方法指示Java虛擬機(jī)創(chuàng)建一個(gè)子進(jìn)程執(zhí)行指定的可執(zhí)行程序// 并返回與該子進(jìn)程對(duì)應(yīng)的Process對(duì)象實(shí)例。ps = rt.exec(strcmd);//等待子進(jìn)程完成再往下執(zhí)行。ps.waitFor();//銷毀子進(jìn)程ps.destroy();} }總結(jié)
以上是生活随笔為你收集整理的使用Java和FFempeg批量转码B站缓存下来的列表视频,成MP4格式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Python 二进制文件流转图片
- 下一篇: Java泛型面试也能虐暴你