114 lines
4.5 KiB
Python
114 lines
4.5 KiB
Python
from os import makedirs
|
|
from os.path import exists, join
|
|
from tempfile import TemporaryFile
|
|
from time import strftime
|
|
|
|
from pygame.image import tostring, frombuffer, save
|
|
from pygame.time import get_ticks
|
|
|
|
from .GameChild import GameChild
|
|
|
|
class VideoRecorder(GameChild):
|
|
|
|
def __init__(self, parent):
|
|
GameChild.__init__(self, parent)
|
|
self.set_requested()
|
|
if self.requested:
|
|
self.display_surface = self.get_display_surface()
|
|
self.delegate = self.get_delegate()
|
|
self.load_configuration()
|
|
self.reset()
|
|
self.subscribe(self.respond)
|
|
|
|
def set_requested(self):
|
|
self.requested = self.get_configuration("video-recordings")["enable"] \
|
|
or self.check_command_line("-enable-video")
|
|
|
|
def load_configuration(self):
|
|
config = self.get_configuration("video-recordings")
|
|
self.root = config["path"]
|
|
self.directory_name_format = config["directory-name-format"]
|
|
self.file_extension = config["file-extension"]
|
|
self.frame_format = config["frame-format"]
|
|
self.framerate = config["framerate"]
|
|
|
|
def reset(self):
|
|
self.recording = False
|
|
self.frame_length = None
|
|
self.frames = None
|
|
self.last_frame = 0
|
|
|
|
def respond(self, event):
|
|
compare = self.delegate.compare
|
|
if compare(event, "record-video"):
|
|
self.toggle_record()
|
|
elif compare(event, "reset-game"):
|
|
self.reset()
|
|
|
|
def is_audio_recording_enabled(self):
|
|
return self.get_configuration("video-recordings", "record-audio") or\
|
|
self.check_command_line("-enable-sound-recording")
|
|
|
|
def toggle_record(self):
|
|
recording = not self.recording
|
|
if recording:
|
|
self.frame_length = len(self.get_string())
|
|
temp_dir = self.get_configuration("video-recordings", "temp-directory")
|
|
if temp_dir == "":
|
|
temp_dir = None
|
|
self.frames = TemporaryFile(dir=temp_dir)
|
|
print("writing video frames to {}".format(self.frames.name))
|
|
if self.is_audio_recording_enabled():
|
|
import pyaudio
|
|
import wave
|
|
self.audio_frames = []
|
|
self.audio_recorder = pyaudio.PyAudio()
|
|
def audio_callback(in_data, frame_count, time_info, status):
|
|
self.audio_frames.append(in_data)
|
|
return (in_data, pyaudio.paContinue)
|
|
for ii in range(self.audio_recorder.get_device_count()):
|
|
print("device {}: {}".format(ii, self.audio_recorder.get_device_info_by_index(ii)))
|
|
self.audio_stream = self.audio_recorder.open(format=pyaudio.paInt32, channels=2, rate=44100,
|
|
frames_per_buffer=1024,
|
|
input=True, stream_callback=audio_callback)
|
|
print("writing audio data to {}".format(self.audio_stream))
|
|
else:
|
|
self.write_frames()
|
|
self.recording = recording
|
|
|
|
def get_string(self):
|
|
return tostring(self.display_surface, self.frame_format)
|
|
|
|
def write_frames(self):
|
|
root = join(self.root, strftime(self.directory_name_format))
|
|
if not exists(root):
|
|
makedirs(root)
|
|
if self.is_audio_recording_enabled():
|
|
import pyaudio
|
|
import wave
|
|
self.audio_stream.stop_stream()
|
|
self.audio_stream.close()
|
|
self.audio_recorder.terminate()
|
|
wf = wave.open(join(root, "audio.wav"), "wb")
|
|
wf.setnchannels(2)
|
|
wf.setsampwidth(self.audio_recorder.get_sample_size(pyaudio.paInt32))
|
|
wf.setframerate(44100)
|
|
wf.writeframes(b"".join(self.audio_frames))
|
|
wf.close()
|
|
print("saved audio in {}".format(root))
|
|
size = self.display_surface.get_size()
|
|
frames = self.frames
|
|
frames.seek(0)
|
|
for ii, frame in enumerate(
|
|
iter(lambda: frames.read(self.frame_length), b'')):
|
|
path = join(root, "{:0{digits}}.png".format(
|
|
ii, digits=self.get_configuration("video-recordings", "filename-digits")))
|
|
save(frombuffer(frame, size, self.frame_format), path)
|
|
print("saved video frames in {}".format(root))
|
|
|
|
def update(self):
|
|
ticks = get_ticks()
|
|
if self.recording and ticks - self.last_frame >= self.framerate:
|
|
self.frames.write(self.get_string())
|
|
self.last_frame = ticks
|