You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebRTC M110版本C++实现自定义音频源方法求助

问题:WebRTC M110版本自定义音频输入无法让远端接收音频轨

我查找资料许久,大多是关于使用AudioDeviceModule实现自定义音频输入的内容,但尝试后遇到问题:客户端无法接收任何音频轨,Observer中的OnTrack仅能获取到视频轨。

尝试的AudioDeviceModule实现代码:

class AudioCaptureModule 
    : public webrtc::AudioDeviceModule
    , public rtc::RefCountInterface
{
// ...
}

auto adm = new rtc::RefCountedObject<AudioCaptureModule>();
auto pc_factory = webrtc::CreatePeerConnectionFactory(
        nullptr,
        nullptr,
        nullptr,
        std::move(adm),
        webrtc::CreateBuiltinAudioEncoderFactory(),
        webrtc::CreateBuiltinAudioDecoderFactory(),
        webrtc::CreateBuiltinVideoEncoderFactory(),
        webrtc::CreateBuiltinVideoDecoderFactory(),
        nullptr,
        nullptr);

我还了解到AudioSourceInterface类,但不确定在当前使用的M110最新稳定版本中是否可行,因为它似乎是旧版本(如M79)的实现方式。请问在最新稳定版本中,有没有实现自定义音频输入并让远端接收音频轨生效的方法?

尝试的AudioSourceInterface相关代码:

class CustomAudioSource : public rtc::RefCountedObject<webrtc::AudioSourceInterface> {
public:
  explicit CustomAudioSource(int sample_rate_hz) : sample_rate_hz_(sample_rate_hz) {}
  
  void AddSink(AudioTrackSinkInterface* sink) override {
    sinks_.push_back(sink);
  }

  void RemoveSink(AudioTrackSinkInterface* sink) override {
    auto it = std::find(sinks_.begin(), sinks_.end(), sink);
    if (it != sinks_.end()) {
      sinks_.erase(it);
    }
  }

  void GenerateAudio(int16_t* audio_data, int sample_rate_hz, size_t num_channels, size_t num_samples) {
    for (auto sink : sinks_) {
      sink->OnData(audio_data, num_samples, sample_rate_hz, num_channels);
    }
  }

private:
  int sample_rate_hz_;
  std::vector<AudioTrackSinkInterface*> sinks_;
};

rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> peer_connection_factory =
    webrtc::CreatePeerConnectionFactory();

webrtc::PeerConnectionInterface::RTCConfiguration config;
rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection =
    peer_connection_factory->CreatePeerConnection(config, nullptr, nullptr, nullptr, nullptr);

auto audio_device_module = webrtc::AudioDeviceModule::Create(0, webrtc::AudioDeviceModule::kPlatformDefaultAudio);
auto audio_source = std::make_unique<MyCustomAudioSource2>();
auto audio_track = peer_connection_factory->CreateAudioTrack("audio_track", audio_device_module->CreateAudioSource(std::move(audio_source)));

peer_connection->AddTrack(audio_track, {"stream"});

解决方案(WebRTC M110+版本)

在M110及以上版本,官方推荐使用**自定义AudioTrackSource**实现自定义音频输入,这是替代旧AudioSourceInterface方案的现代方式,具体步骤如下:

1. 实现自定义AudioTrackSource

继承rtc::RefCountedObject<webrtc::AudioTrackSourceInterface>,实现核心接口方法:

class CustomAudioTrackSource : public rtc::RefCountedObject<webrtc::AudioTrackSourceInterface> {
public:
  CustomAudioTrackSource() : is_live_(true) {}

  // 标识是否为实时音频源,必须返回true
  bool is_live() const override { return is_live_; }

  // 返回源状态,固定为kLive即可
  webrtc::MediaSourceInterface::SourceState state() const override {
    return webrtc::MediaSourceInterface::SourceState::kLive;
  }

  // 添加音频数据接收器
  void AddSink(webrtc::AudioTrackSinkInterface* sink) override {
    std::lock_guard<std::mutex> lock(sinks_mutex_);
    sinks_.push_back(sink);
  }

  // 移除音频数据接收器
  void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override {
    std::lock_guard<std::mutex> lock(sinks_mutex_);
    auto it = std::find(sinks_.begin(), sinks_.end(), sink);
    if (it != sinks_.end()) {
      sinks_.erase(it);
    }
  }

  // 推送自定义音频数据到所有接收器
  void PushAudioData(const int16_t* audio_data,
                     int sample_rate_hz,
                     size_t num_channels,
                     size_t num_samples) {
    std::lock_guard<std::mutex> lock(sinks_mutex_);
    for (auto sink : sinks_) {
      sink->OnData(audio_data, num_samples, sample_rate_hz, num_channels);
    }
  }

private:
  bool is_live_;
  std::mutex sinks_mutex_; // 多线程环境下保护接收器列表
  std::vector<webrtc::AudioTrackSinkInterface*> sinks_;
};

2. 创建并使用自定义音频源

通过PeerConnectionFactory直接创建音频轨道,无需依赖AudioDeviceModule的旧接口:

// 创建PeerConnectionFactory(M110版本参数要求)
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory =
    webrtc::CreatePeerConnectionFactory(
        nullptr, nullptr, nullptr, nullptr,
        webrtc::CreateBuiltinAudioEncoderFactory(),
        webrtc::CreateBuiltinAudioDecoderFactory(),
        webrtc::CreateBuiltinVideoEncoderFactory(),
        webrtc::CreateBuiltinVideoDecoderFactory(),
        nullptr, nullptr);

// 实例化自定义音频源
rtc::scoped_refptr<CustomAudioTrackSource> custom_audio_source =
    new rtc::RefCountedObject<CustomAudioTrackSource>();

// 创建音频轨道
rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track =
    pc_factory->CreateAudioTrack("custom_audio_track", custom_audio_source);

// 创建PeerConnection并添加音频轨道
webrtc::PeerConnectionInterface::RTCConfiguration config;
rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection =
    pc_factory->CreatePeerConnection(config, nullptr, nullptr, nullptr, nullptr);

peer_connection->AddTrack(audio_track, {"stream_id"});

3. 推送音频数据

在你的音频数据生成/采集逻辑中,调用PushAudioData将数据推送到轨道:

// 示例:生成静音数据(替换为你的实际音频采集逻辑)
const int sample_rate = 48000; // WebRTC推荐采样率
const size_t num_channels = 2; // 立体声
const size_t num_samples_per_channel = 960; // 每20ms推送一次的采样数
std::vector<int16_t> audio_data(num_channels * num_samples_per_channel, 0);

custom_audio_source->PushAudioData(audio_data.data(), sample_rate, num_channels, num_samples_per_channel);

原AudioDeviceModule方案失败的可能原因

  • 未完整实现AudioDeviceModule的核心方法(如Init、RecordingStart、RecordingStop)
  • 未正确向WebRTC内部音频管道推送数据(遗漏内部回调调用)
  • M110版本对AudioDeviceModule的实现要求更严格,缺失接口会导致音频轨无法被识别

注意事项

  • 音频数据格式需匹配WebRTC要求:推荐48kHz采样率、16位深度、立体声
  • 推送数据频率要与采样率匹配(如48kHz下每20ms推送960个采样点/通道)
  • 多线程环境下必须用互斥锁保护接收器列表,避免并发访问问题

内容的提问来源于stack exchange,提问作者da Pan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 16:01:03