獲取視頻截圖

最近在搞一個視頻截圖的功能,自己在探索過程中,看到很多各種各樣的解法,走了很多彎路,為了避免做相同功能的朋友們走很多彎路,我把自己解決方案,及探索過程遇到的Bug記錄下來,目前已經適配大部分機型,對于個別機型不能使用的歡迎issuses Github下載

最開始想的是直接用View截圖的方式截取當前的視頻,結果截取的來的圖片是黑屏,附上View截圖代碼

public  Bitmap convertViewToBitmap(View view){
    view.destroyDrawingCache();//銷毀舊的cache銷毀,獲取cache通常會占用一定的內存,所以通常不需要的時候有必要對其進行清理
    view.setDrawingCacheEnabled(true);//cache開啟
    view.buildDrawingCache();//創建新的緩存,獲取cache通常會占用一定的內存,所以通常不需要的時候有必要對其進行清理,在每次獲取新的,先銷毀舊的緩存
    view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));//測量view
    Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());//將緩存的view轉換為圖片
    return bitmap;
}

上面的方式只能對靜態的View進行截圖,但是動態的比如說視頻,那么截出來的圖片就是黑屏。
用SurfaceView顯示在線視頻,然后通過上面截圖方式,得到圖片是黑屏,(關于黑屏的原因大家可以去網上搜索,可以得到你想要的答案,這里就不在說了)于是我就去谷歌,各大博客上尋求解決方案,發現Android提供了MediaMetadataRetriever這個類來獲取縮放圖,于是按照這個思路去搜索,發現可以通過獲取能夠獲取當前播放的幀數,來進行截圖,以下是我的最終解決方案

