diff --git a/src/py.rs b/src/py.rs
index 4b18b1a7aaa88640e99678cc4d9877c7759f6472..22570d3d2560675b065f15d26d970ad266bca8c5 100644
--- a/src/py.rs
+++ b/src/py.rs
@@ -117,5 +117,7 @@ fn boytacean(_py: Python, module: &PyModule) -> PyResult<()> {
     module.add("DISPLAY_WIDTH", DISPLAY_WIDTH)?;
     module.add("DISPLAY_HEIGHT", DISPLAY_HEIGHT)?;
     module.add("CPU_FREQ", GameBoyBase::CPU_FREQ)?;
+    module.add("VISUAL_FREQ", GameBoyBase::VISUAL_FREQ)?;
+    module.add("LCD_CYCLES", GameBoyBase::LCD_CYCLES)?;
     Ok(())
 }
diff --git a/src/python/boytacean/__init__.py b/src/python/boytacean/__init__.py
index 1b4517ad7755dda1ef43ee65e4b43fa9675eddc5..033b1adcc958d327f9839bf726449cf930b7d3d6 100644
--- a/src/python/boytacean/__init__.py
+++ b/src/python/boytacean/__init__.py
@@ -2,6 +2,8 @@ from .gb import (
     DISPLAY_WIDTH,
     DISPLAY_HEIGHT,
     CPU_FREQ,
+    VISUAL_FREQ,
+    LCD_CYCLES,
     GameBoy,
     GameBoyMode,
     GameBoyRust,
diff --git a/src/python/boytacean/gb.py b/src/python/boytacean/gb.py
index 89c61d2d7011e1bdabffe7757fcccf08b201f633..23b82118287d49fab67d5ff9524388044650786b 100644
--- a/src/python/boytacean/gb.py
+++ b/src/python/boytacean/gb.py
@@ -7,7 +7,14 @@ from PIL.Image import Image, frombytes
 
 from .palettes import PALETTES
 
-from .boytacean import DISPLAY_WIDTH, DISPLAY_HEIGHT, CPU_FREQ, GameBoy as GameBoyRust
+from .boytacean import (
+    DISPLAY_WIDTH,
+    DISPLAY_HEIGHT,
+    CPU_FREQ,
+    VISUAL_FREQ,
+    LCD_CYCLES,
+    GameBoy as GameBoyRust,
+)
 
 
 class GameBoyMode(Enum):
@@ -34,7 +41,7 @@ class GameBoy:
         super().__init__()
         self._frame_index = 0
         self._next_frame = None
-        self._frame_gap = 60
+        self._frame_gap = VISUAL_FREQ
         self._system = GameBoyRust(mode.value)
         self._system.set_ppu_enabled(ppu_enabled)
         self._system.set_apu_enabled(apu_enabled)
@@ -93,45 +100,36 @@ This is a [Game Boy](https://en.wikipedia.org/wiki/Game_Boy) emulator built usin
         image = self.image()
         image.save(filename, format=format)
 
-    def set_palette(self, name: str):
-        if not name in PALETTES:
-            raise ValueError(f"Unknown palette: {name}")
-        palette = PALETTES[name]
-        self.set_palette_colors(palette)
-
-    def set_palette_colors(self, colors_hex: str):
-        self._system.set_palette_colors(colors_hex)
-
-    @contextmanager
-    def video_capture(self, fps=5):
-        self._start_capture(fps=fps)
-        try:
-            yield
-        finally:
-            self._stop_capture()
-
-    def video(self):
-        import cv2
+    def video(self, encoder="H264"):
+        from cv2 import VideoWriter, VideoWriter_fourcc, imread
+        from IPython.display import Video
 
         images = glob("*.png")
-        fourcc = cv2.VideoWriter_fourcc(*"H264")
 
-        encoder = cv2.VideoWriter(
+        encoder = VideoWriter(
             "output.mp4",
-            fourcc,
-            60.0 / self._frame_gap,
+            VideoWriter_fourcc(*encoder),
+            VISUAL_FREQ / self._frame_gap,
             (DISPLAY_WIDTH, DISPLAY_HEIGHT),
         )
 
-        for image_file in sorted(images):
-            img = cv2.imread(image_file)
-            encoder.write(img)
+        try:
+            for image_file in sorted(images):
+                img = imread(image_file)
+                encoder.write(img)
+        finally:
+            encoder.release()
 
-        encoder.release()
+        return Video("output.mp4", embed=True, html_attributes="controls loop autoplay")
 
-        from IPython.display import Video
+    def set_palette(self, name: str):
+        if not name in PALETTES:
+            raise ValueError(f"Unknown palette: {name}")
+        palette = PALETTES[name]
+        self.set_palette_colors(palette)
 
-        return Video("output.mp4", embed=True, html_attributes="controls loop autoplay")
+    def set_palette_colors(self, colors_hex: str):
+        self._system.set_palette_colors(colors_hex)
 
     @property
     def ppu_enabled(self) -> bool:
@@ -176,9 +174,17 @@ This is a [Game Boy](https://en.wikipedia.org/wiki/Game_Boy) emulator built usin
     def clock_freq_s(self) -> str:
         return self._system.clock_freq_s()
 
+    @contextmanager
+    def video_capture(self, fps=5):
+        self._start_capture(fps=fps)
+        try:
+            yield
+        finally:
+            self._stop_capture()
+
     def _start_capture(self, fps=5):
         self._next_frame = self._frame_index + self._frame_gap
-        self._frame_gap = int(60.0 / fps)  # @TODO: This is not accurate!!!
+        self._frame_gap = int(VISUAL_FREQ / fps)
 
     def _stop_capture(self):
         self._next_frame = None