Can't record my voice after upgrading to 25.7.3

After upgrading 25.7.3, I can’t record my voice when learning, with the following message,

Unable to record. Please ensure a microphone is connected, and Anki has permission to use the microphone. If other programs are using your microphone, closing them may help.

Original error: ⁨’NoneType’ object has no attribute 'readyRead’⁩

3 Likes

Can reproduce it here.

Logged on Can’t record my voice after upgrading to 25.7.3 · Issue #4225 · ankitects/anki · GitHub.

Should be fixed in 25.07.4

Hello, sadly it does not seem to be fixed. I have exactly the same Problem and I am on Version 25.07.5 (7172b2d2).

Whatever I try the Problem persists.

2 Likes

Working for me on Windows 10. What’s your OS? Can you use Help > About > Copy Debug Info and paste the text here?

2 Likes

I have this issue. Here’s the debug info:

Anki 25.07.5 (7172b2d2) (ao)
Python 3.13.5 Qt 6.9.1 PyQt 6.9.1
Platform: Windows-11-10.0.26100-SP0

===Add-ons (active)===
(add-on provided name [Add-on folder, installed at, version, is config changed])
AJT Media Converter WebP AVIF Opus [‘1151815987’, 2025-03-21T23:06, ‘None’, ‘’]
Add Hyperlink [‘318752047’, 2023-06-18T18:39, ‘None’, ‘’]
Adjust Sound Volume Enhanced by egg rolls [‘2095265391’, 2025-01-15T16:56, ‘None’, mod]
AnKing Note Types Easy Customization [‘952691989’, 2025-05-14T07:08, ‘None’, mod]
Anki Note Linker [‘1077002392’, 2025-04-27T21:16, ‘None’, ‘’]
AnkiRestart - Quick Anki Rebooter for Customize Develop Created by Shige [‘237169833’, 2025-06-22T09:33, ‘None’, mod]
Auto-refresh browser [‘746398558’, 2024-10-01T19:50, ‘None’, ‘’]
CrowdAnki JSON exportimport Edit history Collaborate on deck creation [‘1788670778’, 2023-10-31T01:57, ‘None’, ‘’]
Editor Live Preview [‘1960039667’, 2024-03-05T06:59, ‘None’, ‘’]
Opening the same window multiple time [‘354407385’, 2023-11-05T08:59, ‘None’, ‘’]
Review Heatmap [‘1771074083’, 2022-06-30T08:43, ‘None’, ‘’]
The KING of Button Add-ons [‘374005964’, 2025-07-28T18:25, ‘None’, ‘’]
Watch Foreign Language Movies with Anki [‘939347702’, 2025-06-23T13:59, ‘None’, ‘’]

===IDs of active AnkiWeb add-ons===
1077002392 1151815987 1771074083 1788670778 1960039667 2095265391 237169833 318752047 354407385 374005964 746398558 939347702 952691989

===Add-ons (inactive)===
(add-on provided name [Add-on folder, installed at, version, is config changed])
Chinese Support 3 [‘1752008591’, 2024-02-25T16:37, ‘None’, mod]
link Cards Notes and Preview them in extra window [‘1423933177’, 2025-07-06T18:01, ‘None’, ‘’]

Try this, especially safe mode: Troubleshooting - Anki Manual

Please close Anki, then open it in safe mode by holding down the Shift key while starting Anki. Keep holding Shift down until the on-screen message informs you that Anki has started in safe mode.

The issue still persists in Safe mode.

  • Install latest OS on x64 devices
  • Download the latest Anki
  • Install Anki with all defaults.
  • Launch the application
  • Click on Add.
  • Click on microphone symbol to record voice.

Observe the error while clicking on microphone

Seems like a headset, windows or driver issue, not Anki

what is circled in red are outputs, meaning they emit sound outwards hence the name speakers :speaker_high_volume:

1 Like

Please copy and paste the following into the debug console, then paste the output you get back here:

#!/usr/bin/env python3
"""
Minimal reproducible example for debugging QAudioSource.start() returning None
Copy and paste this into Anki's debug console to test audio initialization
"""

