天天看點

用JAVA擷取視訊檔案中的幀圖檔并等比縮放

最近項目中有一個需要用JAVA擷取視訊檔案中的幀圖檔的場景,之前沒有用過JAVA對視訊檔案進行編輯,于是上網看看有沒有現成的方案,

搜尋的結果是要用到第三方的工具庫,其中有一個是開源的javacv,做過模式識别和圖像處理的肯定知道openCV,而javacv就是利用jni封裝了

調用openCV中的方法,而且javacv中還封裝了對ffmpeg的調用,于是我就決定研究一下怎麼用javacv來擷取視訊中的幀。

1、擷取相關的JAR包和DLL庫

在工程中我用到了其中幾個jar包,其實這幾個包是一次一次試出來的,因為運作時會報class not found,是以少什麼我就加什麼。具體如下:

用JAVA擷取視訊檔案中的幀圖檔并等比縮放

2、如何開始寫代碼

由于網上我沒找到用javacv截視訊的demo,後來沒辦法隻能讀源碼來猜了,于是我又找到這幾個包的源碼包,首先是從javacv包開始

用JAVA擷取視訊檔案中的幀圖檔并等比縮放

仔細看了一下,發現了一個相關的英文單詞:Grabber(抓取的意思),我猜差不多就是FFmpegFrameGrabber了,開是我打開了這個類(FFmpegFrameGrabber),發現應該是猜對了,可是源碼裡一點有幫助的注釋也沒有,但是我發現了有幀相關的方法,如下所示:

用JAVA擷取視訊檔案中的幀圖檔并等比縮放

于是我就從構造函數開始,然後一步步試,最終可以運作的代碼如下

剛開始我也不知道ff.grabFrame()是每次取一幀,而且是按順序一直往下取,是以對于有的視訊會出現幀截圖是全黑的,我還以為是我寫的有問題,後來我換了好幾個視訊測試,才發現是因為第一幀本身就是全黑的,于是我加了個過濾,把開始的幾十或幾百幀過濾掉,取中間的幀圖檔。

3、關于JNI與DLL

代碼寫好後不是立馬就能運作的,由于這個工具用的是jni,是以我們要把DLL檔案放在java.library.path裡,我是直接把ffmpeg-windows-x86.jar和opencv-windows-x86.jar裡的DLL檔案直接解壓放在C:\Program Files\Java\jdk1.7.0_60\bin裡的,對于64位和linux的環境,則要用javacv-bin檔案夾裡其他的平台jar:

用JAVA擷取視訊檔案中的幀圖檔并等比縮放
用JAVA擷取視訊檔案中的幀圖檔并等比縮放

如果DLL檔案放的不對的話,則會報類似如下的錯誤:

Caused by: java.lang.UnsatisfiedLinkError: no opencv_core249 in java.library.path

也可以在java代碼裡輸出java.library.path,然後把DLL檔案放入其中的一個。

4、測試結果

我的測試資料是一個19MB的MP4檔案,結果生成的圖檔隻有8KB:

用JAVA擷取視訊檔案中的幀圖檔并等比縮放

程式的運作結果如下:

4654

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'E:\ceshi\11.mp4':

  Metadata:

    major_brand     : isom

    minor_version   : 1

    compatible_brands: isomavc1

    creation_time   : 2010-12-18 05:39:40

  Duration: 00:03:29.54, start: 0.000000, bitrate: 744 kb/s

    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 752x424 [SAR 424:437 DAR 752:437], 680 kb/s, SAR 729:752 DAR 729:424, 25 fps, 25 tbr, 25k tbn, 50 tbc (default)

    Metadata:

      creation_time   : 2010-12-18 05:39:40

      handler_name    : GPAC ISO Video Handler

    Stream #0:1(und): Audio: aac (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 61 kb/s (default)

      creation_time   : 2010-12-18 05:39:41

      handler_name    : GPAC ISO Audio Handler