Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 当前如何在Pygame中播放视频?_Python_Pygame_Media Player - Fatal编程技术网

Python 当前如何在Pygame中播放视频?

Python 当前如何在Pygame中播放视频?,python,pygame,media-player,Python,Pygame,Media Player,我希望在我的游戏中添加视频(如剪切场景或动画菜单屏幕) 我四处看了看,pygame似乎不再支持视频播放了,所以我想知道是否有其他方法可以让视频在我的游戏中很好地集成,比如让视频在后台播放,让pygame元素(开始按钮等)在前台播放。这里有一个例子(我找不到原始链接)使用和另一个python模块通过管道对帧进行解码,并将其通读到PyGame中进行显示。我复制了一段代码片段(我想是这样),然后忘记了它 我现在已经采用了这种技术来制作一个视频精灵。它使用FFMPEG解码(并重新缩放)视频流,在精灵更新

我希望在我的游戏中添加视频(如剪切场景或动画菜单屏幕)


我四处看了看,pygame似乎不再支持视频播放了,所以我想知道是否有其他方法可以让视频在我的游戏中很好地集成,比如让视频在后台播放,让pygame元素(开始按钮等)在前台播放。

这里有一个例子(我找不到原始链接)使用和另一个python模块通过管道对帧进行解码,并将其通读到PyGame中进行显示。我复制了一段代码片段(我想是这样),然后忘记了它

我现在已经采用了这种技术来制作一个
视频精灵
。它使用FFMPEG解码(并重新缩放)视频流,在精灵
更新()
期间读取视频流以获得下一帧

这是一个非常粗糙的实现,但我希望它能让您了解可能的情况。虽然如果PyGame能够自己播放视频会很好,但至少这种方法会将视频解码和重新缩放交给一个子进程,希望它能在另一个CPU上运行

(编辑:添加了视频结束处理程序和正确的FPS控制)

显然,因为它只是视频流,所以没有声音。但是出于所有的意图和目的,它只是另一个精灵。当视频用完时,我们捕捉到错误并变黑


注意:有时当我运行此命令时,它会破坏Linux中的终端回音。我怀疑这与子进程和/或管道有关。运行
reset
可以修复此问题。这似乎是子进程的常见问题。

我编写了一个代码,它似乎与moviepy配合得很好,我的灵感来自于


这里的优点是视频的速度正确

你需要声音吗?是的,但我认为这不会是一个问题,因为有pygame混音器,所以不,这不一定是一个要求,但如果有它的话还是不错的。我已经试着按原样运行代码(在self.proc中添加shell=True,更改了我的视频目录)但我有一些问题,首先:ffmpeg没有被识别为一个内部命令。我想我并没有真正理解ffmpeg的内容,我使用本教程安装了一个ffmpeg python模块:虽然由于您没有导入此模块,这看起来很奇怪,但无论如何它都不起作用。下一个错误在第33行ValueError:缓冲区长度不等于格式和分辨率大小"@notproplayer3-它直接使用FFMPEG可执行文件对视频进行解码,选项会导致它输出数千个代表像素的RGB字节三元组。因此,您只需为它提供
FFMPEG.exe
的路径,这可能类似于
C:\\Downloads\\FFMPEG.exe
/usr/bin/FFMPEG
等。我将对此进行调查测试缓冲区长度并在必要时进行编辑。这绝对是可行的,非常感谢您花时间帮助我,我真的很感激
import pygame
import subprocess

# Window size
WINDOW_WIDTH    = 600
WINDOW_HEIGHT   = 400
WINDOW_SURFACE  = pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE

DARK_BLUE = (   3,   5,  54)

### initialisation
pygame.init()
pygame.mixer.init()
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), WINDOW_SURFACE )
pygame.display.set_caption("Video Sprite")


