ffmpeg是强大的多媒体处理工具,堪称多媒体处理的瑞士军刀,涵盖了大量的多媒体处理工具。可是ffmpeg是由纯C语言写成,对于python用户来讲使用难度较高,为此今天向你们推荐一款在python中使用ffmpeg的开发包:PyAVpython
PyAV提供了ffmpeg的python接口,但实际是它只是使用ffmpeg作后端,使用Cython封装了ffmpeg的接口,因此实际调用的仍是ffmpeg。后端
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的视频。
小结
点赞美一辈子,关注富三代!
本文分享自微信公众号 - Video Coding(gh_17eb8f3e0fe7)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。