1. 程式人生 > 實用技巧 >利用OpenCV進行H264視訊編碼的簡易方式

利用OpenCV進行H264視訊編碼的簡易方式

在Python下,利用pip安裝預編譯的opencv庫,並實現h264格式的視訊編碼。

1. 安裝OpenCV

$ pip install opencv-python

建議在python虛擬環境下安裝,不容易產生相互影響。

2. 程式碼示例

讀取筆記本自帶攝像頭,並儲存為視訊的最簡實現。

import cv2

def main():
    output_path = './output.avi'
    vc = cv2.VideoCapture(0)
    ret, frame = vc.read()
    w = int(vc.get(cv2.CAP_PROP_FRAME_WIDTH))
    h = int(vc.get(cv2.CAP_PROP_FRAME_HEIGHT))
    fps = vc.get(cv2.CAP_PROP_FPS)
    
    fourcc = cv2.VideoWriter_fourcc('H', '2', '6', '4')
    # fourcc = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')
    # fourcc = cv2.VideoWriter_fourcc('H', 'E', 'V', 'C')
    vw = cv2.VideoWriter(output_path, fourcc, fps, (w, h), True)
    while ret:
        vw.write(frame)
        ret, frame = vc.read()
        cv2.imshow('frame', frame)
        if cv2.waitKey(5) & 0xFF == ord('q'):
            cv2.destroyAllWindows()
            return -1

if __name__ == '__main__':
    main()

2.1 預設編碼

預編譯的opencv,預設支援XVID格式的編碼,但是不支援H264。

如果將# fourcc = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')註釋取消,程式可以正常執行並儲存視訊。

2.2 H264支援

按示例程式碼配置為H264編碼,會顯示如下錯誤提示。攝像頭可以採集到影象,但是不能正常儲存為視訊。

Failed to load OpenH264 library: openh264-1.8.0-win64.dll
Please check environment and/or download library: https://github.com/cisco/openh264/releases

[libopenh264 @ 000001e7a96ddec0] Incorrect library version loaded
Could not open codec 'libopenh264': Unspecified error

根據提示,到Github庫中搜索對應的動態庫。

注意選取對應的版本。我安裝的OpenCV版本為4.4.0.42,提示需要的動態庫為openh264-1.8.0-win64.dll,在Release頁中找到對應的版本,將下載獲得的dll檔案解壓並放在與py檔案同級的工程目錄下。

不同OpenCV版本可能需要的支援庫版本也不同,沒有測試,注意看提示就行。

如果考慮通用性也可以將dll所在的路徑加入環境變數Path中。

本示例實現是在Windows平臺下,Linux下應該也是類似的操作,下載對應的h264支援庫檔案,並加入到PATH能夠搜尋到的地址。

重新執行程式,可以正常顯示影象,並儲存為視訊檔案。

用Potplayer之類的播放器開啟,可以在屬性中看到,編碼格式的相關資訊:

 視訊編碼: H264 - Native D3D9 DXVA Decoder(VLD)

2.3 H265支援

想著用同樣的方法嘗試一下H265編碼。

# fourcc = cv2.VideoWriter_fourcc('H', 'E', 'V', 'C')註釋取消,發現如下錯誤提示:

OpenCV: FFMPEG: tag 0x43564548/'HEVC' is not found (format 'avi / AVI (Audio Video Interleaved)')'

看起來目前預編譯版本的OpenCV是不支援H265編碼的。如果要用H265編碼,需要從原始碼編譯,並在編譯過程中新增對應的支援庫。看到一篇帖子有介紹,目前還沒有驗證。