class VideoSprite( pygame.sprite.Sprite ):
    FFMPEG_BIN = "/usr/bin/ffmpeg"   # Full path to ffmpeg executable

    def __init__(self, rect, filename, FPS=25 ):
        pygame.sprite.Sprite.__init__(self)
        command = [ self.FFMPEG_BIN,
                    '-loglevel', 'quiet',
                    '-i', filename,
                    '-f', 'image2pipe',
                    '-s', '%dx%d' % (rect.width, rect.height),
                    '-pix_fmt', 'rgb24',
                    '-vcodec', 'rawvideo', '-' ]
        self.bytes_per_frame = rect.width * rect.height * 3
        self.proc   = subprocess.Popen( command, stdout=subprocess.PIPE, bufsize=self.bytes_per_frame*3 )
        self.image  = pygame.Surface( ( rect.width, rect.height ), pygame.HWSURFACE )
        self.rect   = self.image.get_rect()
        self.rect.x = rect.x
        self.rect.y = rect.y
        # Used to maintain frame-rate
        self.last_at     = 0           # time frame starts to show
        self.frame_delay = 1000 / FPS  # milliseconds duration to show frame
        self.video_stop  = False

    def update( self ):
        if ( not self.video_stop ):
            time_now = pygame.time.get_ticks()
            if ( time_now > self.last_at + self.frame_delay ):   # has the frame shown for long enough
                self.last_at = time_now
                try:
                    raw_image = self.proc.stdout.read( self.bytes_per_frame )
                    self.image = pygame.image.frombuffer(raw_image, (self.rect.width, self.rect.height), 'RGB')
                    #self.proc.stdout.flush()  - doesn't seem to be necessary
                except:
                    # error getting data, end of file?  Black Screen it
                    self.image = pygame.Surface( ( self.rect.width, self.rect.height ), pygame.HWSURFACE )
                    self.image.fill( ( 0,0,0 ) )
                    self.video_stop = True


### Create Video Area
video_sprite1 = VideoSprite( pygame.Rect( 100, 100, 320, 240 ), '1975_test_pattern.mp4' )
video_sprite2 = VideoSprite( pygame.Rect( 100, 100, 160,  90 ), '/home/kingsley/Videos/rocket.avi' )  # 640x360
#sprite_group = pygame.sprite.GroupSingle()
sprite_group = pygame.sprite.Group()
sprite_group.add( video_sprite1 )
sprite_group.add( video_sprite2 )

### Main Loop
clock = pygame.time.Clock()
done = False
while not done:

    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True
        elif ( event.type == pygame.MOUSEBUTTONUP ):
            # On mouse-click
            pass

    # Movement keys
    keys = pygame.key.get_pressed()
    if ( keys[pygame.K_UP] ):
        video_sprite2.rect.y -= 10
    if ( keys[pygame.K_DOWN] ):
        video_sprite2.rect.y += 10
    if ( keys[pygame.K_LEFT] ):
        video_sprite2.rect.x -= 10
    if ( keys[pygame.K_RIGHT] ):
        video_sprite2.rect.x += 10
    

    # Update the window, but not more than 60fps
    sprite_group.update()
    window.fill( DARK_BLUE )
    sprite_group.draw( window )
    pygame.display.flip()

    # Clamp FPS
    clock.tick_busy_loop(25)  # matching my video file

pygame.quit()
import moviepy.editor
import moviepy.video.fx.all
import pygame

class VideoSprite(pygame.sprite.Sprite):
    def __init__(self, rect, filename):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((rect.width, rect.height), pygame.HWSURFACE)
        self.rect = self.image.get_rect()
        self.rect.x = rect.x
        self.rect.y = rect.y
        self.video = moviepy.editor.VideoFileClip(filename).resize((self.rect.width, self.rect.height))
        self.video_stop = False

    def update(self, time=pygame.time.get_ticks()):
        if not self.video_stop:
            try:
                raw_image = self.video.get_frame(time / 1000)  # /1000 for time in s
                self.image = pygame.image.frombuffer(raw_image, (self.rect.width, self.rect.height), 'RGB')
            except:
                self.video_stop = True