0
雷鋒網(wǎng) AI 開發(fā)者按:近日,NVIDIA 開源了適用于 Python 的視頻處理框架「VideoProcessingFramework(VPF)」。該框架為開發(fā)人員提供了一個簡單但功能強大的 Python 工具,可用于硬件加速的視頻編碼、解碼和處理類等任務。
同時,由于 Python 綁定下的 C ++代碼,它使開發(fā)者可以在數(shù)十行代碼中實現(xiàn)較高的 GPU 利用率。解碼后的視頻幀以 NumPy 數(shù)組或 CUDA 設備指針的形式公開,以簡化交互過程及其擴展功能。
目前,VPF 并未對 NVIDIA Video Codec SDK 附加任何限制,開發(fā)者可充分利用 NVIDIA 專業(yè)級 GPU 的功能。
VPF 是基于 CMake 的開源跨平臺框架,它依賴于 FFmpeg 庫來進行(de)muxing 和 pybind11 項目從而構建 Python 綁定。它包含了一組開源的 C ++庫和 Python 綁定,可與其封閉源代碼 Codec SDK 進行交互。
該框架的主要功能是簡化從 Python 開發(fā) GPU 加速視頻編碼/解碼的過程,可為視頻處理任務(例如解碼,編碼,代碼轉換以及 GPU 加速的色彩空間和像素格式轉換)提供完整的硬件加速。
盡管 Python 不是性能最高的語言,但它易于使用;在 NVIDIA 發(fā)布此視頻處理框架之后,它相當于在現(xiàn)有 Video Codec SDK C ++ 堆棧周圍的 Python wrapper,將用于在 Kepler 及更高版本上基于 GPU 的視頻編碼/解碼。這使得 VPF 在利用基于 GPU 的高性能視頻加速的同時,也獲得了易于閱讀/編寫的代碼。
NVIDIA Video Codec SDK 使用效果示意圖
同時值得注意的是,VPF 還利用 NVIDIA Video Codec SDK(一套全面的 API,包括用于 Windows 和 Linux 上硬件加速視頻編碼和解碼的高性能工具,示例和文檔)來提高靈活性和性能,并為開發(fā)人員提供 Python 固有的易用性。目前,該代碼在 GitHub 上已開源。
Github 地址:
在官網(wǎng)博客宣布 VPF 時,開發(fā)者也提供了一個簡短的 Python 代碼示例,該示例使用 PyNvCodec 模塊顯示 Python 中的視頻轉碼:
import PyNvCodec as nvc
gpuID = 0
encFile = "big_buck_bunny_1080p_h264.mov"
xcodeFile = open("big_buck_bunny_1080p.h264", "wb")
nvDec = nvc.PyNvDecoder(encFile, gpuID)
nvEnc = nvc.PyNvEncoder({'preset': 'hq', 'codec': 'h264', 's': '1920x1080'}, gpuID)
while True:
rawSurface = nvDec.DecodeSingleSurface()
# Decoder will return zero surface if input file is over;
if not (rawSurface.GetCudaDevicePtr()):
break
encFrame = nvEnc.EncodeSingleSurface(rawSurface)
if(encFrame.size):
frameByteArray = bytearray(encFrame)
xcodeFile.write(frameByteArray)
# Encoder is asynchronous, so we need to flush it
encFrames = nvEnc.Flush()
for encFrame in encFrames:
encByteArray = bytearray(encFrame)
xcodeFile.write(encByteArray)
盡管這一示例的設計簡單,但 VPF 仍具有良好的性能。上面顯示的代碼轉換示例足以使 RTX 5000 GPU 上的 Nvenc 單元飽和,如下所示:
Big Buck Bunny 序列包含 14315 幀,可以在 32 秒內(nèi)進行轉碼,而無需使用任何先進的技術(例如生產(chǎn)者-消費者模式),解碼器和編碼器將在單獨的線程中啟動共享解碼器隊列,從而可以在約 447fps 的速度下進行轉碼。由于所有轉碼均在 GPU 上完成,因此沒有明顯的 CPU 負載。
VPF 中包含了多個類,其核心部分是 PyNvDecoder 和 PyNvEncoder 類,它們是與 NVIDIA Video Codec SDK 的 Python 綁定。
PyNvDecoder 和 PyNvEncoder 類支持 NV12 像素格式,所有轉換均通過 GPU 加速,并在 VRAM 內(nèi)存中完成,以提高性能。其中——
PyNvDecoder 類有五個主要方法:
DecodeSingleSurface 從輸入視頻解碼單幀,返回帶有解碼像素的 Surface。下次用戶調(diào)用此方法時,先前返回的 Surface 可能會被重用。如果未解碼幀,則解碼后的 Surface 的 GetCudaDevicePtr 方法將返回零;
DecodeSingleFram 從輸入視頻解碼單幀,返回帶有解碼像素的 NumPy 數(shù)組。下次用戶調(diào)用此方法時,將返回另一個 NumPy 數(shù)組實例。如果未解碼幀,它將返回空的 NumPy 數(shù)組。此操作將設備復制到主機內(nèi)存;
Width 返回解碼的幀寬度;
Height 返回解碼的幀高度;
PixelFormat 返回解碼的幀像素格式。
用戶使用 DecodeSingleSurface 和 DecodeSingleFrame 時,不會破壞解碼器的內(nèi)部狀態(tài)。解碼器類支持 H.264 和 H.265 編解碼器。
PyNvEncoder 類有六個方法:
EncodeSingleSurface 以原始像素獲取 NV12 Surface,對其進行編碼,然后將基本視頻比特流作為 NumPy 數(shù)組返回。編碼器是異步的,因此此方法可能會在前幾次調(diào)用時返回空數(shù)組(取決于編碼器設置),這不是編碼錯誤;
EncodeSingleFrame 以原始像素獲取 NumPy 數(shù)組,對其進行編碼,然后將基本視頻比特流作為 NumPy 數(shù)組返回。編碼器是異步的,因此此方法可能在前幾次調(diào)用時返回空數(shù)組(取決于編碼器設置);
Flush 沖洗編碼器。除非編碼器隊列中的所有原始幀都已編碼,否則它不會返回,并返回帶有基本流字節(jié)的 NumPy 數(shù)組的列表;
Width 返回編碼的幀寬度;
Height 返回編碼的幀高度;
PixelFormat 返回編碼的幀像素格式。
如果用戶使用 EncodeSingleSurface 和 EncodeSingleFrame,則不會破壞編碼器的內(nèi)部狀態(tài)。此外,PyNvEncoder 可以獲取任意分辨率的輸入幀,并在實際編碼之前即時在 GPU 上調(diào)整其大小。
編碼器類支持 H.264 和 H.265 編解碼器,并且具有較低的延遲,因此在編碼會話結束時,應調(diào)用 Flush 刷新編碼器幀隊列。
HardwareSurface 類包含一個包裝器 CUdeviceptr:
GetCudaDevicePtr 將 CUdeviceptr 返回到 CUDA 內(nèi)存對象。
對于主機和設備之間的內(nèi)存?zhèn)鬏敚袃蓚€名為 PyFrameUploader 和 PySurfaceDownloader 的類:
PyFrameUploader 用于將 NumPy 數(shù)組上傳到 GPU;
UploadSingleFrame 將一個 numpy 數(shù)組上傳到 GPU,再將句柄返回到上傳的 Surface。下次用戶調(diào)用此方法時,先前返回的 Surface 可能會被重用。
PySurfaceDownloader 類用于從 GPU 下載 Surface,它只包含一種方法:
DownloadSingleSurface 將 GPU 端 Surface 下載到 CPU 端 numpy 數(shù)組中。下次用戶調(diào)用此方法時,將返回另一個 numpy 數(shù)組實例。
PySurfaceConverter 類用于 GPU 加速的色彩空間和像素格式轉換。以下是受支持的轉化列表:
YUV420 至 NV12
NV12 到 YUV420
NV12 轉 RGB
PySurfaceConverter 類包含一種方法:
Execute 在 GPU 上執(zhí)行轉換,將句柄以輸出格式返回給 Surface。下次用戶調(diào)用此方法時,先前返回的 Surface 可能會被重用。
而 VPF 運行的主要數(shù)據(jù)類型有兩種:
用于 CPU 端數(shù)據(jù)的 NumPy 數(shù)組;
用戶透明 Surface 類,表示 GPU 端數(shù)據(jù);
由于 GPU 端內(nèi)存對象分配很復雜,并且會嚴重影響性能,因此所有歸還 Surface,并在下次調(diào)用時重用先前返回的 VPF 類方法。
與此不同的是,VPF 類方法每次被調(diào)用時都會返回新的 NumPy 數(shù)組實例。移動構造函數(shù)可避免內(nèi)存復制的運行成本。
一、RxFFmpeg
RxFFmpeg 是基于 ( FFmpeg 4.0 + X264 + mp3lame + fdk-aac ) 編譯的適用于 Android 平臺的音視頻編輯、視頻剪輯的快速處理框架。
包含:視頻拼接,轉碼,壓縮,裁剪,片頭片尾,分離音視頻,變速,添加靜態(tài)貼紙和 gif 動態(tài)貼紙,添加字幕,添加濾鏡,添加背景音樂,加速減速視頻,倒放音視頻,音頻裁剪,變聲,混音,圖片合成視頻,視頻解碼圖片等主流特色功能。
RxFFmpeg 開源地址:
二、VidGear
VidGear 是一個圍繞 OpenCV 視頻 I/O 模塊的輕量級 python 包裝器,它使用多線程 Gears(又名 API)構建,每個都有獨特的開拓性功能。
這些 API 提供了易于使用,高度可擴展的多線程包裝器,這些包裝器圍繞著許多底層的最新 python 庫,例如 OpenCV,F(xiàn)Fmpeg,picamera,pafy,pyzmq 和 python-mss ?,可以在各種設備和平臺上實現(xiàn)高速視頻幀讀取功能 。它也是 imutils 庫視頻模塊的重新實現(xiàn),修復了所有主要錯誤,并附帶了直接網(wǎng)絡流支持。
VidGear 開源地址:
VPF 博客地址:
https://devblogs.nvidia.com/vpf-hardware-accelerated-video-processing-framework-in-python/
雷鋒網(wǎng) AI 開發(fā)者 雷鋒網(wǎng)
雷峰網(wǎng)原創(chuàng)文章,未經(jīng)授權禁止轉載。詳情見轉載須知。