2013-01-22 15 views
7

Spero che questa domanda non sia intrinsecamente insensata.È possibile eseguire Pygame come cronjob?

Sto sviluppando un gioco. Ho separato il motore di gioco sottostante (in Python) dal componente grafico. Ho uno script che confonde alcuni parametri, simula parte di un gioco usando il motore di gioco e quindi lo visualizza utilizzando Pygame.

mi piacerebbe automatizzare il processo seguente: simulazione

  1. Esegui come cronjob
  2. visualizzarlo utilizzando Pygame (headlessly)
  3. Salva la visualizzazione in formato breve (~ 10 sec) il video
  4. programmazione caricare video su YouTube

Idealmente, mi piacerebbe fare un paio di volte m al giorno in modo non tecnico le braci della mia squadra potevano vedere il video e dare feedback sugli aspetti visivi del gioco.

Mi piacerebbe usare Pygame perché ho già pronto il codice. Ma sospetto che probabilmente dovrei usare qualcosa come il PIL per creare una serie di file di immagini e andare da lì.

Ciò è possibile con Pygame? Dovrei semplicemente usare PIL? Qualche altra idea per realizzare qualcosa del genere?

risposta

3

Supponendo che si stia eseguendo su linux e il motore grafico funzioni in X, è possibile eseguire senza problemi qualsiasi applicazione desiderata utilizzando Xvfb (X virtual framebuffer). È possibile eseguire un codificatore video della sessione framebuffer virtuale (senza testa). Ci sono un paio di programmi di utilità per rendere questo compito più facile:

Che ci si vuole fare uno script alto livello che:

  • Start up Xvfb
  • Avviare un codificatore video (ad es. Ffmpeg)
  • Esegui il tuo gioco in Xvfb. Non dovresti aver bisogno di modificare il tuo gioco in alcun modo, supponendo che possa funzionare senza input da parte dell'utente, basta impostare la variabile d'ambiente DISPLAY sul valore corretto.
  • Terminare la codifica video
  • Carica il video su YouTube

Xvfb e ffmpeg sono sicuramente la strada da percorrere per la registrazione del gioco headlessly, questo assicura è possibile registrare il gioco come è senza modifiche. Dovrebbe essere fattibile ma non necessariamente facile. Spero che gli script di cui sopra possano iniziare.

1

Anton's answer mi ha ispirato a approfondire questa domanda. Fortunatamente, ho scoperto che è possibile run Pygame headlessly, permettendomi di realizzare ciò che volevo fare un po 'più semplicemente del metodo di Anton.

Il flusso di lavoro di base è la seguente:

  1. Setup Pygame per eseguire headlessly
  2. eseguire il mio gioco, salvando un'immagine dello schermo per ogni frame utilizzando Pygame
  3. Creare video da file di immagini utilizzando ffmpeg
  4. Carica video su Youtube utilizzando youtube-upload

Codice di esempio (versione semplificata del mio codice, quindi questo non è stato provato rigorosamente):

# 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) 

si sarebbe probabilmente desidera eliminare tutti i file di immagine una volta che il video è stato creato.

Ho avuto un piccolo problema catturare screenshot headlessly, che ho lavorato in giro come descritto qui: In Pygame, how can I save a screen image in headless mode?

sono stato in grado di pianificare il mio script per l'esecuzione come un cronjob, senza problemi.

+0

Felice di aiutare, e spero che il metodo che hai descritto funzioni bene. A seconda della durata della cattura, sarei preoccupato di tutto lo spazio su disco necessario per catturare le immagini e della CPU necessaria per convertirli in un video (la codifica di una sessione Xvfb dovrebbe essere più economica in quanto non ha bisogno di png decodificare ogni fotogramma). Xvfb/ffmpeg insieme sarebbero in teoria meno onerosi. –