Search code examples
qtaudiorecordqaudiorecorderqmediarecorder

QAudioRecorder detect user not speaking and stop


I want to use QAudioRecorder to record audio from the user and then use the audio output file for speech to text. I could successfully run and record audio from this example, http://doc.qt.io/qt-5/qtmultimedia-multimedia-audiorecorder-example.html.

But my problem is, I need to detect if user has stopped speaking while QAudioRecorder is actively recording audio. So QAudioRecorder should only stop when user is not speaking.

I could stop QAudioRecorder for fixed seconds using QTimer as below:

void AudioRecorder::toggleRecord()
{
    if (audioRecorder->state() == QMediaRecorder::StoppedState) {
        audioRecorder->setAudioInput(boxValue(ui->audioDeviceBox).toString());

        QAudioEncoderSettings settings;
        settings.setCodec(boxValue(ui->audioCodecBox).toString());
        settings.setSampleRate(boxValue(ui->sampleRateBox).toInt());
        settings.setBitRate(boxValue(ui->bitrateBox).toInt());
        settings.setChannelCount(boxValue(ui->channelsBox).toInt());
        settings.setQuality(QMultimedia::EncodingQuality(ui->qualitySlider->value()));
        settings.setEncodingMode(ui->constantQualityRadioButton->isChecked() ?
                                 QMultimedia::ConstantQualityEncoding :
                                 QMultimedia::ConstantBitRateEncoding);

        QString container = boxValue(ui->containerBox).toString();

        audioRecorder->setEncodingSettings(settings, QVideoEncoderSettings(), container);
        audioRecorder->record();
        this->recordTimeout();
    }
    else {
        this->stopRecording();
    }
}

void AudioRecorder::recordTimeout()
{
    QTimer* mTimer = new QTimer(this);
    mTimer->setSingleShot(true);
    connect(mTimer, SIGNAL(timeout()), SLOT(stopRecording()));
    mTimer->start(6000);
}

void AudioRecorder::stopRecording()
{
    audioRecorder->stop();
}

But instead of this it should stop recording when user is not speaking. The QAudioProbe class has this signal audioBufferProbed(QAudioBuffer) which may be helpful to check level of audio but I don't know how to use it and what level can be used to detect if user is not speaking.


Solution

  • I've been trying to do more or less the same thing for a while now. There is an example - https://doc.qt.io/qt-5/qtdatavisualization-audiolevels-example.html that shows you how implement an audio level meter which should be helpful. The example uses QAudioInput. Specifically, it uses QAudioInput::start(QIODevice * device) and passes a custom QIODevice to implement the audio level meter. The problem with this approach using QAudioInput is once you've got the data, it's not easy to encode it and write it out to file where as with QAudioRecorder it's simple.

    Anyway ... your right QAudioProbe is your best bet if you want to record the easy way with QAudioRecorder. I adapted the Qt audio level meter example to work with QAudioProbe instead of QAudioInput/QIODevice. See - https://gist.github.com/sam-at-github/bf66e84105cc3e23e7113cca5e3b1772.

    One minor issue the level meter needs QAudioFormat but QAudioRecorder only provides you with a QEncoderSettings (Should probably fix code to use the latter. I don't know why both QEncoderSettings and QAudioFormat need to exist ...). You just gotta get a QAudioDeviceInfo for the device your using then use QAudioDeviceInfo::preferredFormat().


    Relaed Post: Qt: API to write raw QAudioInput data to file just like QAudioRecorder