在視頻處理中,提取關鍵幀是一項常見的任務。下面將介紹如何基于FFmpeg和Python,結合OpenCV庫來實現從視頻中提取關鍵幀的功能。
實現思路
- 使用FFmpeg獲取視頻的關鍵幀時間戳:FFmpeg是一個強大的視頻處理工具,可以通過命令行獲取視頻中關鍵幀的時間戳信息。
- 使用OpenCV根據時間戳提取關鍵幀:OpenCV是一個廣泛使用的計算機視覺庫,可以根據視頻的時間戳讀取相應的幀。
代碼實現
import cv2
import subprocess
import redef get_keyframe_timestamps(video_path):"""使用FFmpeg獲取視頻中關鍵幀的時間戳:param video_path: 視頻文件的路徑:return: 關鍵幀的時間戳列表"""# 構建FFmpeg命令command = ['ffmpeg','-i', video_path,'-skip_frame', 'nokey','-vsync', '0','-frame_pts', '1','-loglevel', 'verbose','-f', 'image2','-']try:# 執行FFmpeg命令并捕獲輸出result = subprocess.run(command, capture_output=True, text=True, check=True)output = result.stderr# 使用正則表達式提取關鍵幀的時間戳timestamps = re.findall(r'pts_time:([\d.]+)', output)timestamps = [float(ts) for ts in timestamps]return timestampsexcept subprocess.CalledProcessError as e:print(f"FFmpeg命令執行出錯: {e.stderr}")return []def extract_keyframes(video_path, output_folder):"""根據關鍵幀的時間戳提取關鍵幀并保存到指定文件夾:param video_path: 視頻文件的路徑:param output_folder: 保存關鍵幀的文件夾路徑"""# 打開視頻文件cap = cv2.VideoCapture(video_path)if not cap.isOpened():print("無法打開視頻文件")return# 獲取關鍵幀的時間戳timestamps = get_keyframe_timestamps(video_path)for i, ts in enumerate(timestamps):# 設置視頻的播放位置到關鍵幀的時間戳cap.set(cv2.CAP_PROP_POS_MSEC, ts * 1000)ret, frame = cap.read()if ret:# 保存關鍵幀到指定文件夾output_path = f"{output_folder}/keyframe_{i}.jpg"cv2.imwrite(output_path, frame)print(f"保存關鍵幀 {output_path}")# 釋放視頻捕獲對象cap.release()if __name__ == "__main__":video_path = "your_video.mp4" # 替換為實際的視頻文件路徑output_folder = "keyframes" # 替換為實際的輸出文件夾路徑extract_keyframes(video_path, output_folder)
代碼解釋
-
get_keyframe_timestamps
函數:- 使用FFmpeg命令獲取視頻中關鍵幀的時間戳信息。
- 通過正則表達式從FFmpeg的輸出中提取關鍵幀的時間戳。
-
extract_keyframes
函數:- 打開視頻文件。
- 調用
get_keyframe_timestamps
函數獲取關鍵幀的時間戳。 - 根據時間戳設置視頻的播放位置,并讀取關鍵幀。
- 將關鍵幀保存到指定的文件夾中。
使用方法
- 確保已經安裝了FFmpeg和OpenCV庫。
- 將代碼中的
video_path
替換為實際的視頻文件路徑。 - 將代碼中的
output_folder
替換為實際的輸出文件夾路徑。 - 運行代碼,即可從視頻中提取關鍵幀并保存到指定文件夾。
注意事項
- 請確保FFmpeg的可執行文件已經添加到系統的環境變量中,否則可能會出現命令執行失敗的問題。
- 提取的關鍵幀將以
keyframe_0.jpg
,keyframe_1.jpg
, … 的格式保存到指定的文件夾中。