Ffmpeg is a powerful multimedia processing tool, the Swiss Army knife of multimedia processing, covering a large number of multimedia processing tools. However, FFMPEG is written in pure C language, which is difficult for Python users to use. Therefore, today I recommend a development package that uses FFMPEG in Python: PyAV
PyAV provides the Python interface to FFMPEG, but in reality it only uses FFMPEG as the back end, and uses Cython to encapsulate ffMPEG’s interface, so ffMPEG is still called.
PyAV installation
PyAV is cross-platform and can be installed according to your environment and platform.
Install PyAV on Windows:
Under the Windows installation PyAV can consult blogs blog.csdn.net/Dillon2015/…
Install PyAV on Mac OS X and Ubuntu:
To install PyAV on Mac OS X and Ubuntu, refer to the official installation instructions
PyAV use
PyAV provides a very convenient interface so that developers don’t need to pay too much attention to the low-level details.
The video is split into separate frames
Sometimes when you need to break a video into frames, you only need one command on the FFmpeg command line:
Ffmpeg -i test.avi -r 1 -f image2 image-%3d.jpeg
-r indicates the number of images extracted per second. If it is equal to the frame rate, all frames are extracted.
It’s easy to do the same thing in PyAV,
import av
container = av.open(path_to_video)
#path_to_video is the path to your video
for frame in container.decode(video=0):
frame.to_image().save('frame-%04d.jpg' % frame.index)
Copy the code
Save keyframe
For a video sequence, not all frames are the same, because the video encoding is cross-referenced in inter-frame prediction. If the reference frame of a frame is lost or damaged, the frame cannot be decoded correctly, so it is more important for those frames that are used for reference.
In av. Video. Frame. VideoFrame class has an attribute key_frame to whether the frame is the key frames.
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.)Copy the code
In the above code, non-key frames are skipped and all key frames are saved.
Video encapsulation
Video to encapsulation is to change the encapsulation format of video without changing the encoding mode of video stream, audio stream, etc., such as from MP4 -> MKV
The process is as follows:
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()
Copy the code
Generate video
PyAV can also be used in conjunction with Numpy to convert NDARray directly into video frames, making frame manipulation more flexible and convenient.
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()
Copy the code
The above code generates a 480×320 video at 24fps.
summary
PyAV also has more powerful features, interested partners can install their own try oh.
If you are interested, please pay attention to wechat public account Video Coding