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

Xamarin使用sipsorcery发起SIP呼叫对方听不到语音如何解决?

解决方案说明

问题根因

  • 你当前使用的SIPClientUserAgent属于低阶API,没有封装媒体会话处理逻辑,需要自行完成SDP协商、RTP流收发的全部开发
  • 代码中没有传入音频会话实例,导致发起的SIP呼叫请求未携带媒体相关SDP信息,对端无法建立RTP语音连接
  • sipsorcery默认的音频实现依赖Windows平台组件,Xamarin平台需要自行适配音频采集与播放逻辑

可参考的实现代码

第一步:修改CallViewModel逻辑

public class CallViewModel
{
    string USERNAME = "1001";
    string PASSWORD = "1234";
    string DOMAIN = "192.168.0.105";
    int EXPIRY = 120;

    SIPTransport sipTransport = new SIPTransport();
    SIPUserAgent _sipUserAgent;
    bool _isRegistered = false;

    public CallViewModel()
    {
        SIPUDPChannel udpChannel = new SIPUDPChannel(new IPEndPoint(IPAddress.Any, 0));
        sipTransport.AddSIPChannel(udpChannel);
        
        // 初始化封装了媒体逻辑的SIPUserAgent
        _sipUserAgent = new SIPUserAgent(sipTransport, null);
        
        SIPRegistrationUserAgent regUserAgent = new SIPRegistrationUserAgent(sipTransport, USERNAME, PASSWORD, DOMAIN, EXPIRY);
        regUserAgent.RegistrationFailed += Failed;
        regUserAgent.RegistrationTemporaryFailure += Failure;
        regUserAgent.RegistrationRemoved += RegRemove;
        regUserAgent.RegistrationSuccessful += Success;
        regUserAgent.Start();
    }

    // 注册成功后再发起呼叫
    private void Success(SIPURI obj)
    {
        _isRegistered = true;
        // 异步发起呼叫避免阻塞回调
        _ = Task.Run(InitiateCall);
    }

    private async Task InitiateCall()
    {
        if (!_isRegistered) return;
        
        // 初始化音频会话,测试阶段可先用正弦波虚拟音源验证RTP连接,后续替换为自己实现的Xamarin音频源
        var audioSession = new RtpAudioSession(
            new DummyAudioOptions { AudioSource = DummyAudioSourcesEnum.SineWave }, 
            new List<SDPMediaFormatsEnum> { SDPMediaFormatsEnum.PCMU }
        );
        
        // 发起呼叫,传入音频会话实例
        await _sipUserAgent.Call("sip:1002@192.168.0.105", USERNAME, PASSWORD, audioSession);
    }

    // 其余回调方法可根据业务需求实现
    private void RegRemove(SIPURI obj) => _isRegistered = false;
    private void Failure(SIPURI arg1, string arg2) { /* 注册临时失败处理逻辑 */ }
    private void Failed(SIPURI arg1, string arg2) { /* 注册失败处理逻辑 */ }
}

第二步:平台权限配置

  • Android端:在AndroidManifest.xml中添加以下权限,同时在运行时主动申请麦克风权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
  • iOS端:在Info.plist中添加麦克风使用说明
<key>NSMicrophoneUsageDescription</key>
<string>需要麦克风权限进行语音通话</string>

注意事项

  • 不要在构造函数中直接调用呼叫方法,建议等待注册成功回调触发后再发起呼叫,避免因注册未完成导致呼叫失败
  • 你需要自行实现IMediaSession接口对接Xamarin原生的AudioRecord(音频采集)和AudioTrack(音频播放)API,替换示例中的DummyAudioSourcesEnum.SineWave虚拟音频源
  • 测试时建议先在内网环境进行,排除端口映射、NAT穿越等网络问题对RTP传输的影响

内容的提问来源于stack exchange,提问作者Katya Appazova

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 18:27:03