#include "capture_audio_capturer.h" #include "../base/logger.h" #include "../base/media_common.h" #include #include #ifdef _WIN32 #include #include #include #include #pragma comment(lib, "ole32.lib") #endif extern "C" { #include #include #include #include #include } namespace av { namespace capture { AudioCapturer::AudioCapturer() : audioParams_(CapturerType::AUDIO_MIC) { AV_LOGGER_DEBUG("创建音频采集器"); // 注册设备 avdevice_register_all(); lastLevelUpdate_ = std::chrono::steady_clock::now(); } AudioCapturer::~AudioCapturer() { close(); AV_LOGGER_DEBUG("音频采集器已销毁"); } ErrorCode AudioCapturer::initialize(const CapturerParams& params) { if (params.mediaType != MediaType::AUDIO) { AV_LOGGER_ERROR("参数媒体类型不是音频"); return ErrorCode::INVALID_PARAMS; } audioParams_ = static_cast(params); if (!validateParams(audioParams_)) { return ErrorCode::INVALID_PARAMS; } ErrorCode result = ErrorCode::SUCCESS; if (audioParams_.type == CapturerType::AUDIO_MIC) { result = initializeMicrophone(); } else if (audioParams_.type == CapturerType::AUDIO_SYSTEM || audioParams_.type == CapturerType::AUDIO_LOOPBACK) { result = initializeSystemAudio(); } else { AV_LOGGER_ERROR("不支持的音频采集器类型"); return ErrorCode::NOT_SUPPORTED; } if (result == ErrorCode::SUCCESS) { setState(CapturerState::INITIALIZED); AV_LOGGER_INFOF("音频采集器初始化成功: {}Hz, {}ch, {}", audioParams_.sampleRate, audioParams_.channels, av_get_sample_fmt_name(audioParams_.sampleFormat)); } return result; } ErrorCode AudioCapturer::start() { std::lock_guard lock(captureMutex_); if (getState() != CapturerState::INITIALIZED) { AV_LOGGER_ERROR("采集器状态无效,无法启动"); return ErrorCode::INVALID_STATE; } shouldStop_ = false; // 启动采集线程 try { captureThread_ = std::thread(&AudioCapturer::captureThreadFunc, this); setState(CapturerState::STARTED); AV_LOGGER_INFO("音频采集已启动"); return ErrorCode::SUCCESS; } catch (const std::exception& e) { AV_LOGGER_ERRORF("启动音频采集线程失败: {}", e.what()); return ErrorCode::THREAD_ERROR; } } ErrorCode AudioCapturer::stop() { std::lock_guard lock(captureMutex_); if (getState() != CapturerState::STARTED) { return ErrorCode::SUCCESS; } shouldStop_ = true; // 唤醒暂停的线程 { std::lock_guard pauseLock(pauseMutex_); paused_ = false; pauseCondition_.notify_all(); } // 等待线程结束 if (captureThread_.joinable()) { captureThread_.join(); } setState(CapturerState::STOPPED); AV_LOGGER_INFO("音频采集已停止"); return ErrorCode::SUCCESS; } ErrorCode AudioCapturer::pause() { if (getState() != CapturerState::STARTED) { return ErrorCode::INVALID_STATE; } paused_ = true; AV_LOGGER_INFO("音频采集已暂停"); return ErrorCode::SUCCESS; } ErrorCode AudioCapturer::resume() { if (getState() != CapturerState::STARTED) { return ErrorCode::INVALID_STATE; } { std::lock_guard lock(pauseMutex_); paused_ = false; pauseCondition_.notify_all(); } AV_LOGGER_INFO("音频采集已恢复"); return ErrorCode::SUCCESS; } ErrorCode AudioCapturer::reset() { ErrorCode result = stop(); if (result != ErrorCode::SUCCESS) { return result; } // 清空帧队列 { std::lock_guard lock(queueMutex_); while (!frameQueue_.empty()) { frameQueue_.pop(); } } resetStats(); audioLevel_ = 0.0f; setState(CapturerState::INITIALIZED); AV_LOGGER_INFO("音频采集器已重置"); return ErrorCode::SUCCESS; } ErrorCode AudioCapturer::close() { stop(); // 清理资源 cleanupResampler(); cleanupAudioProcessing(); if (codecCtx_) { avcodec_free_context(&codecCtx_); codecCtx_ = nullptr; } if (formatCtx_) { avformat_close_input(&formatCtx_); formatCtx_ = nullptr; } codec_ = nullptr; audioStreamIndex_ = -1; setState(CapturerState::IDLE); AV_LOGGER_INFO("音频采集器已关闭"); return ErrorCode::SUCCESS; } std::vector AudioCapturer::getAvailableDevices() const { std::vector devices; auto deviceInfos = getDetailedDeviceInfo(); for (const auto& info : deviceInfos) { devices.push_back(info.name); } return devices; } std::string AudioCapturer::getCurrentDevice() const { return audioParams_.deviceName; } std::vector AudioCapturer::getDetailedDeviceInfo() const { std::lock_guard lock(deviceCacheMutex_); if (!devicesCached_) { if (audioParams_.type == CapturerType::AUDIO_MIC) { cachedDevices_ = enumerateMicrophones(); } else { cachedDevices_ = enumerateSystemAudioDevices(); } devicesCached_ = true; } return cachedDevices_; } ErrorCode AudioCapturer::setAudioParams(int sampleRate, int channels, AVSampleFormat sampleFormat) { if (getState() == CapturerState::STARTED) { AV_LOGGER_ERROR("无法在采集过程中修改音频参数"); return ErrorCode::INVALID_STATE; } audioParams_.sampleRate = sampleRate; audioParams_.channels = channels; audioParams_.sampleFormat = sampleFormat; AV_LOGGER_INFOF("音频参数已更新: {}Hz, {}ch, {}", sampleRate, channels, av_get_sample_fmt_name(sampleFormat)); return ErrorCode::SUCCESS; } ErrorCode AudioCapturer::setVolume(float volume) { if (volume < 0.0f || volume > 2.0f) { AV_LOGGER_ERROR("音量值超出范围 (0.0-2.0)"); return ErrorCode::INVALID_PARAMS; } currentVolume_ = volume; audioParams_.volume = volume; AV_LOGGER_INFOF("音量已设置为: {:.2f}", volume); return ErrorCode::SUCCESS; } float AudioCapturer::getVolume() const { return currentVolume_; } ErrorCode AudioCapturer::setNoiseReduction(bool enable) { noiseReductionEnabled_ = enable; audioParams_.enableNoiseReduction = enable; AV_LOGGER_INFOF("Noise reduction {}", enable ? "enabled" : "disabled"); return ErrorCode::SUCCESS; } ErrorCode AudioCapturer::setEchoCancellation(bool enable) { echoCancellationEnabled_ = enable; audioParams_.enableEchoCancellation = enable; AV_LOGGER_INFOF("Echo cancellation {}", enable ? "enabled" : "disabled"); return ErrorCode::SUCCESS; } AudioCaptureParams AudioCapturer::getCurrentParams() const { return audioParams_; } float AudioCapturer::getAudioLevel() const { return audioLevel_.load(); } bool AudioCapturer::validateParams(const CapturerParams& params) { const auto& audioParams = static_cast(params); if (audioParams.sampleRate <= 0 || audioParams.sampleRate > 192000) { AV_LOGGER_ERROR("采样率无效"); return false; } if (audioParams.channels <= 0 || audioParams.channels > 8) { AV_LOGGER_ERROR("声道数无效"); return false; } if (audioParams.bufferSize <= 0 || audioParams.bufferSize > 8192) { AV_LOGGER_ERROR("缓冲区大小无效"); return false; } if (audioParams.volume < 0.0f || audioParams.volume > 2.0f) { AV_LOGGER_ERROR("音量值无效"); return false; } return true; } ErrorCode AudioCapturer::initializeMicrophone() { AV_LOGGER_INFOF("初始化麦克风采集器: 索引={}", audioParams_.micIndex); #ifdef _WIN32 return setupDirectSoundMicrophone(); #elif defined(__linux__) return setupALSAMicrophone(); #elif defined(__APPLE__) return setupCoreAudioMicrophone(); #else AV_LOGGER_ERROR("当前平台不支持麦克风采集"); return ErrorCode::NOT_SUPPORTED; #endif } ErrorCode AudioCapturer::initializeSystemAudio() { AV_LOGGER_INFO("初始化系统音频采集器"); #ifdef _WIN32 return setupWASAPISystemAudio(); #elif defined(__linux__) return setupPulseAudioCapture(); #elif defined(__APPLE__) return setupCoreAudioSystemCapture(); #else AV_LOGGER_ERROR("当前平台不支持系统音频采集"); return ErrorCode::NOT_SUPPORTED; #endif } ErrorCode AudioCapturer::openInputDevice() { const AVInputFormat* inputFormat = getPlatformInputFormat(); if (!inputFormat) { AV_LOGGER_ERROR("获取音频输入格式失败"); return ErrorCode::NOT_SUPPORTED; } std::string deviceName = getPlatformDeviceName(); if (deviceName.empty()) { AV_LOGGER_ERROR("获取音频设备名称失败"); return ErrorCode::DEVICE_NOT_FOUND; } AV_LOGGER_INFOF("打开音频输入设备: {} (格式: {})", deviceName, inputFormat->name); // 设置输入选项 AVDictionary* options = nullptr; // 设置音频参数 av_dict_set(&options, "sample_rate", std::to_string(audioParams_.sampleRate).c_str(), 0); av_dict_set(&options, "channels", std::to_string(audioParams_.channels).c_str(), 0); // 设置缓冲区大小 av_dict_set(&options, "audio_buffer_size", std::to_string(audioParams_.bufferSize).c_str(), 0); // 注意:不要在实际打开设备时设置list_devices选项,这会导致AVERROR_EXIT // 打开输入 int ret = avformat_open_input(&formatCtx_, deviceName.c_str(), inputFormat, &options); av_dict_free(&options); if (ret < 0) { AV_LOGGER_ERRORF("打开音频输入设备失败: {} (设备: {})", ffmpeg_utils::errorToString(ret), deviceName); // 如果是设备不存在错误,尝试多种回退方案 if (ret == AVERROR(EIO) || ret == AVERROR(ENOENT)) { // 尝试1: 使用默认设备 AV_LOGGER_WARNING("尝试使用默认音频设备"); AVDictionary* defaultOptions = nullptr; av_dict_set(&defaultOptions, "sample_rate", std::to_string(audioParams_.sampleRate).c_str(), 0); av_dict_set(&defaultOptions, "channels", std::to_string(audioParams_.channels).c_str(), 0); ret = avformat_open_input(&formatCtx_, "audio=default", inputFormat, &defaultOptions); av_dict_free(&defaultOptions); if (ret < 0) { AV_LOGGER_WARNINGF("默认设备失败: {}, 尝试设备索引0", ffmpeg_utils::errorToString(ret)); // 尝试2: 使用设备索引0 AVDictionary* indexOptions = nullptr; av_dict_set(&indexOptions, "sample_rate", std::to_string(audioParams_.sampleRate).c_str(), 0); av_dict_set(&indexOptions, "channels", std::to_string(audioParams_.channels).c_str(), 0); ret = avformat_open_input(&formatCtx_, "audio=0", inputFormat, &indexOptions); av_dict_free(&indexOptions); if (ret < 0) { AV_LOGGER_WARNINGF("DirectShow设备索引0失败: {}, 尝试WASAPI", ffmpeg_utils::errorToString(ret)); // 尝试3: 使用WASAPI const AVInputFormat* wasapiFormat = av_find_input_format("wasapi"); if (wasapiFormat) { AVDictionary* wasapiOptions = nullptr; av_dict_set(&wasapiOptions, "sample_rate", std::to_string(audioParams_.sampleRate).c_str(), 0); av_dict_set(&wasapiOptions, "channels", std::to_string(audioParams_.channels).c_str(), 0); ret = avformat_open_input(&formatCtx_, "", wasapiFormat, &wasapiOptions); av_dict_free(&wasapiOptions); if (ret < 0) { AV_LOGGER_ERRORF("所有音频设备打开尝试都失败: {}", ffmpeg_utils::errorToString(ret)); return static_cast(ret); } AV_LOGGER_INFO("成功打开WASAPI默认音频设备"); } else { AV_LOGGER_ERRORF("WASAPI不可用,所有音频设备打开尝试都失败: {}", ffmpeg_utils::errorToString(ret)); return static_cast(ret); } } else { AV_LOGGER_INFO("成功打开音频设备索引0"); } } else { AV_LOGGER_INFO("成功打开默认音频设备"); } } else { return static_cast(ret); } } // 查找流信息 ret = avformat_find_stream_info(formatCtx_, nullptr); if (ret < 0) { AV_LOGGER_ERRORF("查找音频流信息失败: {}", ffmpeg_utils::errorToString(ret)); return static_cast(ret); } // 查找音频流 audioStreamIndex_ = av_find_best_stream(formatCtx_, AVMEDIA_TYPE_AUDIO, -1, -1, &codec_, 0); if (audioStreamIndex_ < 0) { AV_LOGGER_ERROR("未找到音频流"); return ErrorCode::STREAM_NOT_FOUND; } // 创建解码上下文 codecCtx_ = avcodec_alloc_context3(codec_); if (!codecCtx_) { AV_LOGGER_ERROR("分配音频解码上下文失败"); return ErrorCode::MEMORY_ALLOC_FAILED; } // 复制流参数到解码上下文 ret = avcodec_parameters_to_context(codecCtx_, formatCtx_->streams[audioStreamIndex_]->codecpar); if (ret < 0) { AV_LOGGER_ERRORF("复制音频流参数失败: {}", ffmpeg_utils::errorToString(ret)); return static_cast(ret); } // 打开解码器 ret = avcodec_open2(codecCtx_, codec_, nullptr); if (ret < 0) { AV_LOGGER_ERRORF("打开音频解码器失败: {}", ffmpeg_utils::errorToString(ret)); return static_cast(ret); } // 设置音频重采样 return setupAudioResampling(); } ErrorCode AudioCapturer::setupAudioResampling() { AVSampleFormat srcFormat = codecCtx_->sample_fmt; int srcSampleRate = codecCtx_->sample_rate; int srcChannels = codecCtx_->ch_layout.nb_channels; AVChannelLayout srcChannelLayout = codecCtx_->ch_layout; AVSampleFormat dstFormat = audioParams_.sampleFormat; int dstSampleRate = audioParams_.sampleRate; int dstChannels = audioParams_.channels; AVChannelLayout dstChannelLayout; av_channel_layout_default(&dstChannelLayout, dstChannels); needResampling_ = (srcFormat != dstFormat) || (srcSampleRate != dstSampleRate) || (srcChannels != dstChannels); if (needResampling_) { AV_LOGGER_INFOF("需要音频重采样: {}Hz,{}ch,{} -> {}Hz,{}ch,{}", srcSampleRate, srcChannels, av_get_sample_fmt_name(srcFormat), dstSampleRate, dstChannels, av_get_sample_fmt_name(dstFormat)); swrCtx_ = swr_alloc(); if (!swrCtx_) { AV_LOGGER_ERROR("分配音频重采样器失败"); return ErrorCode::MEMORY_ALLOC_FAILED; } // 设置重采样参数 av_opt_set_chlayout(swrCtx_, "in_chlayout", &srcChannelLayout, 0); av_opt_set_int(swrCtx_, "in_sample_rate", srcSampleRate, 0); av_opt_set_sample_fmt(swrCtx_, "in_sample_fmt", srcFormat, 0); av_opt_set_chlayout(swrCtx_, "out_chlayout", &dstChannelLayout, 0); av_opt_set_int(swrCtx_, "out_sample_rate", dstSampleRate, 0); av_opt_set_sample_fmt(swrCtx_, "out_sample_fmt", dstFormat, 0); // 初始化重采样器 int ret = swr_init(swrCtx_); if (ret < 0) { AV_LOGGER_ERRORF("初始化音频重采样器失败: {}", ffmpeg_utils::errorToString(ret)); cleanupResampler(); return static_cast(ret); } // 创建重采样输出帧 resampledFrame_ = makeAVFrame(); if (!resampledFrame_) { return ErrorCode::MEMORY_ALLOC_FAILED; } resampledFrame_->format = dstFormat; resampledFrame_->sample_rate = dstSampleRate; av_channel_layout_copy(&resampledFrame_->ch_layout, &dstChannelLayout); } return ErrorCode::SUCCESS; } void AudioCapturer::captureThreadFunc() { AV_LOGGER_INFO("音频采集线程已启动"); while (!shouldStop_) { // 检查暂停状态 { std::unique_lock lock(pauseMutex_); pauseCondition_.wait(lock, [this] { return !paused_ || shouldStop_; }); } if (shouldStop_) { break; } ErrorCode result = captureFrame(); if (result != ErrorCode::SUCCESS) { onError(result, "采集音频帧失败"); // 短暂休眠后重试 std::this_thread::sleep_for(std::chrono::milliseconds(5)); } } AV_LOGGER_INFO("音频采集线程已退出"); } ErrorCode AudioCapturer::captureFrame() { AVPacket* packet = av_packet_alloc(); if (!packet) { return ErrorCode::MEMORY_ALLOC_FAILED; } // 读取包 int ret = av_read_frame(formatCtx_, packet); if (ret < 0) { av_packet_free(&packet); if (ret == AVERROR_EOF) { AV_LOGGER_WARNING("音频流结束"); return ErrorCode::END_OF_STREAM; } else { AV_LOGGER_ERRORF("读取音频帧失败: {}", ffmpeg_utils::errorToString(ret)); return static_cast(ret); } } // 检查是否是音频包 if (packet->stream_index != audioStreamIndex_) { av_packet_free(&packet); return ErrorCode::SUCCESS; } // 发送包到解码器 ret = avcodec_send_packet(codecCtx_, packet); av_packet_free(&packet); if (ret < 0) { AV_LOGGER_ERRORF("发送音频包到解码器失败: {}", ffmpeg_utils::errorToString(ret)); return static_cast(ret); } // 接收解码后的帧 AVFramePtr frame = makeAVFrame(); if (!frame) { return ErrorCode::MEMORY_ALLOC_FAILED; } ret = avcodec_receive_frame(codecCtx_, frame.get()); if (ret == AVERROR(EAGAIN)) { return ErrorCode::SUCCESS; // 需要更多输入 } else if (ret < 0) { AV_LOGGER_ERRORF("接收音频解码帧失败: {}", ffmpeg_utils::errorToString(ret)); return static_cast(ret); } // 音频处理 AVFramePtr processedFrame = processAudioFrame(frame); if (!processedFrame) { return ErrorCode::PROCESSING_ERROR; } // 计算音频电平 calculateAudioLevel(processedFrame); // 回调 onFrameCaptured(processedFrame); return ErrorCode::SUCCESS; } AVFramePtr AudioCapturer::processAudioFrame(const AVFramePtr& frame) { if (!frame) { return nullptr; } AVFramePtr processedFrame = std::move(const_cast(frame)); // 重采样 if (needResampling_) { processedFrame = resampleAudioFrame(processedFrame); if (!processedFrame) { return nullptr; } } // 音量控制 if (currentVolume_ != 1.0f) { processedFrame = applyVolumeControl(processedFrame); } // 降噪处理 if (noiseReductionEnabled_) { processedFrame = applyNoiseReduction(processedFrame); } return processedFrame; } AVFramePtr AudioCapturer::resampleAudioFrame(const AVFramePtr& frame) { if (!frame || !swrCtx_ || !resampledFrame_) { return nullptr; } // 计算输出采样数 int outSamples = swr_get_out_samples(swrCtx_, frame->nb_samples); resampledFrame_->nb_samples = outSamples; // 重新分配缓冲区(如果需要) if (av_frame_get_buffer(resampledFrame_.get(), 0) < 0) { AV_LOGGER_ERROR("分配重采样缓冲区失败"); return nullptr; } // 执行重采样 int convertedSamples = swr_convert(swrCtx_, resampledFrame_->data, outSamples, (const uint8_t**)frame->data, frame->nb_samples); if (convertedSamples < 0) { AV_LOGGER_ERRORF("音频重采样失败: {}", ffmpeg_utils::errorToString(convertedSamples)); return nullptr; } resampledFrame_->nb_samples = convertedSamples; // 复制时间戳等信息 av_frame_copy_props(resampledFrame_.get(), frame.get()); // 创建新的frame并复制数据 AVFramePtr outputFrame = makeAVFrame(); if (!outputFrame) { return nullptr; } av_frame_ref(outputFrame.get(), resampledFrame_.get()); return outputFrame; } AVFramePtr AudioCapturer::applyVolumeControl(const AVFramePtr& frame) { if (!frame || currentVolume_ == 1.0f) { return nullptr; } // 简单的音量控制实现 AVSampleFormat format = static_cast(frame->format); int channels = frame->ch_layout.nb_channels; int samples = frame->nb_samples; if (format == AV_SAMPLE_FMT_S16) { int16_t* data = reinterpret_cast(frame->data[0]); for (int i = 0; i < samples * channels; ++i) { data[i] = static_cast(data[i] * currentVolume_); } } else if (format == AV_SAMPLE_FMT_FLT) { float* data = reinterpret_cast(frame->data[0]); for (int i = 0; i < samples * channels; ++i) { data[i] *= currentVolume_; } } return nullptr; } AVFramePtr AudioCapturer::applyNoiseReduction(const AVFramePtr& frame) { // 简单的降噪实现(实际应用中需要更复杂的算法) if (!frame) { return nullptr; } // 这里可以实现噪声门限、频谱减法等降噪算法 // 目前只是一个占位符实现 return nullptr; } void AudioCapturer::calculateAudioLevel(const AVFramePtr& frame) { if (!frame) { return; } auto now = std::chrono::steady_clock::now(); auto elapsed = std::chrono::duration(now - lastLevelUpdate_).count(); if (elapsed < LEVEL_UPDATE_INTERVAL) { return; } std::lock_guard lock(levelMutex_); AVSampleFormat format = static_cast(frame->format); int channels = frame->ch_layout.nb_channels; int samples = frame->nb_samples; double sum = 0.0; int totalSamples = samples * channels; if (format == AV_SAMPLE_FMT_S16) { const int16_t* data = reinterpret_cast(frame->data[0]); for (int i = 0; i < totalSamples; ++i) { sum += std::abs(data[i]) / 32768.0; } } else if (format == AV_SAMPLE_FMT_FLT) { const float* data = reinterpret_cast(frame->data[0]); for (int i = 0; i < totalSamples; ++i) { sum += std::abs(data[i]); } } float level = static_cast(sum / totalSamples); audioLevel_.store(std::min(level, 1.0f)); lastLevelUpdate_ = now; } void AudioCapturer::cleanupResampler() { if (swrCtx_) { swr_free(&swrCtx_); swrCtx_ = nullptr; } resampledFrame_.reset(); needResampling_ = false; } void AudioCapturer::cleanupAudioProcessing() { // 清理音频处理相关资源 noiseReductionEnabled_ = false; echoCancellationEnabled_ = false; currentVolume_ = 1.0f; audioLevel_ = 0.0f; } std::vector AudioCapturer::enumerateMicrophones() const { #ifdef _WIN32 return enumerateDirectSoundDevices(); #elif defined(__linux__) return enumerateALSADevices(); #elif defined(__APPLE__) return enumerateCoreAudioDevices(); #else return {}; #endif } std::vector AudioCapturer::enumerateSystemAudioDevices() const { #ifdef _WIN32 return enumerateWASAPIDevices(); #elif defined(__linux__) return enumeratePulseAudioDevices(); #elif defined(__APPLE__) return enumerateCoreAudioDevices(); #else return {}; #endif } const AVInputFormat* AudioCapturer::getPlatformInputFormat() const { #ifdef _WIN32 if (audioParams_.type == CapturerType::AUDIO_MIC) { return av_find_input_format("dshow"); } else { return av_find_input_format("dshow"); // WASAPI通过dshow访问 } #elif defined(__linux__) if (audioParams_.type == CapturerType::AUDIO_MIC) { return av_find_input_format("alsa"); } else { return av_find_input_format("pulse"); } #elif defined(__APPLE__) return av_find_input_format("avfoundation"); #endif return nullptr; } std::string AudioCapturer::getPlatformDeviceName() const { #ifdef _WIN32 if (audioParams_.type == CapturerType::AUDIO_MIC) { if (!audioParams_.deviceName.empty()) { return "audio=" + audioParams_.deviceName; } else { // 尝试获取可用设备列表中的第一个设备 auto devices = enumerateDirectSoundDevices(); if (!devices.empty() && audioParams_.micIndex < devices.size()) { // 使用设备的实际名称 return "audio=" + devices[audioParams_.micIndex].name; } else { // 回退到设备索引 return "audio=" + std::to_string(audioParams_.micIndex); } } } else { return "audio=" + (audioParams_.audioDevice.empty() ? "@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\\wave_{00000000-0000-0000-0000-000000000000}" : audioParams_.audioDevice); } #elif defined(__linux__) if (audioParams_.type == CapturerType::AUDIO_MIC) { if (!audioParams_.deviceName.empty()) { return audioParams_.deviceName; } else { return "hw:" + std::to_string(audioParams_.micIndex); } } else { return audioParams_.audioDevice.empty() ? "default" : audioParams_.audioDevice; } #elif defined(__APPLE__) if (audioParams_.type == CapturerType::AUDIO_MIC) { return ":" + std::to_string(audioParams_.micIndex); } else { return ":none"; } #endif return ""; } #ifdef _WIN32 std::vector AudioCapturer::enumerateDirectSoundDevices() const { std::vector devices; // 基于FFmpeg输出,我们知道有一个麦克风设备可用 // 添加已知的麦克风设备 AudioDeviceInfo micDevice; micDevice.id = "0"; micDevice.name = "Microphone (High Definition Audio Device)"; micDevice.description = "High Definition Audio Device Microphone"; micDevice.isDefault = true; micDevice.isInput = true; micDevice.supportedSampleRates = {8000, 16000, 22050, 44100, 48000}; micDevice.supportedChannels = {1, 2}; micDevice.supportedFormats = {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT}; devices.push_back(micDevice); // 添加默认设备作为后备 AudioDeviceInfo defaultDevice; defaultDevice.id = "default"; defaultDevice.name = "默认音频设备"; defaultDevice.description = "系统默认音频输入设备"; defaultDevice.isDefault = false; defaultDevice.isInput = true; defaultDevice.supportedSampleRates = {8000, 16000, 22050, 44100, 48000}; defaultDevice.supportedChannels = {1, 2}; defaultDevice.supportedFormats = {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT}; devices.push_back(defaultDevice); return devices; } std::vector AudioCapturer::enumerateWASAPIDevices() const { std::vector devices; // 简化的WASAPI设备枚举 AudioDeviceInfo device; device.id = "wasapi_default"; device.name = "默认系统音频"; device.description = "WASAPI系统音频设备"; device.isDefault = true; device.isInput = false; // 添加常见采样率 device.supportedSampleRates = {44100, 48000, 96000}; // 添加常见声道数 device.supportedChannels = {2, 6, 8}; // 添加支持的采样格式 device.supportedFormats = { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT }; devices.push_back(device); return devices; } ErrorCode AudioCapturer::setupDirectSoundMicrophone() { AV_LOGGER_INFO("设置DirectSound麦克风"); return openInputDevice(); } ErrorCode AudioCapturer::setupWASAPISystemAudio() { AV_LOGGER_INFO("设置WASAPI系统音频"); return openInputDevice(); } #endif // AudioCaptureFactory 实现 std::unique_ptr AudioCapturer::AudioCaptureFactory::createMicrophone(int micIndex) { auto capturer = std::make_unique(); AudioCaptureParams params(CapturerType::AUDIO_MIC); params.micIndex = micIndex; ErrorCode result = capturer->initialize(params); if (result != ErrorCode::SUCCESS) { AV_LOGGER_ERRORF("创建麦克风采集器失败: {}", static_cast(result)); return nullptr; } return capturer; } std::unique_ptr AudioCapturer::AudioCaptureFactory::createSystemAudio(bool loopback) { auto capturer = std::make_unique(); AudioCaptureParams params(loopback ? CapturerType::AUDIO_LOOPBACK : CapturerType::AUDIO_SYSTEM); params.captureLoopback = loopback; ErrorCode result = capturer->initialize(params); if (result != ErrorCode::SUCCESS) { AV_LOGGER_ERRORF("创建系统音频采集器失败: {}", static_cast(result)); return nullptr; } return capturer; } std::unique_ptr AudioCapturer::AudioCaptureFactory::createBestMicrophone() { return createMicrophone(0); // 默认使用第一个麦克风 } } // namespace capture } // namespace av