JAVA通過URL連結獲取視訊檔案資訊(無需下載檔案)

hello龍兄發表於2019-07-22

  最近專案碰到一個大坑:APP上需要在獲取視訊列表時就獲取視訊的時長,但早期上傳的時候資料庫都沒有儲存這個資料,所以前段時間新增一個時長欄位,在上傳時手動輸入視訊時長,但是之前庫中有上萬條資料沒這個資訊,如果這樣一條一條手動輸入,人都得瘋掉。所以誰也不提不管這破事,在這之前的視訊時長資訊就讓它空在那。最近領導讓我做個按類目分類統計視訊時長資訊,和領導反映了這個問題,最終解決方案就把沒有的做0處理。在完成了這個功能後,我就在想能用什麼方式把之前的視訊時長全部給更新上去。手動輸入這個肯定時不行的,必須得java後臺來獲取錄入。但上網搜尋了無數的帖子,最終通過java實現的只有一種方法能用,那就是先要下載到本地,然後再一個一個的遍歷查詢。看著伺服器上的上萬個視訊,想想這方法就讓人頭皮發麻。

  雖然沒找到可行方法,但基本上都是用jave獲取視訊資訊的。於是就去檢視jave的官方API,瞭解到是通過FFmpeg處理多媒體檔案,接著又檢視FFmpeg的API,發現ffmpeg在命令列中使用時可以通過url獲取視訊。但使用jave工具包時獲取MultimediaInfo就必須得傳入File,可是又不能通過url建立File。於是就就反編譯jave的jar從原始碼上動手。

// 原始碼
public
MultimediaInfo getInfo(File source) throws InputFormatException, EncoderException { FFMPEGExecutor ffmpeg; ffmpeg = locator.createExecutor(); ffmpeg.addArgument("-i"); ffmpeg.addArgument(source.getAbsolutePath()); try { ffmpeg.execute(); } catch(IOException e) { throw new EncoderException(e); } MultimediaInfo multimediainfo; RBufferedReader reader = null; reader = new RBufferedReader(new InputStreamReader(ffmpeg.getErrorStream())); multimediainfo = parseMultimediaInfo(source, reader); ffmpeg.destroy(); return multimediainfo; Exception exception; exception; ffmpeg.destroy(); throw exception; }

ffmpeg傳入引數時使用的是

source.getAbsolutePath()獲取檔案的絕對路徑,所以通過url建立File在這是獲取的就是 專案路徑+url了。

然後就把傳入path修改成了url,但是執行還是出現 InputFormatException異常。好吧,那就繼續找問題吧

然後debug發現雖然修改了path,但是這路徑細看還是不對

http://v1.v.123.com\11\919\2019\zb\0181.mp4
正確的url應該是這樣的:http://v1.v.123.com/11/919/2019/zb/0181.mp4

 接著更正問題。

 if(path.indexOf("http") != -1) {
            path = source.getPath();
            path = path.split(":")[0] + "://" + path.split(":")[1].substring(1);
            path = path.replace("\\", "/");
        }

 

這次終於沒問題了,可以正常使用了。然後還有下面這個方法的呼叫,原始碼中有個獲取異常資訊的也得修改path值

multimediainfo = parseMultimediaInfo(source, reader);

 這個也和只需重複上面的操作就OK了。這樣就完全搞定了。

import lx.jave.AudioAttributes;
import lx.jave.AudioInfo;
import lx.jave.Encoder;
import lx.jave.EncoderException;
import lx.jave.EncodingAttributes;
import lx.jave.InputFormatException;
import lx.jave.MultimediaInfo;
import lx.jave.VideoInfo;
import lx.jave.VideoSize;

/**
 * jave多媒體工具類(需匯出jave  jar包) 
 * @author longxiong
 *
 */
public class JaveToolsTest {

    public static void main(String[] args) throws InputFormatException, EncoderException, Exception {

        /**
         * 獲取本地多媒體檔案資訊
         */
        // 編碼器
        Encoder encoder = new Encoder();
        File file = new File("http://*****018.mp4");
        // 多媒體資訊
        MultimediaInfo info = encoder.getInfo(file);
        // 時長資訊
        long duration = info.getDuration();
        System.out.println("視訊時長為:" + duration / 1000 + "秒");
        // 音訊資訊
        AudioInfo audio = info.getAudio();
        int bitRate = audio.getBitRate();  // 位元率
        int channels = audio.getChannels();  // 聲道
        String decoder = audio.getDecoder();  // 解碼器
        int sRate = audio.getSamplingRate();  // 取樣率
        System.out.println("解碼器:" + decoder + ",聲道:" + channels + ",位元率:" + bitRate + ",取樣率:" + sRate);
        // 視訊資訊
        VideoInfo video = info.getVideo();
        int bitRate2 = video.getBitRate();
        Float fRate = video.getFrameRate();  // 幀率
        VideoSize videoSize = video.getSize();
        int height = videoSize.getHeight();  // 視訊高度
        int width = videoSize.getWidth();  // 視訊寬度
        System.out.println("視訊幀率:" + fRate + ",位元率:" + bitRate2 + ",視訊高度:" + height + ",視訊寬度:" + width);
        }
}

 

 

雖然是比較簡單的修改,還是附上修改後的jar包吧。

連結:https://pan.baidu.com/s/1gqsfl_2Tq2swbMY-mQUQeg
提取碼:zpdh

附帶測試一下讀取效能:

單執行緒讀取20個視訊:

多執行緒(開啟了10個執行緒)讀取20個視訊:

從資料上看採用多執行緒效能還是可以的。差不多一秒鐘就能讀取一個了。不過幾千上萬的資料就不知道會不會崩了。下次有空在測試一下。

相關文章