#include "audio_recorder.h" #include "capturer/audio/audio_qt_capturer.h" #include "capturer/audio/wasapi_loopback_capturer.h" #include "qdebug.h" #include #include AudioRecorder::AudioRecorder() {} AudioRecorder::~AudioRecorder() { Close(); } bool AudioRecorder::Open(const std::vector& deviceTypes, Encoder::Param& param, const uint32_t sampleRate, const uint32_t channels, const uint32_t bitsPerSample, const AVSampleFormat format) { qDebug() << "AudioRecorder::Open called, deviceTypes size:" << deviceTypes.size(); Close(); Info mixInfo; mixInfo.mixer = &_mixer; mixInfo.isRecord = &_isRecord; mixInfo.streamIndex = &_streamIndex; // 清空并重新创建音频捕获器 m_audioCapturers.clear(); for (int index = 0; index < deviceTypes.size(); ++index) { mixInfo.mixIndex = index; _infos.push_back(mixInfo); if (deviceTypes[index] == AudioCapturer::Type::Speaker) { m_audioCapturers.push_back(new WASAPILoopbackCapturer()); } else { m_audioCapturers.push_back(new WASAPILoopbackCapturer()); } } // 初始化每个音频捕获器 for (int index = 0; index < deviceTypes.size(); ++index) { if (!m_audioCapturers[index]->Init(deviceTypes[index])) { qDebug() << "Failed to initialize audio capturer" << index; return false; } // 添加音频格式验证 const AudioFormat& format = m_audioCapturers[index]->GetFormat(); qDebug() << "Audio Capturer" << index << "Format:" << "SampleRate:" << format.sampleRate << "Channels:" << format.channels << "BitsPerSample:" << format.bitsPerSample << "BlockAlign:" << format.blockAlign << "AvgBytesPerSec:" << format.avgBytesPerSec; // 验证格式是否与预期一致 if (format.sampleRate != sampleRate) { qDebug() << "Warning: Sample rate mismatch. Expected:" << sampleRate << "Got:" << format.sampleRate; } if (format.channels != channels) { qDebug() << "Warning: Channel count mismatch. Expected:" << channels << "Got:" << format.channels; } if (!_mixer.AddAudioInput(index, format.sampleRate, format.channels, format.bitsPerSample, _GetAVSampleFormat(format.bitsPerSample))) { qDebug() << "AddAudioInput failed for index" << index; return false; } } if (!_mixer.AddAudioOutput(sampleRate, channels, bitsPerSample, format)) { qDebug() << "AddAudioOutput failed"; return false; } _param = param; if (!_mixer.SetOutFrameSize(1024)) { qDebug() << "SetOutFrameSize failed"; return false; } // 启动所有成功初始化的音频捕获器 for (auto capturer : m_audioCapturers) { capturer->Start(); } return true; } void AudioRecorder::Close() { StopRecord(); // 停止并释放所有音频捕获器 for (auto capturer : m_audioCapturers) { if (capturer) { capturer->Stop(); delete capturer; } } m_audioCapturers.clear(); _mixer.Close(); _infos.clear(); } void AudioRecorder::SetVolumeScale(float scale, int mixIndex) { auto info = _mixer.GetInputInfo(mixIndex); if (info != nullptr) { info->scale = scale; } } bool AudioRecorder::LoadMuxer(AvMuxer& muxer) { std::lock_guard lock(_muxersMtx); // 检查是否已经加载过这个muxer for (const auto& info : _muxers) { if (info.muxer == &muxer) { return true; // 已经加载过,直接返回成功 } } int streamIndex = muxer.AddAudioStream(_param); if (streamIndex == -1) { qDebug() << "AddAudioStream failed"; return false; } _muxers.emplace_back(&muxer, streamIndex); // 为了兼容性,保留原有的_infos逻辑(如果需要的话) for (auto&& info : _infos) { if (info.muxer == nullptr) { info.muxer = &muxer; break; } } return true; } bool AudioRecorder::UnloadMuxer(AvMuxer& muxer) { std::lock_guard lock(_muxersMtx); auto it = std::find_if(_muxers.begin(), _muxers.end(), [&muxer](const MuxerInfo& info) { return info.muxer == &muxer; }); if (it != _muxers.end()) { _muxers.erase(it); // 清理_infos中对应的muxer引用 for (auto&& info : _infos) { if (info.muxer == &muxer) { info.muxer = nullptr; } } return true; } return false; // 没有找到对应的muxer } bool AudioRecorder::StartRecord() { _isRecord = true; m_audioTimer.Start(AUDIO_PULL_INTERVAL_MS, [this] { this->PullAndProcessAudio(); }); return true; } void AudioRecorder::StopRecord() { _isRecord = false; m_audioTimer.Stop(); } // 新增:主动拉取音频数据的接口 void AudioRecorder::PullAndProcessAudio() { for (int index = 0; index < m_audioCapturers.size(); ++index) { // 每次多次拉取小块数据,提升音频帧写入频率 while (true) { char buf[1024]; int bytes = m_audioCapturers[index]->readAudioData(buf, sizeof(buf)); // static int debugCounter = 0; // if (++debugCounter % 100 == 0) { // 每100次打印一次,避免日志过多 // qDebug() << "Capturer" << index << "read" << bytes << "bytes"; // } if (bytes <= 0) { break; } // 添加调试信息,显示数据大小 auto frame = _mixer.Convert(index, (uint8_t*) buf, bytes); if (frame && _isRecord) { int frameSize = _mixer.GetOutFrameSize(); if (_mixer.GetOutFrameSize() != frameSize) { _mixer.SetOutFrameSize(frameSize); continue; } // 向所有已加载的muxer写入音频数据 { std::lock_guard muxerLock(_muxersMtx); for (const auto& muxerInfo : _muxers) { muxerInfo.muxer->Write(frame, muxerInfo.streamIndex); } } } } } } std::string AudioRecorder::GetEncoderNameForMuxer(AvMuxer& muxer) { std::lock_guard lock(_muxersMtx); auto it = std::find_if(_muxers.begin(), _muxers.end(), [&](const MuxerInfo& info){ return info.muxer == &muxer; }); if (it == _muxers.end()) return {}; AVCodecContext* ctx = muxer.GetCodecCtx(it->streamIndex); if (!ctx || !ctx->codec || !ctx->codec->name) return {}; return std::string(ctx->codec->name); }