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

使用sip.js+React-Native-WebRTC发起呼叫报错:logger.debug未定义

问题:React Native中sip.js调用Inviter.invite()时出现logger.debug未定义错误

在React Native应用中使用sip.js结合react-native-webrtc开发语音通话功能,调用Inviter.invite()发起外呼时遇到错误:

ERROR Failed to make a call: logger.debug is not a function (it is undefined)

简化代码

import { RTCPeerConnection, mediaDevices } from 'react-native-webrtc';
import { UserAgent, Registerer, URI, Inviter } from 'sip.js';
import SipKeys from '../utils/SipKeys';
import customSessionDescriptionHandlerFactory from './customSessionDescriptionHandlerFactory';
import InCallManager from 'react-native-incall-manager';
import { logger } from './logger'

const configuration = {
  iceServers: [
    { urls: SipKeys.stunUri, username: SipKeys.username, credential: SipKeys.password },
    { urls: SipKeys.turnUri, username: SipKeys.username, credential: SipKeys.password },
    { urls: SipKeys.gStunUri, username: SipKeys.username, credential: SipKeys.password }
  ],
  iceTransportPolicy: 'all',
  bundlePolicy: 'balanced',
  rtcpMuxPolicy: 'require',
};

const createMockMediaStream = async () => {
  try {
    const stream = await mediaDevices.getUserMedia({ audio: true, video: false });
    console.debug('Stream created');
    return stream;
  } catch (error) {
    console.error('Error creating media stream', error);
    throw error;
  }
};

const createPeerConnection = async () => {
  console.debug('Initializing PeerConnection...');
  const peerConnection = new RTCPeerConnection(configuration);
  console.debug('PeerConnection initialized');

  peerConnection.onicecandidate = (iceEvent) => {
    if (iceEvent.candidate) {
      console.debug('ICE Candidate found');
    }
  };

  peerConnection.onsignalingstatechange = () => {
    console.debug(`Signaling State: ${peerConnection.signalingState}`);
  };

  peerConnection.onnegotiationneeded = async () => {
    console.debug('Negotiation needed');
  };

  peerConnection.ontrack = (event) => {
    console.debug('Track event');
  };

  peerConnection.onremovetrack = (event) => {
    console.debug('Remove track event');
  };

  const localStream = await createMockMediaStream();
  console.debug('Local stream obtained');

  localStream.getTracks().forEach(track => {
    console.debug('Adding track');
    peerConnection.addTrack(track, localStream);
  });

  const offer = await peerConnection.createOffer();
  await peerConnection.setLocalDescription(offer);
  console.debug('Offer created');

  return peerConnection;
};

const connectToSIP = async () => {
  try {
    const uri = new URI('sip', SipKeys.username, SipKeys.uri);

    const userAgentOptions = {
      uri,
      transportOptions: {
        server: SipKeys.wsServers
      },
      authorizationUsername: SipKeys.username,
      authorizationPassword: SipKeys.password,
      sessionDescriptionHandlerFactoryOptions: {
        peerConnectionOptions: { rtcConfiguration: configuration }
      },
      sessionDescriptionHandlerFactory: customSessionDescriptionHandlerFactory,
      sipExtension100rel: 'REQUIRED',
      viaHost: SipKeys.uri,
      autostart: true, // Autostart the UserAgent
    };
    const loggerObj = {
      logBuiltinEnabled: true, // Disable built-in logging if needed
      logLevel: 'debug', // Set desired log level
      logConnector: logger, // Use the custom logger
    }
    // Log the configuration to ensure logger is correctly passed
    console.log('UserAgent configuration:', userAgentOptions);

    const userAgent = new UserAgent(userAgentOptions, loggerObj);

    userAgent.delegate = {
      onConnect: () => console.debug('SIP Connected'),
      onDisconnect: () => console.debug('SIP Disconnected'),
    };

    userAgent.transport.onConnect = () => console.debug('Transport Connected');
    userAgent.transport.onDisconnect = (error) => console.error('Transport Disconnected', error);

    const registerer = new Registerer(userAgent);

    registerer.stateChange = (newState) => {
      if (newState === 'Unregistered' || newState === 'Terminated') {
        console.error('SIP Registration state changed:', newState);
      }
    };

    await userAgent.start();

    const registererOptions = {
      requestDelegate: {
        onAccept: (response) => console.debug('SIP Registered successfully!', response),
        onReject: (response) => console.error('SIP Registration failed', response),
      }
    };

    registerer.register(registererOptions);

    InCallManager.start({ media: 'audio' });

    setTimeout(() => {
      initiateOutgoingCall(userAgent);
    }, 1500);

    return { userAgent, registerer, configuration };
  } catch (error) {
    console.error('Failed to connect to SIP', error);
  }
};

const initiateOutgoingCall = async (userAgent) => {
  try {
    const target = new URI('sip', SipKeys.targetUri, SipKeys.uri);
    const inviter = new Inviter(userAgent, target, {
      earlyMedia: true,
      allowEarlyMedia: true,
      inviteWithoutSdp: false,
      sessionDescriptionHandlerOptions: {
        constraints: { audio: true, video: false },
        peerConnectionOptions: { rtcConfiguration: configuration },
        iceGatheringTimeout: 200,
      },
    });

    inviter.delegate = {
      onInvite: () => console.debug('Invite event triggered'),
      onAccepted: () => console.debug('Call accepted'),
      onProgress: response => console.debug('Call in progress', response),
      onTerminated: (message, cause) => console.error(`Call terminated: ${cause}`)
    };

    console.debug('Inviting...');
    await inviter.invite();
  } catch (error) {
    console.error(`Failed to make a call: ${error.message}`);
  }
};

解决方案

  • 问题根源:sip.js的Logger对象要求logConnector必须实现对应日志级别的方法(debug、info、warn、error等),你的自定义logger对象缺少debug方法,或者导入的logger未正确定义这些方法。

  • 修复步骤:

    1. 检查并完善自定义logger的实现,确保包含所有sip.js所需的日志方法:
      // logger.js 示例实现
      export const logger = {
        debug: (message) => console.debug(message),
        info: (message) => console.info(message),
        warn: (message) => console.warn(message),
        error: (message) => console.error(message)
      };
      
    2. 确认logger对象被正确导入,检查导入路径是否正确、是否已正确导出。
    3. 若不需要自定义日志,可直接移除loggerObj参数,使用sip.js内置日志:
      // 移除loggerObj参数
      const userAgent = new UserAgent(userAgentOptions);
      
    4. 额外检查:确保sip.js版本与react-native-webrtc版本兼容,避免版本不匹配导致的隐性问题。

内容的提问来源于stack exchange,提问作者Gurpreet Singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 21:51:12