diff --git a/qt/aqt/forms/preferences.ui b/qt/aqt/forms/preferences.ui
index e705d0b05..085c10881 100644
--- a/qt/aqt/forms/preferences.ui
+++ b/qt/aqt/forms/preferences.ui
@@ -107,13 +107,6 @@
- -
-
-
-
-
-
-
-
@@ -616,7 +609,6 @@
paste_strips_formatting
nightMode
useCurrent
- recording_driver
default_search_text
uiScale
showEstimates
diff --git a/qt/aqt/pinnedmodules.py b/qt/aqt/pinnedmodules.py
index 3586d4ff5..8fe9e2c39 100644
--- a/qt/aqt/pinnedmodules.py
+++ b/qt/aqt/pinnedmodules.py
@@ -33,7 +33,6 @@ except:
import PyQt5.QtSvg # type: ignore
import PyQt5.QtMultimedia # type: ignore
import socks
-import pyaudio
# legacy compat
import anki.storage
diff --git a/qt/aqt/preferences.py b/qt/aqt/preferences.py
index c0cce5612..e10029b94 100644
--- a/qt/aqt/preferences.py
+++ b/qt/aqt/preferences.py
@@ -9,7 +9,7 @@ from anki.collection import OpChanges
from anki.consts import newCardSchedulingLabels
from aqt import AnkiQt
from aqt.operations.collection import set_preferences
-from aqt.profiles import RecordingDriver, VideoDriver
+from aqt.profiles import VideoDriver
from aqt.qt import *
from aqt.utils import HelpPage, disable_help_button, openHelp, showInfo, showWarning, tr
@@ -134,48 +134,13 @@ class Preferences(QDialog):
def setup_profile(self) -> None:
"Setup options stored in the user profile."
- self.setup_recording_driver()
self.setup_network()
self.setup_backup()
def update_profile(self) -> None:
- self.update_recording_driver()
self.update_network()
self.update_backup()
- # Profile: recording driver
- ######################################################################
-
- def setup_recording_driver(self) -> None:
- self._recording_drivers = [
- RecordingDriver.QtAudioInput,
- RecordingDriver.PyAudio,
- ]
- # The plan is to phase out PyAudio soon, so will hold off on
- # making this string translatable for now.
- self.form.recording_driver.addItems(
- [
- f"Voice recording driver: {driver.value}"
- for driver in self._recording_drivers
- ]
- )
- self.form.recording_driver.setCurrentIndex(
- self._recording_drivers.index(self.mw.pm.recording_driver())
- )
-
- def update_recording_driver(self) -> None:
- new_audio_driver = self._recording_drivers[
- self.form.recording_driver.currentIndex()
- ]
- if self.mw.pm.recording_driver() != new_audio_driver:
- self.mw.pm.set_recording_driver(new_audio_driver)
- if new_audio_driver == RecordingDriver.PyAudio:
- showInfo(
- """\
-The PyAudio driver will likely be removed in a future update. If you find it works better \
-for you than the default driver, please let us know on the Anki forums."""
- )
-
# Profile: network
######################################################################
diff --git a/qt/aqt/profiles.py b/qt/aqt/profiles.py
index ce1fabef6..59ba16572 100644
--- a/qt/aqt/profiles.py
+++ b/qt/aqt/profiles.py
@@ -31,11 +31,6 @@ from aqt.utils import disable_help_button, showWarning, tr
# - Saves in sqlite rather than a flat file so the config can't be corrupted
-class RecordingDriver(Enum):
- PyAudio = "PyAudio"
- QtAudioInput = "Qt"
-
-
class VideoDriver(Enum):
OpenGL = "auto"
ANGLE = "angle"
@@ -556,18 +551,6 @@ create table if not exists profiles
def set_auto_sync_media_minutes(self, val: int) -> None:
self.profile["autoSyncMediaMinutes"] = val
- def recording_driver(self) -> RecordingDriver:
- if driver := self.profile.get("recordingDriver"):
- try:
- return RecordingDriver(driver)
- except ValueError:
- # revert to default
- pass
- return RecordingDriver.QtAudioInput
-
- def set_recording_driver(self, driver: RecordingDriver) -> None:
- self.profile["recordingDriver"] = driver.value
-
def show_browser_table_tooltips(self) -> bool:
return self.profile.get("browserTableTooltips", True)
diff --git a/qt/aqt/qt5.py b/qt/aqt/qt5.py
index 6c1e68f63..d87a3fa2c 100644
--- a/qt/aqt/qt5.py
+++ b/qt/aqt/qt5.py
@@ -96,9 +96,3 @@ class QtAudioInputRecorder(Recorder):
t.timeout.connect(on_stop_timer) # type: ignore
t.setSingleShot(True)
t.start(500)
-
-
-def prompt_for_mic_permission() -> None:
- from PyQt5.QtMultimedia import QAudioDeviceInfo
-
- QAudioDeviceInfo.defaultInputDevice()
diff --git a/qt/aqt/sound.py b/qt/aqt/sound.py
index 3642a9157..ee6c38ae2 100644
--- a/qt/aqt/sound.py
+++ b/qt/aqt/sound.py
@@ -9,7 +9,6 @@ import platform
import re
import subprocess
import sys
-import threading
import time
import wave
from abc import ABC, abstractmethod
@@ -23,11 +22,9 @@ import aqt
from anki import hooks
from anki.cards import Card
from anki.sound import AV_REF_RE, AVTag, SoundOrVideoTag
-from anki.types import assert_exhaustive
from anki.utils import isLin, isMac, isWin, namedtmp
from aqt import gui_hooks
from aqt.mpv import MPV, MPVBase, MPVCommandError
-from aqt.profiles import RecordingDriver
from aqt.qt import *
from aqt.taskman import TaskManager
from aqt.utils import (
@@ -546,16 +543,6 @@ class Recorder(ABC):
##########################################################################
-def prompt_for_mic_permission() -> None:
- if qtmajor == 5 and isMac:
- from .qt5 import prompt_for_mic_permission
-
- prompt_for_mic_permission()
- else:
- # no longer seems to be required, perhaps due to newer macOS sdk?
- pass
-
-
class QtAudioInputRecorder(Recorder):
def __init__(self, output_path: str, mw: aqt.AnkiQt, parent: QWidget) -> None:
super().__init__(output_path)
@@ -625,87 +612,6 @@ class QtAudioInputRecorder(Recorder):
t.start(500)
-# PyAudio recording
-##########################################################################
-
-try:
- import pyaudio
-except:
- pyaudio = None
-
-
-PYAU_CHANNELS = 1
-PYAU_INPUT_INDEX: int | None = None
-
-
-class PyAudioThreadedRecorder(threading.Thread):
- def __init__(self, output_path: str, startup_delay: float) -> None:
- threading.Thread.__init__(self)
- self._output_path = output_path
- self._startup_delay = startup_delay
- self.finish = False
- # though we're using pyaudio here, we rely on Qt to trigger
- # the permission prompt
- prompt_for_mic_permission()
-
- def run(self) -> None:
- chunk = 1024
- p = pyaudio.PyAudio()
-
- rate = int(p.get_default_input_device_info()["defaultSampleRate"])
- PYAU_FORMAT = pyaudio.paInt16
-
- stream = p.open(
- format=PYAU_FORMAT,
- channels=PYAU_CHANNELS,
- rate=rate,
- input=True,
- input_device_index=PYAU_INPUT_INDEX,
- frames_per_buffer=chunk,
- )
-
- # swallow the first 300ms to allow audio device to quiesce
- wait = int(rate * self._startup_delay)
- stream.read(wait, exception_on_overflow=False)
-
- # read data in a loop until self.finish is set
- data = b""
- while not self.finish:
- data += stream.read(chunk, exception_on_overflow=False)
-
- # write out the wave file
- stream.close()
- p.terminate()
- wf = wave.open(self._output_path, "wb")
- wf.setnchannels(PYAU_CHANNELS)
- wf.setsampwidth(p.get_sample_size(PYAU_FORMAT))
- wf.setframerate(rate)
- wf.writeframes(data)
- wf.close()
-
-
-class PyAudioRecorder(Recorder):
- def __init__(self, mw: aqt.AnkiQt, output_path: str) -> None:
- super().__init__(output_path)
- self.mw = mw
-
- def start(self, on_done: Callable[[], None]) -> None:
- self.thread = PyAudioThreadedRecorder(self.output_path, self.STARTUP_DELAY)
- self.thread.start()
- super().start(on_done)
-
- def stop(self, on_done: Callable[[str], None]) -> None:
- # ensure at least a second captured
- while self.duration() < 1:
- time.sleep(0.1)
-
- def func(fut: Future) -> None:
- Recorder.stop(self, on_done)
-
- self.thread.finish = True
- self.mw.taskman.run_in_background(self.thread.join, func)
-
-
# Recording dialog
##########################################################################
@@ -760,20 +666,14 @@ class RecordDialog(QDialog):
saveGeom(self, "audioRecorder2")
def _start_recording(self) -> None:
- driver = self.mw.pm.recording_driver()
- if driver is RecordingDriver.PyAudio:
- self._recorder = PyAudioRecorder(self.mw, namedtmp("rec.wav"))
- elif driver is RecordingDriver.QtAudioInput:
- if qtmajor > 5:
- self._recorder = QtAudioInputRecorder(
- namedtmp("rec.wav"), self.mw, self._parent
- )
- else:
- from .qt5 import QtAudioInputRecorder as Qt5Recorder
-
- self._recorder = Qt5Recorder(namedtmp("rec.wav"), self.mw, self._parent)
+ if qtmajor > 5:
+ self._recorder = QtAudioInputRecorder(
+ namedtmp("rec.wav"), self.mw, self._parent
+ )
else:
- assert_exhaustive(driver)
+ from .qt5 import QtAudioInputRecorder as Qt5Recorder
+
+ self._recorder = Qt5Recorder(namedtmp("rec.wav"), self.mw, self._parent)
self._recorder.start(self._start_timer)
def _start_timer(self) -> None: