diff --git a/.github/workflows/lint-and-build.yml b/.github/workflows/lint-and-build.yml
index 85f116ab..1089c845 100644
--- a/.github/workflows/lint-and-build.yml
+++ b/.github/workflows/lint-and-build.yml
@@ -89,6 +89,7 @@ jobs:
       - name: Analysing the code with Pyright
         uses: jakebailey/pyright-action@v1
         with:
+          version: "1.1.364"
           working-directory: src/
           python-version: ${{ matrix.python-version }}
   Build:
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 815e9679..138878f4 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -62,6 +62,10 @@
   "[json][jsonc]": {
     "editor.defaultFormatter": "vscode.json-language-features",
   },
+  "[yaml]": {
+    "editor.defaultFormatter": "redhat.vscode-yaml"
+  },
+  "yaml.format.printWidth": 100,
   "[python]": {
     // Ruff as a formatter doesn't fully satisfy our needs yet: https://github.com/astral-sh/ruff/discussions/7310
     "editor.defaultFormatter": "ms-python.autopep8",
diff --git a/pyproject.toml b/pyproject.toml
index 41b4e3a5..bb3a68c7 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -25,7 +25,7 @@ ignore = [
   "ERA001", # eradicate: commented-out-code
   # contextlib.suppress is roughly 3x slower than try/except
   "SIM105", # flake8-simplify: use-contextlib-suppress
-  # Negative performance impact
+  # Slower and more verbose https://github.com/astral-sh/ruff/issues/7871
   "UP038", # non-pep604-isinstance
   # Checked by type-checker (pyright)
   "ANN", # flake-annotations
diff --git a/scripts/lint.ps1 b/scripts/lint.ps1
index 84dc6f8b..3e0eacb1 100644
--- a/scripts/lint.ps1
+++ b/scripts/lint.ps1
@@ -6,7 +6,7 @@ Write-Host "`nRunning formatting..."
 autopep8 src/ --recursive --in-place
 add-trailing-comma $(git ls-files '**.py*')
 
-Write-Host "`nRunning Ruff..."
+Write-Host "`nRunning Ruff ..."
 ruff check . --fix
 $exitCodes += $LastExitCode
 if ($LastExitCode -gt 0) {
@@ -16,12 +16,16 @@ else {
   Write-Host "`Ruff passed" -ForegroundColor Green
 }
 
-Write-Host "`nRunning Pyright..."
-$Env:PYRIGHT_PYTHON_FORCE_VERSION = 'latest'
-npx pyright@latest src/
+$pyrightVersion = '1.1.364' # Change this if latest has issues
+Write-Host "`nRunning Pyright $pyrightVersion ..."
+$Env:PYRIGHT_PYTHON_FORCE_VERSION = $pyrightVersion
+npx -y pyright@$pyrightVersion src/
 $exitCodes += $LastExitCode
 if ($LastExitCode -gt 0) {
   Write-Host "`Pyright failed ($LastExitCode)" -ForegroundColor Red
+  if ($pyrightVersion -eq 'latest') {
+    npx pyright@latest --version
+  }
 }
 else {
   Write-Host "`Pyright passed" -ForegroundColor Green
diff --git a/src/AutoSplit.py b/src/AutoSplit.py
index 9314101a..20bbfab0 100644
--- a/src/AutoSplit.py
+++ b/src/AutoSplit.py
@@ -6,7 +6,7 @@
 from copy import deepcopy
 from time import time
 from types import FunctionType
-from typing import NoReturn
+from typing import NoReturn, cast
 
 import cv2
 from cv2.typing import MatLike
@@ -946,7 +946,8 @@ def set_preview_image(qlabel: QLabel, image: MatLike | None):
             capture = image
 
         qimage = QtGui.QImage(
-            capture.data,
+            # Try to update PySide6, see https://bugreports.qt.io/browse/QTBUG-114635
+            cast(bytes, capture.data) if sys.platform == "linux" else capture.data,
             width,
             height,
             width * channels,
diff --git a/src/capture_method/Screenshot using QT attempt.py b/src/capture_method/Screenshot using QT attempt.py
index fa55e8d5..abb3d3af 100644
--- a/src/capture_method/Screenshot using QT attempt.py	
+++ b/src/capture_method/Screenshot using QT attempt.py	
@@ -1,17 +1,18 @@
-# flake8: noqa
+# ruff: noqa: RET504
 import sys
 
 if sys.platform != "linux":
-    raise OSError()
+    raise OSError
 from typing import cast
 
 import numpy as np
 from cv2.typing import MatLike
 from PySide6.QtCore import QBuffer, QIODeviceBase
 from PySide6.QtGui import QGuiApplication
-from capture_method.CaptureMethodBase import CaptureMethodBase
 from typing_extensions import override
 
+from capture_method.CaptureMethodBase import CaptureMethodBase
+
 
 class QtCaptureMethod(CaptureMethodBase):
     _render_full_content = False
diff --git a/src/capture_method/VideoCaptureDeviceCaptureMethod.py b/src/capture_method/VideoCaptureDeviceCaptureMethod.py
index fc62e1fc..29606f95 100644
--- a/src/capture_method/VideoCaptureDeviceCaptureMethod.py
+++ b/src/capture_method/VideoCaptureDeviceCaptureMethod.py
@@ -1,4 +1,3 @@
-import sys
 from threading import Event, Thread
 from typing import TYPE_CHECKING
 
@@ -8,13 +7,11 @@
 from cv2.typing import MatLike
 from typing_extensions import override
 
+from capture_method import get_input_device_resolution
 from capture_method.CaptureMethodBase import CaptureMethodBase
 from error_messages import CREATE_NEW_ISSUE_MESSAGE, exception_traceback
 from utils import ImageShape, is_valid_image
 
-if sys.platform == "win32":
-    from pygrabber.dshow_graph import FilterGraph
-
 if TYPE_CHECKING:
     from AutoSplit import AutoSplit
 
@@ -101,14 +98,11 @@ def __init__(self, autosplit: "AutoSplit"):
             return
 
         # Ensure we're using the right camera size. And not OpenCV's default 640x480
-        if sys.platform == "win32":
-            filter_graph = FilterGraph()
-            filter_graph.add_video_input_device(autosplit.settings_dict["capture_device_id"])
-            width, height = filter_graph.get_input_device().get_current_format()
-            filter_graph.remove_filters()
+        resolution = get_input_device_resolution(autosplit.settings_dict["capture_device_id"])
+        if resolution is not None:
             try:
-                self.capture_device.set(cv2.CAP_PROP_FRAME_WIDTH, width)
-                self.capture_device.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
+                self.capture_device.set(cv2.CAP_PROP_FRAME_WIDTH, resolution[0])
+                self.capture_device.set(cv2.CAP_PROP_FRAME_HEIGHT, resolution[1])
             except cv2.error:
                 # Some cameras don't allow changing the resolution
                 pass
diff --git a/src/capture_method/XcbCaptureMethod.py b/src/capture_method/XcbCaptureMethod.py
index 7f56f41f..7c957a1d 100644
--- a/src/capture_method/XcbCaptureMethod.py
+++ b/src/capture_method/XcbCaptureMethod.py
@@ -39,7 +39,7 @@ def get_frame(self):
         selection = self._autosplit_ref.settings_dict["capture_region"]
         x = selection["x"] + offset_x
         y = selection["y"] + offset_y
-        image = ImageGrab.grab(
+        image = ImageGrab.grab(  # pyright: ignore[reportUnknownMemberType] # TODO: Fix upstream
             (
                 x,
                 y,
diff --git a/src/capture_method/__init__.py b/src/capture_method/__init__.py
index 168a6378..e099d444 100644
--- a/src/capture_method/__init__.py
+++ b/src/capture_method/__init__.py
@@ -1,4 +1,3 @@
-import asyncio
 import os
 import sys
 from collections import OrderedDict
@@ -77,7 +76,7 @@ def __hash__(self):
 
     @override
     @staticmethod
-    def _generate_next_value_(name: "str | CaptureMethodEnum", *_):
+    def _generate_next_value_(name: str, start: int, count: int, last_values: list["str | CaptureMethodEnum"]):
         return name
 
     NONE = ""
@@ -113,10 +112,11 @@ def get_method_by_index(self, index: int):
     # Disallow unsafe get w/o breaking it at runtime
     @override
     def __getitem__(  # type:ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
-        self,
-        __key: Never,
+            self,
+            key: Never,
+            /,
     ) -> type[CaptureMethodBase]:
-        return super().__getitem__(__key)
+        return super().__getitem__(key)
 
     @override
     def get(self, key: CaptureMethodEnum, default: object = None, /):
@@ -149,7 +149,7 @@ def get(self, key: CaptureMethodEnum, default: object = None, /):
         CAPTURE_METHODS[CaptureMethodEnum.DESKTOP_DUPLICATION] = DesktopDuplicationCaptureMethod
     CAPTURE_METHODS[CaptureMethodEnum.PRINTWINDOW_RENDERFULLCONTENT] = ForceFullContentRenderingCaptureMethod
 elif sys.platform == "linux":
-    if features.check_feature(feature="xcb"):
+    if features.check_feature(feature="xcb"):  # pyright: ignore[reportUnknownMemberType] # TODO: Fix upstream
         CAPTURE_METHODS[CaptureMethodEnum.XCB] = XcbCaptureMethod
     try:
         pyscreeze.screenshot()
@@ -211,15 +211,22 @@ def get_input_device_resolution(index: int) -> tuple[int, int] | None:
     # https://github.com/Toufool/AutoSplit/issues/238
     except COMError:
         return None
-    resolution = filter_graph.get_input_device().get_current_format()
-    filter_graph.remove_filters()
+
+    try:
+        resolution = filter_graph.get_input_device().get_current_format()
+    # For unknown reasons, some devices can raise "ValueError: NULL pointer access".
+    # For instance, Oh_DeeR's AVerMedia HD Capture C985 Bus 12
+    except ValueError:
+        return None
+    finally:
+        filter_graph.remove_filters()
     return resolution
 
 
-async def get_all_video_capture_devices():
+def get_all_video_capture_devices():
     named_video_inputs = get_input_devices()
 
-    async def get_camera_info(index: int, device_name: str):
+    def get_camera_info(index: int, device_name: str):
         backend = ""
         # Probing freezes some devices (like GV-USB2 and AverMedia) if already in use. See #169
         # FIXME: Maybe offer the option to the user to obtain more info about their devices?
@@ -246,9 +253,4 @@ async def get_camera_info(index: int, device_name: str):
             else None
         )
 
-    return [
-        camera_info
-        for camera_info
-        in await asyncio.gather(*starmap(get_camera_info, enumerate(named_video_inputs)))
-        if camera_info is not None
-    ]
+    return list(filter(None, starmap(get_camera_info, enumerate(named_video_inputs))))
diff --git a/src/menu_bar.py b/src/menu_bar.py
index c47e880d..a01fe031 100644
--- a/src/menu_bar.py
+++ b/src/menu_bar.py
@@ -1,4 +1,3 @@
-import asyncio
 import json
 import sys
 import webbrowser
@@ -135,7 +134,7 @@ def __init__(self, autosplit: "AutoSplit"):
         self.__video_capture_devices: list[CameraInfo] = []
         """
         Used to temporarily store the existing cameras,
-        we don't want to call `get_all_video_capture_devices` agains and possibly have a different result
+        we don't want to call `get_all_video_capture_devices` again and possibly have a different result
         """
 
         self.setupUi(self)
@@ -246,7 +245,7 @@ def __fps_limit_changed(self, value: int):
 
     @fire_and_forget
     def __set_all_capture_devices(self):
-        self.__video_capture_devices = asyncio.run(get_all_video_capture_devices())
+        self.__video_capture_devices = get_all_video_capture_devices()
         if len(self.__video_capture_devices) > 0:
             for i in range(self.capture_device_combobox.count()):
                 self.capture_device_combobox.removeItem(i)