MaixPy3 播放视频

更新时间 负责人 内容 备注
2021年12月4日 Rui 初次编写文档 ----
2022年1月18日 dalaoshu 修改文档,增加效果图 ----
2022年4月24日 Coty 修改视频播放代码,修改了提供视频的尺寸 ----

实际上它是由 ffmpeg + pyav 编译而来,它们分别是什么呢?

FFmpeg 是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。

https://pyav.org/docs/develop/

PyAV 是一个用于 FFmpeg 的 python 绑定。通过容器、流、包、编解码器和帧直接和精确地访问媒体。它公开了一些数据的转换,并帮助您从其他包(例如 Numpy 和 Pillow )获取数据。

目前测试的视频格式有 mp4 和 avi,其他格式还没有进行测试,以下是我们提供的测试视频供确认效果。

如何播放视频?

这里使用的是转换后的 output_240_240.mp4 测试视频,从这里获得视频后存放到 Linux 系统的 root 目录中,将 path_to_video 的参数修改成所存放视频路径,如:'/root/output_240_240.mp4',其他视频同理,需要注意的是 v831 的性能很弱,可能最高就播放到软解 h264 30fps 了,硬解资源不被 FFmpeg 所提供。

ffmpeg 转换命令 ffmpeg -r 30 -i badapple_240_60fps.mp4 -af volume=+10dB -vf scale=240:240,setdar=1:1 output.mp4

import pyaudio, av, time
from maix import display, camera, image
path_to_video = '/root/output_240_240.mp4'

import _thread

try:
    container = av.open(path_to_video)
    ai_stream = container.streams.audio[0]
    vi_stream = container.streams.video[0]
    fifo = av.AudioFifo()
    p = pyaudio.PyAudio()
    ao = p.open(format=pyaudio.paFloat32, channels=1, rate=44100, output=True)
    audio = [p, ao, fifo]
    def play_audio(audio):
        while len(audio):
            for frame in audio[2].read_many(4096):
                audio[1].write(frame.planes[0].to_bytes())
    _thread.start_new_thread(play_audio, (audio, ) )
    for frame in container.decode(video=0, audio=0):
        if 'Audio' in repr(frame):
            frame.pts = None
            frame.time_base = None
            fifo.write(frame)
        if 'Video' in repr(frame):
            img = image.load(bytes(frame.to_rgb().planes[0]), (vi_stream.width, vi_stream.height))
            display.show(img)
finally:
    ao.stop_stream()
    ao.close()
    p.terminate()
    audio = []

如何录制视频?

2022年07月26日 根据 pyav.org 文档加源码整理如下代码,从录制编码到播放(x264 支持手机预览但解码性能低),注意该代码只在 av 9.2.0 版本的库可用,需要更新 0.5.2 系统底包的(av 8.0.3)喔(这种需要编译的包 pip 是得不到的)。


import pyaudio, av, _thread
from maix import display, camera, image
path_to_video = '/root/output_240_240.mp4'

try:
    container = av.open(path_to_video)
    ai_stream = container.streams.audio[0]
    vi_stream = container.streams.video[0]
    fifo = av.AudioFifo()
    p = pyaudio.PyAudio()
    ao = p.open(format=pyaudio.paFloat32, channels=1, rate=44100, output=True)
    audio = [p, ao, fifo]
    def play_audio(audio):
        try:
            while len(audio):
                for frame in audio[2].read_many(4096):
                    audio[1].write(frame.planes[0].to_bytes())
        except Exception as e:
            print(e)
    _thread.start_new_thread(play_audio, (audio, ) )
    for frame in container.decode(video=0, audio=0):
        if 'Audio' in repr(frame):
            frame.pts = None
            frame.time_base = None
            fifo.write(frame)
        if 'Video' in repr(frame):
            img = image.load(bytes(frame.to_rgb().planes[0]), (vi_stream.width, vi_stream.height))
            display.show(img)
finally:
    ao.stop_stream()
    ao.close()
    p.terminate()
    audio = []

试试吧,可以看到录制的是我们填充的 image 图像,打印了时间字符串。