/**
     * 視頻截圖代碼
     * @param url   播放的url
     * @param width 生成圖片的寬度
     * @param height    生成圖片的高度
     * @param currentVideoTime  當前播放的播放的秒數
     * @return
     */
    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    private Bitmap createVideoThumbnail(String url, int width, int height,String currentVideoTime) {
        Bitmap bitmap = null;
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        int kind = MediaStore.Video.Thumbnails.MINI_KIND;
        try {
            if (Build.VERSION.SDK_INT >= 14) {//Android4.0以上的設備,必須使用這種方式來設置源播放視頻的路徑
                retriever.setDataSource(url, new HashMap<String, String>());
            } else {
                retriever.setDataSource(url);
            }
            int millis = mMdeiaPlayer.getDuration();
            Log.e(TAG, "-----millis----" + millis);
            int pro = mMdeiaPlayer.getCurrentPosition();
            Log.e(TAG,"-----pro----"+pro);
            String timeString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
            long time = Long.parseLong(timeString) * 1000; //獲取總長度,這一句也是必須的
            long d = time*pro/millis;//計算當前播放的幀數,來截取當前的視頻
            Log.e(TAG,"---------"+d);
            bitmap = retriever.getFrameAtTime(d, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
            if (kind == MediaStore.Images.Thumbnails.MICRO_KIND && bitmap != null) {
                bitmap = ThumbnailUtils.extractThumbnail(bitmap, width, height,
                        ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
            }
        } catch (IllegalArgumentException ex) {
            // Assume this is a corrupt video file
        } catch (RuntimeException ex) {
            // Assume this is a corrupt video file.
        } finally {
            try {
                retriever.release();
                mMdeiaPlayer.start();
            } catch (RuntimeException ex) {
                // Ignore failures while cleaning up.
            }
        }

        return bitmap;
}

demo下載:https://github.com/denghuilong/screenVideo/tree/master

bug及解決方案

start called in state 4

04-05 10:58:14.169 2237-2237/demo.dhl.con.onlinevideo E/MediaPlayer: start called in state 4
04-05 10:58:14.169 2237-2237/demo.dhl.con.onlinevideo E/MediaPlayer: error (-38, 0)
04-05 10:58:14.169 2237-2237/demo.dhl.con.onlinevideo E/MediaPlayer: Error (-38,0)
04-05 10:58:14.176 2237-2250/demo.dhl.con.onlinevideo E/MediaPlayer: error (261, -1003)
04-05 10:58:14.176 2237-2237/demo.dhl.con.onlinevideo E/MediaPlayer: Error (261,-1003)

可能由于的播放的文件錯誤,或者給的url地址不能播放,可以在瀏覽器中試一下。

start called in state 1

04-05 11:50:27.346 2038-2038/demo.dhl.con.onlinevideo E/MediaPlayer: start called in state 1
04-05 11:50:27.347 2038-2038/demo.dhl.con.onlinevideo E/MediaPlayer: error (-38, 0)
04-05 11:50:27.367 2038-2050/demo.dhl.con.onlinevideo E/MediaPlayer: error (261, -1003)
04-05 11:50:27.367 2038-2038/demo.dhl.con.onlinevideo E/MediaPlayer: Error (261,-1003)

原因:

Streaming is Not supported before Android 3.0
Please test in device having above 3.0 version

解決方案:

![](http://upload-images.jianshu.io/upload_images/1479838-d821c0b136e94734.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
這是Android官網關于,Android所支持的網絡協議網絡協議
>音頻和視頻播放支持以下網絡協議:
>RTSP協議(RTP,SDP的)
>HTTP / HTTPS的進步流
>HTTP / HTTPS的現場直播議定書草案:
>MPEG-2 TS流媒體文件只
>協議版本3(的Andr??oid 4.0及以上)
>議定書“第2版(Android的3.x版)
>不支持之前的Andr??oid 3.0
>注: HTTPS不支持之前的Android 3.1。
更換一臺Android3.0以上的設備就好了

status=0x80000000

java.io.IOException: setDataSource failed.: status=0x80000000

1、 第一種解決方法

InputStream in = getResources().getAssets().open("GPSResp.dat");   

2、 第二種解決方案
將播放的視頻或者音樂因為轉換成Android所支持的格式
下面是Android所支持的格式

static const char* kNoCompressExt[] = {
    ".jpg", ".jpeg", ".png", ".gif",
    ".wav", ".mp2", ".mp3", ".ogg", ".aac",
    ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet",
    ".rtttl", ".imy", ".xmf", ".mp4", ".m4a",
    ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2",
    ".amr", ".awb", ".wma", ".wmv"
};

java.io.IOException: Prepare failed.: status=0x1

MediaPlay播放視頻的時候報下面的錯

    java.io.IOException: Prepare failed.: status=0x1

解決方案
把mediaPlayer.prepare;改成
mediaPlayer.prepareAsync();

getFrameAtTime: videoFrame is a NULL pointer

播放視頻的時候包下面的錯誤

    getFrameAtTime: videoFrame is a NULL pointer

解決方案:
視頻地址錯誤,或者 視頻損壞不能播放,檢查視頻是否正常

怎么樣對播放的視頻進行截圖

當我們使用SurfaceView的來顯示播放的視頻的時候,需要截取視頻的時候,直接使用普通View獲取截圖的方式,會是黑屏,網上很多博客提到了解決方案mHolder.lockCanvas() 獲取Canva來獲取畫布,實現截取視頻,其實是錯誤的,我照著網上的貼子做了,報了下面的錯,不知道是不是我的使用方法有錯,請網友指正

    12:58:24.690: E/BaseSurfaceHolder(719): Exception locking surface
    12:58:24.690: E/BaseSurfaceHolder(719): java.lang.IllegalArgumentException
    12:58:24.690: E/BaseSurfaceHolder(719):   at android.view.Surface.nativeLockCanvas(Native Method)
    12:58:24.690: E/BaseSurfaceHolder(719):   at android.view.Surface.lockCanvas(Surface.java:447)
    12:58:24.690: E/BaseSurfaceHolder(719):   at com.android.internal.view.BaseSurfaceHolder.internalLockCanvas(BaseSurfaceHolder.java:184)

原因:
SurfaceView 主要用來兩種用法:
1、和MediaPlay配合使用播放視頻,
2、或者和Canvas配合使用實現一些動畫
但是不能這兩種方法一起使用或者就會報上面的錯。
解決方案:
如果想要做視頻截取的話,可以使用MediaMetadataRetriever這個類截取當前播放的幀畫面,來是現實視頻截圖功能,項目貼上,代碼中有注釋

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,237評論 25 708
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,229評論 4 61
  • 前幾日,讀朋友在其工作號上發布的文章。 一場早有預謀的分手在男主偷瞄咖啡店女店主之后順利進行。事后,女主開始了另一...
    翰弦閱讀 250評論 0 0
  • 喜歡一個人是成本最低的事情,為什么我們卻越來越難喜歡一個人了呢。 昨天跟一個姐姐喝茶聊天,她說,最近總失眠,覺得最...
    英以閱讀 694評論 1 2
  • 喜歡你, 是從你送我鋼筆的那天說起, 喜歡你, 是從酒后開的玩笑說起, 喜歡你, 是從你溫柔的拒絕說起, 喜歡你,...
    蕭天閱讀 418評論 0 0