from contextlib import contextmanager from pygwin._pg import pg as _pg import moviepy.editor as mpe from array import array from PIL import Image import numpy as np import threading import pyautogui import tempfile import pyaudio import wave import time import sys import cv2 import os class record: def __init__(self,win,audio=False): self._isaudio = audio self._surface = win self.reset() def reset(self): self._run = False self._fpss = [] self._frames = [] self._codec = cv2.VideoWriter_fourcc(*"mp4v") if self._isaudio: self._apy = pyaudio.PyAudio() self._aframs = [] self._astrm = self.apy.open(format=pyaudio.paInt16,channels=1, rate=44100,input=True,frames_per_buffer=1024) def start(self,newThread=True): self._run = True if self._isaudio: def audiot(self): while self._run: self._aframs.append(self.astrm.read(1024)) self._athread = threading.Thread(target=lambda:audiot(self)) self._athread.start() def main(self): while self.run: self._record() if newThread: self._thread = threading.Thread(target=lambda:main(self)) self._thread.start() else:main() def _record(self): if self._run: try: self._frames.append(self._surface) self._fpss.append(self._surface.rawFps) except: pass def render(self, path): temp = tempfile.gettempdir() if self.isaudio: wavpath = os.path.join(temp, 'audio.wav') wavfile = wave.open(wavpath, 'wb') wavfile.setnchannels(1) wavfile.setsampwidth(self._apy.get_sample_size(pyaudio.paInt16)) wavfile.setframerate(44100) af = [] for i in self._aframs: af.append(array('h',i)) wavfile.writeframes(b''.join(af)) wavfile.close() fps = 0 for i in self._fpss: fps += i fps = fps/len(self._fpss) if self._isaudio: noaudiopath = os.path.join(temp, 'noaudio.mp4') else: noaudiopath = path out = cv2.VideoWriter(noaudiopath,self._codec, fps,self._surface.size) for i in self._frames: frame = np.array(_pg.surfarray.array3d(i).swapaxes(0,1)) frame = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB) out.write(frame) out.release() if self._isaudio: videoclip = mpe.VideoFileClip(noaudiopath) audioclip = mpe.AudioFileClip(wavpath) new_audioclip = mpe.CompositeAudioClip([audioclip]) videoclip.audio = new_audioclip @contextmanager def ss(): with open(os.devnull, "w") as devnull: oso = sys.stdout sys.stdout = devnull try:yield finally:sys.stdout=oso with ss(): videoclip.write_videofile(path) os.remove(noaudiopath) os.remove(wavpath) def stop(self): self._run = False try: self._thread.join() except: pass if self._isaudio: self._athread.join()