我上一篇文章寫了關於視頻直播點播服務器中調整關鍵幀間隔的方法,同時也發現也是有一部分的開發者是有這個需求的。我記得之前我粗略寫過I幀的判斷:H264編碼NALU結構介紹與I幀判斷方法,但也是粗略的寫了一下,本篇文章我決定就關鍵幀來做個詳細點的說明,最基本的就是——什么是關鍵幀。
關鍵幀,就是說這一幀是連接兩段不同的內容,這一幀后面的視頻內容會有新的變化或過渡;在時間軸上這一幀帶有小黑點標志;空白關鍵幀,跟關鍵幀作用相同,但是這一幀沒有內容,在時間軸上,這一幀沒有小黑點標志;在這一幀填充內容后,就變成關鍵幀了;普通幀是用來計量播放時間或過渡時間用的,不能手動設置普通幀的內容,它是播放過程中由前后關鍵幀以及過渡類型自動填充的,手動插入或刪除普通幀,會改變前后兩個關鍵幀之間的過渡時間。
視頻關鍵幀分為I幀,P幀,B幀,這里介紹下區別,也是我搜索得到的,僅供參考。I幀才是關鍵幀,P,B算不上關鍵幀。
I幀是幀內壓縮編碼得到的,通常是每個GOP組的第一幀/基礎幀,在一組中只有一個I幀,I幀所占信息量大,解碼時僅有I幀即可完整重構圖像,所以才叫關鍵幀。
P幀與B幀是幀間壓縮,P幀沒有完整圖像數據,只有與前一幀的差別信息,因此也叫預測幀,B幀則是考慮前后幀的差別(故而也叫雙向預測幀),因此B幀解碼時間最長,壓縮比最大。
那怎么提取視頻的關鍵幀呢?其實提取關鍵幀比提取視頻幀快很多倍,下面我就基於Android系統來講一下提取視頻幀的方法:
第一個參數
是傳入截取時間,只能是us(微秒)
第二個參數
OPTION_CLOSEST
在給定的時間,檢索最近一個幀,這個幀不一定是關鍵幀。
OPTION_CLOSEST_SYNC
在給定的時間,檢索最近一個同步與數據源相關聯的的幀(關鍵幀)。
OPTION_NEXT_SYNC
在給定時間之后檢索一個同步與數據源相關聯的關鍵幀。
OPTION_PREVIOUS_SYNC
在給定時間之前檢索一個同步與數據源相關的關鍵幀
這里為了提取我們想要的幀,不使用關鍵幀,所以用 OPTION_CLOSEST
public Bitmap getFrameAtTime()
//如果不加參數的話,提取第一個關鍵幀
public Bitmap getFrameAtTime() {
return getFrameAtTime(-1, OPTION_CLOSEST_SYNC);
}
/**
* 獲取視頻文件截圖
*
* @param path 視頻文件的路徑
* @return Bitmap 返回獲取的Bitmap
*/
public Bitmap getVideoThumb(String path) {
MediaMetadataRetriever media = new MediaMetadataRetriever();
media.setDataSource(path);
Bitmap frameAtTime = media.getFrameAtTime(1 * 1000 * 1000, MediaMetadataRetriever.OPTION_CLOSEST);
if (frameAtTime == null) {
frameAtTime = media.getFrameAtTime(3 * 1000 * 1000, MediaMetadataRetriever.OPTION_CLOSEST);
}
return frameAtTime;
}