code: def start(self):
      while True:
          cycle_start = time.time()
  
          frame = self.grab_frame()
  
          if self.frame_transformation_pipeline is not None:
              frame_pipeline = (
                  self.frame_transformation_pipeline.transform(frame)
              )
          else:
              frame_pipeline = frame
  
          frame_shape = (
              str(frame.shape).replace("(", "").replace(")", "")
          )
          frame_dtype = str(frame.dtype)
  
          frame_bytes = (
              f"{cycle_start}~{frame_shape}~{frame_dtype}~".encode(
                  "utf-8"
              )
              + frame.tobytes()
          )
  
          self.redis_client.lpush(
              config["frame_grabber"]["redis_key"], frame_bytes
          )
          self.redis_client.ltrim(
              config["frame_grabber"]["redis_key"],
              0,
              self.frame_buffer_size,
          )
  
          if self._has_png_transformation_pipeline():
              frame_pipeline_shape = "PNG"
              frame_pipeline_dtype = "PNG"
  
              frame_pipeline_bytes = (
                  f"{cycle_start}~{frame_pipeline_shape}~{frame_pipeline_dtype}~".encode(
                      "utf-8"
                  )
                  + frame_pipeline
              )
          else:
              frame_pipeline_shape = (
                  str(frame_pipeline.shape)
                  .replace("(", "")
                  .replace(")", "")
              )
              frame_pipeline_dtype = str(frame_pipeline.dtype)
  
              frame_pipeline_bytes = (
                  f"{cycle_start}~{frame_pipeline_shape}~{frame_pipeline_dtype}~".encode(
                      "utf-8"
                  )
                  + frame_pipeline.tobytes()
              )
  
          self.redis_client.lpush(
              config["frame_grabber"]["redis_key"] + "_PIPELINE",
              frame_pipeline_bytes,
          )
          self.redis_client.ltrim(
              config["frame_grabber"]["redis_key"] + "_PIPELINE",
              0,
              self.frame_buffer_size,
          )
  
          cycle_end = time.time()
  
          cycle_duration = cycle_end - cycle_start
          cycle_duration -= int(cycle_duration)
  
          frame_time_left = self.frame_time - cycle_duration
  
          if frame_time_left > 0:
              time.sleep(frame_time_left)
  
file_path: SerpentAI/serpent/frame_grabber.py
imports: import numpy
  import mss
  from redis import StrictRedis
  from serpent.config import config
  import time
  from serpent.game_frame import GameFrame
  from serpent.game_frame_buffer import GameFrameBuffer
  from serpent.frame_transformation_pipeline import FrameTransformationPipeline
label_desc: Use image node_id 2 for calling the FrameGrabber obj's underlying member method code with example usage: obj.start() without return types