from PyQt6.QtMultimedia import QAudioDevice, QAudioFormat, QAudioSource, QMediaDevices
from PyQt6.QtWidgets import QApplication, QWidget


def test_qaudio_source():
    """Test QAudioSource initialization and debug available formats"""
    try:
        
        print("=== QAudioSource Debug Test ===")
        
        # Create a minimal widget as parent (required for QAudioSource)
        app = QApplication.instance()
        if app is None:
            print("No QApplication found - this test needs to run within Anki")
            return
        
        parent = QWidget()
        
        # Get available audio devices
        print("\n1. Available Audio Input Devices:")
        input_devices = QMediaDevices.audioInputs()
        for i, device in enumerate(input_devices):
            print(f"   Device {i}: {device.description()}")
            print(f"   - ID: {device.id()}")
            print(f"   - Default: {device.isDefault()}")
        
        if not input_devices:
            print("   No audio input devices found!")
            return
        
        # Get the default audio device
        default_device: QAudioDevice = QMediaDevices.defaultAudioInput()
        print(f"\n2. Default Audio Input Device:")
        print(f"   Description: {default_device.description()}")
        print(f"   ID: {default_device.id()}")
        
        # Check supported formats for default device
        print(f"\n3. Supported formats for default device:")
        supported_sample_rates = default_device.supportedSampleFormats()
        supported_channel_counts = (default_device.minimumChannelCount(), default_device.maximumChannelCount())
        supported_formats = default_device.supportedSampleFormats()
        
        print(f"   Sample rates: {supported_sample_rates}")
        print(f"   Channel counts: {supported_channel_counts}")
        print(f"   Sample formats: {[fmt.name for fmt in supported_formats]}")
        
        # Create the format (same as in the original code)
        print(f"\n4. Creating QAudioFormat:")
        format = QAudioFormat()
        format.setChannelCount(2)
        format.setSampleRate(44100)
        format.setSampleFormat(QAudioFormat.SampleFormat.Int16)
        
        print(f"   Requested - Channels: {format.channelCount()}, Rate: {format.sampleRate()}, Format: {format.sampleFormat().name}")
        
        # Check if the format is supported
        is_supported = default_device.isFormatSupported(format)
        print(f"   Format supported by default device: {is_supported}")
        
        if not is_supported:
            print("   Trying to find a preferred format...")
            preferred_format = default_device.preferredFormat()
            print(f"   Preferred - Channels: {preferred_format.channelCount()}, Rate: {preferred_format.sampleRate()}, Format: {preferred_format.sampleFormat().name}")
        
        # Create QAudioSource with default device (same as original code)
        print(f"\n5. Creating QAudioSource:")
        source = QAudioSource(format, parent)
        
        # Check the actual format that will be used
        actual_format = source.format()
        print(f"   Actual format - Channels: {actual_format.channelCount()}, Rate: {actual_format.sampleRate()}, Format: {actual_format.sampleFormat().name}")
        
        # Get audio source state and error before starting
        print(f"\n6. Audio source state before start():")
        print(f"   State: {source.state().name}")
        print(f"   Error: {source.error().name}")
        print(f"   Buffer size: {source.bufferSize()}")
        
        # Try starting the audio source - THIS IS THE KEY TEST
        print(f"\n7. Calling source.start():")
        iodevice = source.start()
        
        # Check the return value
        print(f"   Return value: {iodevice}")
        print(f"   Return value type: {type(iodevice)}")
        print(f"   Is None: {iodevice is None}")
        
        # Check state and error after start
        print(f"\n8. Audio source state after start():")
        print(f"   State: {source.state().name}")
        print(f"   Error: {source.error().name}")
        
        if iodevice is not None:
            print(f"   IODevice: {iodevice}")
            print(f"   IODevice type: {type(iodevice)}")
            print(f"   IODevice open: {iodevice.isOpen()}")
            print(f"   IODevice readable: {iodevice.isReadable()}")
        
        # Clean up
        if iodevice is not None:
            source.stop()
        
        parent.deleteLater()
        
        print(f"\n=== Test Complete ===")
        
    except ImportError as e:
        print(f"Import error: {e}")
        print("Make sure PyQt6.QtMultimedia is available")
    except Exception as e:
        print(f"Error during test: {e}")
        import traceback
        traceback.print_exc()

