我正在尝试使用以下库从客户端(浏览器)调用 FreeSWITCH 服务器:
我也使用 React。
当我拨打电话时,我成功邀请了目的地 URI。
单击按钮并调用函数 callSip 后,我们的 SessionState 变为 Ringing,然后邀请成功,然后 SessionState 为“Answered”,然后运行 requestDelegate 对象中的 onAccept 函数,但没有建立连接,因为 SessionState 变为“Ended”
毕竟我有这个日志。
如何建立语音连接,使其接听电话不中断?如何将远程声音从 sip 添加到音频参考元素?
const CallList: React.FC<Props> = (props) => {
const [userURI, setUserURI] = useState<URI | null>(null);
const audioRef = useRef(null);
useEffect(() => {
const uri = UserAgent.makeURI("sip:9012@serverpoint");
if (!uri) {
throw new Error("Failed to create URI");
}
setUserURI(uri);
return () => {
console.log("unmount");
};
}, []);
if (!userURI) {
return <div></div>;
}
const userAgentOptions: UserAgentOptions = {
uri: userURI,
authorizationPassword: "pasw",
authorizationUsername: "9012",
transportOptions: {
server: "ws://serverpoint",
},
};
const userAgent = new UserAgent(userAgentOptions);
const target = UserAgent.makeURI("sip:9005@serverpoint");
const session = new Inviter(userAgent, target as URI);
// Setup session state change handler
session.stateChange.addListener((newState: SessionState) => {
switch (newState) {
case SessionState.Establishing:
alert("Ringing");
break;
case SessionState.Established:
alert("Answered");
break;
case SessionState.Terminated:
alert("Ended");
break;
}
});
// Options including delegate to capture response messages
const inviteOptions: InviterInviteOptions = {
requestDelegate: {
onAccept: (response) => {
console.log(response.message);
alert("Positive response");
console.log("Positive response = " + response);
},
onReject: (response) => {
console.log("Negative response = " + response);
},
},
sessionDescriptionHandlerOptions: {
constraints: {
audio: true,
video: false,
},
},
};
const callSIP = () => {
session
.invite(inviteOptions)
.then((request: OutgoingInviteRequest) => {
alert("Successfully sent INVITE");
alert("INVITE request = " + request);
})
.catch((error: Error) => {
console.log("Failed to send INVITE");
});
};
const stop = () =>
setTimeout(() => {
userAgent
.stop()
.then(() => {
console.log("Stopped");
})
.catch((error) => {
console.error("Failed to stop");
});
}, 5000);
userAgent
.start()
.then(() => {
console.log("Connected");
const registerer = new Registerer(userAgent);
registerer.stateChange.addListener((newStat) => {
console.log(newStat);
// switch (newState) {
// case RegistererState.Registered:
// console.log("Registered");
// break;
// case RegistererState.Unregistered:
// console.log("Unregistered");
// break;
// case RegistererState.Terminated:
// console.log("Terminated");
// break;
// }
});
registerer
.register()
.then((request) => {
alert("Successfully sent REGISTER");
alert("Sent request = " + request);
})
.catch((error) => {
console.error("Failed to send REGISTER");
});
if (registerer.state === "Registered") {
// Currently registered
alert("Registered");
}
// stop();
})
.catch((error) => {
console.error("Failed to connect");
});
const panes = [
{
menuItem: "Calls",
render: () => (
<Tab.Pane loading={false}>
<List celled>
<List.Item>
<audio ref={audioRef} id="remote-audio"></audio>
</List.Item>
{props.data.map((item) => (
<List.Item key={v4()} onClick={callSIP}>
<Image avatar src="" />
<List.Content>
<List.Header>
{item.location} - {item.number}
</List.Header>
{item.timestamp}
</List.Content>
<List.Content floated="right">
<Button>Call</Button>
</List.Content>
</List.Item>
))}
</List>
</Tab.Pane>
),
},
{
menuItem: "tab 2",
render: () => <Tab.Pane>Tab 2 Content</Tab.Pane>,
},
];
return (
<Container>
<Tab panes={panes} />
</Container>
);
};
export default CallList;