I’m building a web-based SIP phone application using JsSIP (version 3.10.0) to handle VoIP calls over WebRTC. My setup works fine for inbound calls—audio streams both ways—but I’m facing an issue with outbound calls where I can’t hear the remote party, and the “peerconnection” event isn’t firing as expected.
What I’m Doing
Setup: I’m using JsSIP to connect to a SIP server via WebSocket (WSS). The client registers successfully and can initiate/receive calls.
Code Structure: I handle all new sessions (inbound and outbound) in a handleNewRTCSession function triggered by the “newRTCSession” event from JsSIP’s UA. For WebRTC, I rely on the “peerconnection” event to access the RTCPeerConnection and attach a “track” listener to capture the remote audio stream.
Outbound Call Flow: I call userAgent.call(target, callOptions) to start an outbound call. The call connects (remote party answers), and they can hear me, but I don’t hear them.
const userAgent = new JsSIP.UA({
uri: "sip:[email protected]",
password: "****",
sockets: [new JsSIP.WebSocketInterface("wss://sip-server.example.com:7443")],
});
const callOptions = {
mediaConstraints: { audio: true, video: false },
pcConfig: { iceServers: [{ urls: "stun:stun.l.google.com:19302" }] },
};
userAgent.on("newRTCSession", handleNewRTCSession);
function handleNewRTCSession(e) {
const session = e.session;
console.log("New session:", session.direction);
session.on("peerconnection", (data) => {
console.log("Peerconnection event:", data);
const peerConnection = data.peerconnection;
peerConnection.addEventListener("track", (event) => {
console.log("Remote stream received:", event.streams[0]);
document.getElementById("remoteAudio").srcObject = event.streams[0];
});
});
session.on("accepted", () => {
console.log("Call accepted");
});
session.on("failed", (e) => {
console.log("Call failed:", e.cause);
});
if (session.direction === "outgoing") {
console.log("Outbound call started");
}
}
function makeCall(target) {
userAgent.call(target, callOptions);
}
// Start UA
userAgent.start();
The Workaround which i’m trying right now is forcing peerconnection when the call is accepted in outbound case:
if (session.connection && session.direction === óutgoing) {
console.log("Manually handling peer connection:", session.connection);
handlePeerConnection({ peerconnection: session.connection });
}
function handlePeerConnection(data) {
console.log(data);
const peerConnection = data.peerconnection;
peerConnection.addEventListener("track", (event) => {
console.log(event);
console.log("StreamViewType", event.streams);
const remoteStream = event.streams[0];
console.log("Remote stream received:", remoteStream);
audioElement.srcObject = remoteStream;
audioElement
.play()
.catch((e) => console.error("Audio playback failed:", e));
});
peerConnection.addEventListener("icecandidate", (event) => {
if (event.candidate) {
console.log("ICE candidate:", event.candidate);
} else {
console.log("ICE gathering complete");
}
});
}
Questions
- Why isn’t the “peerconnection” event firing for outbound calls in
JsSIP 3.10.0, even though the call connects and session.connection
exists?
- Is this a known bug, a configuration issue, or something specific to
my SIP server’s SDP/ICE handling?
- Is manually using session.connection a safe long-term solution, or
should I adjust my approach (e.g., update JsSIP, change
callOptions)?
Additional Details
JsSIP Version: 3.10.0
Browser: Chrome (latest)
SIP Server: A hosted FusionPBX.
SDP: Local offers Opus/G722/PCMU, remote responds with G722, both sendrecv.
I’d appreciate any insights or suggestions to fix this cleanly without relying on the workaround. Thanks!