# Run the test
test_qaudio_source()

【NoneType’ object has no attribute 'readyRead’⁩】
And I can record in ⁨25.02.7

Please follow the instructions posted above:

Downgrading to 25.02.7 resolved the issue

Help!

I am facing the same trouble that I can’t record own voice in edit section of cards by the last edition ANKI Version ⁨25.07.5 (7172b2d2)⁩ in macOS 12.7.6. My headset is working well to record and receive audio in other apps.

Failure information:

“Unable to record. Please ensure a microphone is connected, and Anki has permission to use the microphone. If other programs are using your microphone, closing them may help.

Original error: ⁨’NoneType’ object has no attribute 'readyRead’⁩ ”

Downgrading to 25.02.7 resolved the same issue as well. Thank you.

Help!

I’m having the same issue where I can’t record my voice in the card editing section of Anki version 25.07.5 (7172b2d2) on macOS 12.7.6. My headset works fine for recording and audio in other apps.

Error message:

“Unable to record. Please make sure a microphone is connected and Anki has permission to access it. Closing any other apps that might be using the microphone could help.

Original error: ‘NoneType’ object has no attribute 'readyRead’.

For everyone still reporting this –

Not much is going to happen until someone steps up and helps with this request from the developer.

2 Likes

Here’s the output on version 25.07.5:

>>> #!/usr/bin/env python3

... """

... Minimal reproducible example for debugging QAudioSource.start() returning None

... Copy and paste this into Anki's debug console to test audio initialization

... """

...

... from PyQt6.QtMultimedia import QAudioDevice, QAudioFormat, QAudioSource, QMediaDevices

... from PyQt6.QtWidgets import QApplication, QWidget

...

...

... def test_qaudio_source():

... """Test QAudioSource initialization and debug available formats"""

... try:

...

... print("=== QAudioSource Debug Test ===")

...

... # Create a minimal widget as parent (required for QAudioSource)

... app = QApplication.instance()

... if app is None:

... print("No QApplication found - this test needs to run within Anki")

... return

...

... parent = QWidget()

...

... # Get available audio devices

... print("\\n1. Available Audio Input Devices:")

... input_devices = QMediaDevices.audioInputs()

... for i, device in enumerate(input_devices):

... print(f" Device {i}: {device.description()}")

... print(f" - ID: {device.id()}")

... print(f" - Default: {device.isDefault()}")

...

... if not input_devices:

... print(" No audio input devices found!")

... return

...

... # Get the default audio device

... default_device: QAudioDevice = QMediaDevices.defaultAudioInput()

... print(f"\\n2. Default Audio Input Device:")

... print(f" Description: {default_device.description()}")

... print(f" ID: {default_device.id()}")

...

... # Check supported formats for default device

... print(f"\\n3. Supported formats for default device:")

... supported_sample_rates = default_device.supportedSampleFormats()

... supported_channel_counts = (default_device.minimumChannelCount(), default_device.maximumChannelCount())

... supported_formats = default_device.supportedSampleFormats()

...

... print(f" Sample rates: {supported_sample_rates}")

... print(f" Channel counts: {supported_channel_counts}")

... print(f" Sample formats: {\[fmt.name for fmt in supported_formats\]}")

...

... # Create the format (same as in the original code)

... print(f"\\n4. Creating QAudioFormat:")

... format = QAudioFormat()

... format.setChannelCount(2)

... format.setSampleRate(44100)

... format.setSampleFormat(QAudioFormat.SampleFormat.Int16)

...

... print(f" Requested - Channels: {format.channelCount()}, Rate: {format.sampleRate()}, Format: {format.sampleFormat().name}")

...

... # Check if the format is supported

