您好,登錄后才能下訂單哦!
話說2016年的直播比較火,2017年短視頻又火了。但對于開發者來說隱藏在這背后的技術才是我們所關心的,畢竟我們是靠技術吃飯的。
現在在安卓中多媒體服務比較強大,而與視頻有關的視頻基本處理技術有必要學習一下。我前段時間也在做有關視頻的一些需求,當然也涉及本文的標題內容。
經測試和研究發現在android中提取視頻圖片的方法只有MediaMetadataRetriever這個類比較靠譜簡單實用。當然OpenGL-也可以做到哈!(后者不展開介紹),
最后會把完整的demo獻上。
效果圖
技術需求
調研
先看第3個問題,這個比較簡單。主要是MediaMetadataRetriever這個系統API類。
大體意思就是:給定一個媒體文件,它能檢索/輸出一些元數據和幀。有點意思哈,它加載了動態庫media_jni,可見它是一個十分接近底層的一個類。
技術實現-視頻基本信息的獲取
看一下類結構,有一些常量,作為一線碼農,我懂你哦。
//1.初始化 mMetadataRetriever = new MediaMetadataRetriever(); //2.設置視頻源文件mMetadataRetriever.setDataSource(file.getAbsolutePath()); //3.獲取視頻的寬 String w = mMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH); //獲取視頻的高 String h = mMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT); //獲取視頻的時長,ms mMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); // 等等...一些其它屬性,比如媒體類型(3gp,mp4) ,視頻旋轉角度 //4.釋放資源,防止內存泄漏,養成好習慣 mMetadataRetrieve.release();
我自己簡單了寫了一個util類,最后會獻上。
技術實現-獲取視頻關鍵幀
直接上代碼-我懂你
public Bitmap extractFrame(long timeMs) { //第一個參數是傳入時間,只能是us(微秒) //OPTION_CLOSEST ,在給定的時間,檢索最近一個幀,這個幀不一定是關鍵幀。 //OPTION_CLOSEST_SYNC 在給定的時間,檢索最近一個同步與數據源相關聯的的幀(關鍵幀) //OPTION_NEXT_SYNC 在給定時間之后檢索一個同步與數據源相關聯的關鍵幀。 //OPTION_PREVIOUS_SYNC 在給定時間之前檢索一個同步與數據源相關聯的關鍵幀。 // Bitmap bitmap = mMetadataRetriever.getFrameAtTime(timeMs * 1000, MediaMetadataRetriever.OPTION_CLOSEST_SYNC); Bitmap bitmap = null; for (long i = timeMs; i < fileLength; i += 1000) { bitmap = mMetadataRetriever.getFrameAtTime(i * 1000, MediaMetadataRetriever.OPTION_CLOSEST_SYNC); if (bitmap != null) { break; } } return bitmap; }
實用的時候直接: Bitmap bitmap = extractFrame(0); fileLength為視頻的時長( 毫秒數),返回bitmap ,然后你用可以操作bitmap了,比如保存到sd卡上,看你愛好了。有人問:咿,怎么for循環啊?是這樣的,我遇到過有時候你傳入的0,它有時候返回的bitmap為null,找不到關鍵幀,因此你需要多次遞增1秒獲取。
那么需求一的實現也OK了,但是有一點需要注意就是展示視頻的控件的寬和高和蓋在上面的圖片的控件的寬和高一樣才有你播放的時候就連貫了。
技術實現-獲取視頻多張圖片
我相信大家都能想到需求一的for循環一下不就可以了嗎,是的,沒錯。
首先提取圖片遇到高清視頻可能耗時,我經過測試用vivo-xplay-5a ,1080高清視頻,提取一張圖片也就是mMetadataRetriever.getFrameAtTime()方法大概90-120ms之間。
for (int i = 0; i < thumbnailsCount; i++) { if (stop) { metadataRetriever.release(); break; } long time = startPosition + interval * i; if (i == thumbnailsCount - 1) { if (interval > 1000) { String path = extractFrame(metadataRetriever, endPosition - 800, OutPutFileDirPath); sendAPic(path, endPosition - 800); } else { String path = extractFrame(metadataRetriever, endPosition, OutPutFileDirPath); sendAPic(path, endPosition); } } else { String path = extractFrame(metadataRetriever, time, OutPutFileDirPath); sendAPic(path, time); } }
stop是停止提取圖片的標志,extractFrame方法就是metadataRetriever.getFrameAtTime()返回bitmap然后 bitmap.compress()返回保存到sd卡上的圖片路徑,最后sendAPic將提取的圖片路徑和時間加工為一個對象借助handler更新到UI線程中去,然后展示到recycleview上去,具體代碼可以參考demo。這里保存的圖片沒有進行壓縮,第二篇文章會具體講到。
demo地址:https://github.com/ta893115871/MediaMetadataRetrieverDemo
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。