Anton's answer zainspirowało mnie do głębszego wniknięcia w to pytanie. Na szczęście odkryłem, że jest możliwe run Pygame headlessly, co pozwoliło mi osiągnąć to, co chciałem zrobić nieco prościej niż metoda Antona.
Podstawowy przepływ pracy wygląda następująco: pygame
- Instalator uruchomić headlessly
- Uruchom moją grę, oszczędzając wyświetlanego obrazu dla każdej klatki, używając Pygame
- Tworzenie wideo z plików graficznych przy użyciu ffmpeg
- Załaduj film na Youtube, korzystając z youtube-upload
Przykładowy kod (uproszczona wersja mojego własnego kodu, więc nie został ściśle kontrolowane):
# imports
import os
import subprocess
import pygame
import mygame
# setup pygame to run headlessly
os.environ['SDL_VIDEODRIVER'] = 'dummy'
pygame.display.set_mode((1,1))
# can't use display surface to capture images for some reason, so I set up
# my own screen using a pygame rect
width, height = 400, 400
black = (0,0,0)
flags = pygame.SRCALPHA
depth = 32
screen = pygame.Surface((width, height), flags, depth)
pygame.draw.rect(screen, black, (0, 0, width, height), 0)
# my game object: screen becomes attribute of game object: game.screen
game = mygame.MyGame(screen)
# need this file format for saving images and encoding video with ffmpeg
image_file_f = 'frame_%03d.png'
# run game, saving images of each screen
game.init()
while game.is_running:
game.update() # updates screen
image_path = image_file_f % (game.frame_num)
pygame.image.save(game.screen, image_path)
# create video of images using ffmpeg
output_path = '/tmp/mygame_clip_for_youtube.mp4'
ffmpeg_command = (
'ffmpeg',
'-r', str(game.fps),
'-sameq',
'-y',
'-i', image_file_f,
output_path
)
subprocess.check_call(ffmpeg_command)
print "video file created:", output_path
# upload video to Youtube using youtube-upload
gmail_address='[email protected]'
gmail_password='test123'
upload_command = (
'youtube-upload',
'--unlisted',
'--email=%s' % (gmail_address),
'--password=%s' % (gmail_password),
'--title="Sample Game Clip"',
'--description="See https://stackoverflow.com/q/14450581/1093087"',
'--category=Games',
output_path
)
proc = subprocess.Popen(
upload_command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
out, err = proc.communicate()
print "youtube link: %s" % (out)
Wy zapewne chcesz usunąć wszystkie pliki graficzne raz film powstał.
miałem trochę problemów przechwytywania zrzutów ekranu headlessly, którą pracowali jak opisano tutaj: In Pygame, how can I save a screen image in headless mode?
byłem w stanie zaplanować mój skrypt uruchamiany jako cronjob bez problemów.
Cieszę się, że mogę Ci pomóc, i mam nadzieję, że opisana metoda działa dobrze. W zależności od długości przechwytywania, martwię się o całą przestrzeń dyskową potrzebną do przechwytywania obrazów i procesor potrzebny do przekonwertowania ich na wideo (kodowanie sesji Xvfb powinno być tańsze, ponieważ nie potrzebuje png dekodowanie każdej klatki). Xvfb/ffmpeg razem teoretycznie byłoby mniej podatne. –