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