3

Pygame 1.x has a movie module which makes playing movies pretty straightforward. The internet is full of variations of the answer provided in this SO question

However, I'm using Pygame 2, and it appears that the movie module has been removed. Or maybe just not implemented yet? I can't find a reference to it in the current docs, nor any examples online.

I found this example of using pygame.Overlay with pymedia, but it appears that pymedia does not run on Python 3.

I'm new to the Python ecosystem and don't know all the nooks and crannies and idiomatic tools. I'm hoping someone might be able to point me in the right direction. Thank you!

Ben
  • 571
  • 2
  • 4
  • 15

1 Answers1

4

Edit, 2021-11-09: - My answer below will get the job done, but there is a more idiomatic answer (ie., less of a hack) here


Thanks to the folks over at the pygame discord and this example of using FFMPEG with a subprocess, I have a working solution. Hopefully this will help someone out in the future.

import pygame
from lib.constants import SCREEN_WIDTH, SCREEN_HEIGHT
from viewcontrollers.Base import BaseView
import subprocess as sp

FFMPEG_BIN = "ffmpeg"
BYTES_PER_FRAME = SCREEN_WIDTH * SCREEN_HEIGHT * 3

class AnimationFullScreenView(BaseView):

    def __init__(self):
        super(AnimationFullScreenView, self).__init__()

        command = [
            FFMPEG_BIN,
            '-loglevel', 'quiet',
            '-i', 'animations/__BasicBoot.mp4',
            '-f', 'image2pipe',
            '-pix_fmt', 'rgb24',
            '-vcodec', 'rawvideo', '-'
        ]
        self.proc = sp.Popen(command, stdout = sp.PIPE, bufsize=BYTES_PER_FRAME*2)

    # draw() will be run once per frame
    def draw(self):
        raw_image = self.proc.stdout.read(BYTES_PER_FRAME)
        image = pygame.image.frombuffer(raw_image, (SCREEN_WIDTH, SCREEN_HEIGHT), 'RGB')
        self.proc.stdout.flush()
        self.surf.blit(image, (0, 0))


Ben
  • 571
  • 2
  • 4
  • 15
  • 1
    Wow, that's a really interesting way to do it. Does it turn out to be slow on the PyGame side? I wonder if `ffmpeg` can decode the video to a particular size, then it could utilise video hardware to speed things up, and save PyGame from having to re-size, etc. – Kingsley Nov 21 '19 at 21:31
  • 1
    Don't know yet. This is a peculiar little project that only ever has to run on one display, and only at 12fps. I'm working on some improvements where I can pre-register all the video clips and pipe them into temp files, then play them using seek/read. The subprocess documentation warns against using `read` on its stdout to avoid deadlock issues. So far it's working out. – Ben Nov 21 '19 at 22:31
  • 1
    Hmm, you could pre-calculate a "difference-block" between subsequent frames, and store an (x, y, bitmap) in your new stream. I guess this makes it like an animated .GIF – Kingsley Nov 22 '19 at 01:04
  • Thanks. I'm a bit out of my element here. I haven't done a ton of non-web GUI programming and basically no game development at all. If you have any resources you can point me to for calculating difference blocks, I'll keep them in my back pocket in case I need to optimize down the road. – Ben Nov 22 '19 at 17:16