在python中優雅的使用ffmpeg:PyAV

ffmpeg是強大的多媒體處理工具,堪稱多媒體處理的瑞士軍刀,涵蓋了大量的多媒體處理工具。可是ffmpeg是由純C語言寫成,對於python用戶來講使用難度較高,爲此今天向你們推薦一款在python中使用ffmpeg的開發包:PyAVpython

PyAV提供了ffmpeg的python接口,但實際是它只是使用ffmpeg作後端,使用Cython封裝了ffmpeg的接口,因此實際調用的仍是ffmpeg。後端

PyAV安裝

PyAV是跨平臺的,能夠根據本身的環境和平臺選擇安裝。微信

Windows安裝PyAV:ide

在Windows下安裝PyAV能夠參照博客https://blog.csdn.net/Dillon2015/article/details/91358179工具

Mac OS X和Ubuntu上安裝PyAV:ui

在Mac OS X和Ubuntu上安裝PyAV能夠參考官網安裝方法編碼

PyAV使用

PyAV提供了很是方便的接口使開發者不須要太關注底層細節。url

視頻分割爲獨立的幀

有的時候作處理時須要將一段視頻按幀分紅一張張圖像,在ffmpeg命令行中只須要一條命令:spa

ffmpeg –i test.avi –r 1 –f image2 image-%3d.jpeg.net

-r表示每秒提取圖像的數量,若是等於幀率則會將全部幀都提取出來。

在PyAV中實現一樣的功能也很簡單,

import av

container = av.open(path_to_video)
#path_to_video是你視頻的路徑
for frame in container.decode(video=0):
   frame.to_image().save('frame-%04d.jpg' % frame.index)

保存關鍵幀

對於一個視頻序列來講並非全部幀都同樣,由於視頻編碼在進行幀間預測時會出現相互參考的狀況,若是一幀的參考幀丟失或損壞了那麼這一幀就沒法正確解碼,因此對於那些用於被參考的幀就相對更重要了。

av.video.frame.VideoFrame類中有一個屬性key_frame用以表示該幀是不是關鍵幀。

import av
import av.datasets

container = av.open(path_to_video)
# Signal that we only want to look at keyframes.
stream = container.streams.video[0]
stream.codec_context.skip_frame = 'NONKEY'

for frame in container.decode(stream):
   # We use `frame.pts` as `frame.index` won't make must sense with the `skip_frame`.
   frame.to_image().save(
       'night-sky.{:04d}.jpg'.format(frame.pts),
       quality=80,
  )

在以上代碼中跳過了非關鍵幀,將全部關鍵幀保存下來。

視頻轉封裝

視頻轉封裝就是改變視頻的封裝格式而不改變其中視頻流、音頻流等的編碼方式,例如從mp4->mkv

過程以下:

import av
import av.datasets

input_ = av.open(path_to_video)
output = av.open('remuxed.mkv', 'w')

# Make an output stream using the input as a template. This copies the stream
# setup from one to the other.
in_stream = input_.streams.video[0]
out_stream = output.add_stream(template=in_stream)

for packet in input_.demux(in_stream):
   # We need to skip the "flushing" packets that `demux` generates.
   if packet.dts is None:
       continue

   # We need to assign the packet to the new stream.
   packet.stream = out_stream
   output.mux(packet)

output.close()

生成視頻

PyAV還能夠和numpy配合使用,直接將ndarray轉換成視頻幀,使得對幀的操做更加靈活和方便。

from __future__ import division

import numpy as np

import av

duration = 4
fps = 24
total_frames = duration * fps
container = av.open('test.mp4', mode='w')
stream = container.add_stream('mpeg4', rate=fps)
stream.width = 480
stream.height = 320
stream.pix_fmt = 'yuv420p'

for frame_i in range(total_frames):
   img = np.empty((480, 320, 3))
   img[:, :, 0] = 0.5 + 0.5 * np.sin(2 * np.pi * (0 / 3 + frame_i / total_frames))
   img[:, :, 1] = 0.5 + 0.5 * np.sin(2 * np.pi * (1 / 3 + frame_i / total_frames))
   img[:, :, 2] = 0.5 + 0.5 * np.sin(2 * np.pi * (2 / 3 + frame_i / total_frames))

   img = np.round(255 * img).astype(np.uint8)
   img = np.clip(img, 0, 255)

   frame = av.VideoFrame.from_ndarray(img, format='rgb24')
   for packet in stream.encode(frame):
       container.mux(packet)

#Flush stream
for packet in stream.encode():
   container.mux(packet)

#Close the file
container.close()

以上代碼生成了一段480x320幀率24fps的視頻。

小結

PyAV還要更多更強大的功能,感興趣的小夥伴能夠本身安裝試試哦。

點讚美一輩子,關注富三代!

本文分享自微信公衆號 - Video Coding(gh_17eb8f3e0fe7)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索