You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pyglet动画转视频:np.frombuffer尺寸不符致reshape失败

解决Pyglet帧捕获转视频时的reshape失败问题

问题根源

你遇到的核心问题是np.frombuffer的默认解析类型不对:

  • buffer是字节流,每个RGBA通道占1字节,总字节数应为width * height * 4
  • 但np.frombuffer(buffer)默认会把字节解析成float64类型(每个元素占8字节),导致数组长度变成总字节数 / 8,和预期的像素通道数完全不匹配,reshape步骤直接报错。

另外你的代码还有两个隐藏问题:

  1. writer初始化在on_draw之后,第一次调用writer.append_data时writer还未定义,会触发NameError
  2. image_data.pitch(每行实际字节数)可能不等于width*4(GPU内存对齐要求),直接用窗口宽度reshape会导致画面变形

修正后的代码

import numpy as np
import pyglet
import imageio.v2 as iio

# 初始化窗口
window = pyglet.window.Window(480, 480)

label = pyglet.text.Label('Hello, world',
                          font_name='Times New Roman',
                          font_size=36,
                          x=window.width//2, y=window.height//2,
                          anchor_x='center', anchor_y='center')

# 提前初始化视频写入器,必须放在on_draw之前
writer = iio.get_writer("out.mp4", fps=30)  # 指定帧率,避免视频播放速度异常

@window.event
def on_draw():
    window.clear()
    label.draw()

    # 捕获帧
    color_buffer = pyglet.image.get_buffer_manager().get_color_buffer()
    image_data = color_buffer.get_image_data()
    buffer = image_data.get_data("RGBA", image_data.pitch)

    # 关键:指定dtype=np.uint8,按1字节解析每个通道数据
    frame = np.frombuffer(buffer, dtype=np.uint8)
    # 按pitch计算每行像素数,再裁剪到窗口实际宽度,解决内存对齐问题
    frame = frame.reshape((image_data.height, image_data.pitch//4, 4))[:, :image_data.width, :]
    # 去掉Alpha通道(MP4大多不支持RGBA格式),转成RGB
    frame_rgb = frame[..., :3]
    # 写入视频帧
    writer.append_data(frame_rgb)

# 程序退出时关闭写入器,保证视频文件完整
def on_close():
    writer.close()
window.push_handlers(on_close)

pyglet.app.run()

关键修改说明

  • 指定dtype=np.uint8:让numpy按1字节解析每个通道,数组长度与实际像素通道数匹配
  • 处理pitch对齐:用image_data.pitch计算每行实际像素数,再裁剪到窗口宽度,避免画面变形
  • 提前初始化writer:解决第一次调用append_data时的未定义错误
  • 添加关闭回调:程序退出时关闭写入器,防止视频文件损坏
  • 转RGB格式:适配MP4等主流视频容器的格式要求

内容的提问来源于stack exchange,提问作者user16451053

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 02:22:55