@@ -220,6 +220,7 @@ def __init__(self, width: int | None = None, height: int | None = None):
220220 self ._ffmpeg_queue : queue .Queue | None = None
221221 self ._ffmpeg_thread : threading .Thread | None = None
222222 self ._ffmpeg_stop_event : threading .Event | None = None
223+ self ._recording = False
223224 self ._textures : dict [str , rl .Texture ] = {}
224225 self ._target_fps : int = _DEFAULT_FPS
225226 self ._last_fps_log_time : float = time .monotonic ()
@@ -283,35 +284,6 @@ def _close(sig, frame):
283284 self ._render_texture = rl .load_render_texture (self ._width , self ._height )
284285 rl .set_texture_filter (self ._render_texture .texture , rl .TextureFilter .TEXTURE_FILTER_BILINEAR )
285286
286- if RECORD :
287- output_fps = fps * RECORD_SPEED
288- ffmpeg_args = [
289- 'ffmpeg' ,
290- '-v' , 'warning' , # Reduce ffmpeg log spam
291- '-nostats' , # Suppress encoding progress
292- '-f' , 'rawvideo' , # Input format
293- '-pix_fmt' , 'rgba' , # Input pixel format
294- '-s' , f'{ self ._width } x{ self ._height } ' , # Input resolution
295- '-r' , str (fps ), # Input frame rate
296- '-i' , 'pipe:0' , # Input from stdin
297- '-vf' , 'vflip,format=yuv420p' , # Flip vertically and convert to yuv420p
298- '-r' , str (output_fps ), # Output frame rate (for speed multiplier)
299- '-c:v' , 'libx264' ,
300- '-preset' , 'ultrafast' ,
301- ]
302- if RECORD_BITRATE :
303- ffmpeg_args += ['-b:v' , RECORD_BITRATE , '-maxrate' , RECORD_BITRATE , '-bufsize' , RECORD_BITRATE ]
304- ffmpeg_args += [
305- '-y' , # Overwrite existing file
306- '-f' , 'mp4' , # Output format
307- RECORD_OUTPUT , # Output file path
308- ]
309- self ._ffmpeg_proc = subprocess .Popen (ffmpeg_args , stdin = subprocess .PIPE )
310- self ._ffmpeg_queue = queue .Queue (maxsize = 60 ) # Buffer up to 60 frames
311- self ._ffmpeg_stop_event = threading .Event ()
312- self ._ffmpeg_thread = threading .Thread (target = self ._ffmpeg_writer_thread , daemon = True )
313- self ._ffmpeg_thread .start ()
314-
315287 # OFFSCREEN disables FPS limiting for fast offline rendering (e.g. clips)
316288 rl .set_target_fps (0 if OFFSCREEN else fps )
317289
@@ -355,6 +327,39 @@ def _startup_profile_context(self):
355327 print (f"{ green } UI window ready in { elapsed_ms :.1f} ms{ reset } " )
356328 sys .exit (0 )
357329
330+ def begin_recording (self ):
331+ if not RECORD or self ._recording :
332+ return
333+
334+ self ._recording = True
335+ output_fps = self ._target_fps * RECORD_SPEED
336+ ffmpeg_args = [
337+ 'ffmpeg' ,
338+ '-v' , 'warning' , # Reduce ffmpeg log spam
339+ '-nostats' , # Suppress encoding progress
340+ '-f' , 'rawvideo' , # Input format
341+ '-pix_fmt' , 'rgba' , # Input pixel format
342+ '-s' , f'{ self ._width } x{ self ._height } ' , # Input resolution
343+ '-r' , str (self ._target_fps ), # Input frame rate
344+ '-i' , 'pipe:0' , # Input from stdin
345+ '-vf' , 'vflip,format=yuv420p' , # Flip vertically and convert to yuv420p
346+ '-r' , str (output_fps ), # Output frame rate (for speed multiplier)
347+ '-c:v' , 'libx264' ,
348+ '-preset' , 'ultrafast' ,
349+ ]
350+ if RECORD_BITRATE :
351+ ffmpeg_args += ['-b:v' , RECORD_BITRATE , '-maxrate' , RECORD_BITRATE , '-bufsize' , RECORD_BITRATE ]
352+ ffmpeg_args += [
353+ '-y' , # Overwrite existing file
354+ '-f' , 'mp4' , # Output format
355+ RECORD_OUTPUT , # Output file path
356+ ]
357+ self ._ffmpeg_proc = subprocess .Popen (ffmpeg_args , stdin = subprocess .PIPE )
358+ self ._ffmpeg_queue = queue .Queue (maxsize = 60 ) # Buffer up to 60 frames
359+ self ._ffmpeg_stop_event = threading .Event ()
360+ self ._ffmpeg_thread = threading .Thread (target = self ._ffmpeg_writer_thread , daemon = True )
361+ self ._ffmpeg_thread .start ()
362+
358363 def _ffmpeg_writer_thread (self ):
359364 """Background thread that writes frames to ffmpeg."""
360365 while True :
@@ -560,7 +565,7 @@ def render(self):
560565
561566 rl .end_drawing ()
562567
563- if RECORD :
568+ if self . _recording :
564569 image = rl .load_image_from_texture (self ._render_texture .texture )
565570 data_size = image .width * image .height * 4
566571 data = bytes (rl .ffi .buffer (image .data , data_size ))
0 commit comments