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

基于Pygame的视频播放器CPU占用率异常波动问题求助

Pygame视频播放器CPU占用波动问题调试求助

我用Pygame开发了一款视频播放器,通过缓冲区将视频文件的numpy帧数组流传输至Pygame窗口。当前遇到异常:CPU占用率随时间逐步升高(程序运行变慢),随后又骤降(程序运行提速),内存占用基本保持稳定,因此排除内存泄漏可能。这种波动导致视频播放变为幻灯片模式,幅度远超预期,恳请协助调试。

可通过文末代码复现问题,任意.mp4文件均可。程序会输出log.txt文件用于调试,我的调试发现如下:

初始几秒处理速度较快:

[12:13:31] (Variable: current_frame) 1
[12:13:31] (Variable: len(frame_buffer)) 3
[12:13:31] (Process time) 0.08 seconds

约30秒内持续变慢,处理时间峰值达约0.5秒:

[12:14:07] (Variable: current_frame) 154
[12:14:07] (Variable: len(frame_buffer)) 3
[12:14:07] (Process time) 0.53 seconds

随后处理时间回落至初始水平:

[12:14:11] (Variable: current_frame) 164
[12:14:11] (Variable: len(frame_buffer)) 3
[12:14:11] (Process time) 0.1 seconds

这是我用matplotlib绘制的约1000帧的趋势图:
帧处理时间趋势图

import cv2
import time
import pygame
import gc
from datetime import datetime

#Debug code
runtime_start = str(datetime.now().strftime("%H-%M-%S"))
def log(prefix, message):
    string = "[" + str(datetime.now().strftime("%H:%M:%S")) + "] " + "(" + str(prefix) + ") " + str(message)
    print(string)
    with open(file="log" + runtime_start + ".txt", mode="a", encoding="utf-8") as file:
        file.write(string + "\n")
### ### ###

#Globals
buffer_size = 3
frame_buffer = []
### ### ###

#Functions
def loadVideoFileToMemory(file):
    """
    Load file to memory.
    """
    global capture
    capture = cv2.VideoCapture(file)
    

def getFrameFromVideo(file, frame_number):
    """
    Captures a frame from the loaded file, returns a numpy image array.
    """
    #capture = cv2.VideoCapture(file)
    capture.set(cv2.CAP_PROP_POS_FRAMES, frame_number)
    ret, frame = capture.read()

    #image = ImageTk.PhotoImage(image=Image.fromarray(frame))
    image = cv2.resize(frame, (90*6, 160*6))
    del frame
    gc.collect()
    return image
    
def setBuffer(start_frame):
    """
    Fills the buffer at a set starting frame before playing the video.
    """
    frame_buffer.clear()
    for i in range(buffer_size):
        frame_buffer.append(getFrameFromVideo("test_video1.mp4", start_frame + i))

def updateBuffer(frame):
    """
    Updates frame_buffer, deals with garabge collection.
    """
    del frame_buffer[0]
    gc.collect()
    if len(frame_buffer) < buffer_size: #Limits to buffer size
        frame_array = getFrameFromVideo("test_video1.mp4", frame + buffer_size)
        frame_buffer.append(frame_array)
        del frame_array
        gc.collect()


def displayImageToPygame(image, window):
    """
    Converts a numpy image array to a pygame surface and blits to screen.
    """
    window.blit(pygame.surfarray.make_surface(image), (0,0))


def createPygameWindow():
    """
    Creates a pygame window, sets the frame_buffer and starts the main thread.
    """
    window = pygame.display.set_mode((160*6, 90*6))
    pygame.display.flip()

    #Starting frame
    current_frame = 0
    setBuffer(current_frame) #Set from this position
    displayImageToPygame(frame_buffer[0], window) #Show starting frame


    pygameThread(window, current_frame)


def pygameThread(window, current_frame):
    """
    Main thread. Plays the video.
    """
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

    
        timer_start = time.time() #DEBUG: PROCESSING TIME

        current_frame += 1
        displayImageToPygame(frame_buffer[1], window)
        updateBuffer(current_frame)
        pygame.display.flip()

        #DEBUG: POST TO LOG.TXT
        log("Variable: current_frame", current_frame)
        log("Variable: len(frame_buffer)", len(frame_buffer))
        timer_end = time.time() #DEBUG: PROCESSING TIME
        log("Process time",  str(round(timer_end - timer_start, 2)) + " seconds")
        ###
### ### ###
       
video_file = "test_video1.mp4" #Replace this with a path to an .mp4 file.
loadVideoFileToMemory(video_file)
createPygameWindow()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 16:40:30