... is_supported = default_device.isFormatSupported(format)

... print(f" Format supported by default device: {is_supported}")

...

... if not is_supported:

... print(" Trying to find a preferred format...")

... preferred_format = default_device.preferredFormat()

... print(f" Preferred - Channels: {preferred_format.channelCount()}, Rate: {preferred_format.sampleRate()}, Format: {preferred_format.sampleFormat().name}")

...

... # Create QAudioSource with default device (same as original code)

... print(f"\\n5. Creating QAudioSource:")

... source = QAudioSource(format, parent)

...

... # Check the actual format that will be used

... actual_format = source.format()

... print(f" Actual format - Channels: {actual_format.channelCount()}, Rate: {actual_format.sampleRate()}, Format: {actual_format.sampleFormat().name}")

...

... # Get audio source state and error before starting

... print(f"\\n6. Audio source state before start():")

... print(f" State: {source.state().name}")

... print(f" Error: {source.error().name}")

... print(f" Buffer size: {source.bufferSize()}")

...

... # Try starting the audio source - THIS IS THE KEY TEST

... print(f"\\n7. Calling source.start():")

... iodevice = source.start()

...

... # Check the return value

... print(f" Return value: {iodevice}")

... print(f" Return value type: {type(iodevice)}")

... print(f" Is None: {iodevice is None}")

...

... # Check state and error after start

... print(f"\\n8. Audio source state after start():")

... print(f" State: {source.state().name}")

... print(f" Error: {source.error().name}")

...

... if iodevice is not None:

... print(f" IODevice: {iodevice}")

... print(f" IODevice type: {type(iodevice)}")

... print(f" IODevice open: {iodevice.isOpen()}")

... print(f" IODevice readable: {iodevice.isReadable()}")

...

... # Clean up

... if iodevice is not None:

... source.stop()

...

... parent.deleteLater()

...

... print(f"\\n=== Test Complete ===")

...

... except ImportError as e:

... print(f"Import error: {e}")

... print("Make sure PyQt6.QtMultimedia is available")

... except Exception as e:

... print(f"Error during test: {e}")

... import traceback

... traceback.print_exc()

...

... # Run the test

... test_qaudio_source()

=== QAudioSource Debug Test ===

1\. Available Audio Input Devices:

Device 0: Mikrofon (PRO X)

\- ID: b'{0.0.1.00000000}.{78a04987-ca59-4dd3-a9b8-4cc0e11fa5fc}'

\- Default: True

Device 1: Zestaw mikrofonów (Realtek(R) Audio)

\- ID: b'{0.0.1.00000000}.{f1a2ad3b-7a96-4578-ba4d-864d6af5b5ab}'

\- Default: False

2\. Default Audio Input Device:

Description: Mikrofon (PRO X)

ID: b'{0.0.1.00000000}.{78a04987-ca59-4dd3-a9b8-4cc0e11fa5fc}'

3\. Supported formats for default device:

Sample rates: \[<SampleFormat.UInt8: 1>, <SampleFormat.Int16: 2>, <SampleFormat.Int32: 3>, <SampleFormat.Float: 4>\]

Channel counts: (1, 1)

Sample formats: \['UInt8', 'Int16', 'Int32', 'Float'\]

4\. Creating QAudioFormat:

Requested - Channels: 2, Rate: 44100, Format: Int16

Format supported by default device: False

Trying to find a preferred format...

Preferred - Channels: 1, Rate: 48000, Format: Float

5\. Creating QAudioSource:

Actual format - Channels: 2, Rate: 44100, Format: Int16

6\. Audio source state before start():

State: StoppedState

Error: NoError

Buffer size: 44100

7\. Calling source.start():

Qt warning: QAudioSource::start: QAudioFormat not supported by QAudioDevice

Return value: None

Return value type: <class 'NoneType'>

Is None: True

8\. Audio source state after start():

State: StoppedState

Error: OpenError

=== Test Complete ===
2 Likes

Thanks for that. When the next beta comes out, please let me know how it goes for you.

2 Likes