web视频通话demo_1.3.0
<h2>一 demo 文件</h2>
<p>[<a href="https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2023-9/1694767402521/index.html.zip](https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2023-9/1694767402521/index.html.zip">https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2023-9/1694767402521/index.html.zip](https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2023-9/1694767402521/index.html.zip</a> "<a href="https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2023-9/1694767402521/index.html.zip"">https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2023-9/1694767402521/index.html.zip"</a>;)</p>
<h2>二、demo代码</h2>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
&lt;title&gt;web通话demo&lt;/title&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdn.bootcdn.net/ajax/libs/bootstrap-validator/0.5.3/css/bootstrapValidator.min.css&quot;&gt;
&lt;script src=&quot;https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2023-7/1689143438187/duerwebsdk-1.3.0.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://cdn.bootcdn.net/ajax/libs/bootstrap-validator/0.5.3/js/bootstrapValidator.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://apps.bdimg.com/libs/bootstrap/3.2.0/js/bootstrap.min.js&quot;&gt;&lt;/script&gt;
&lt;link href=&quot;https://apps.bdimg.com/libs/bootstrap/3.2.0/css/bootstrap.min.css&quot; rel=&quot;stylesheet&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class=&quot;modal&quot; role=&quot;dialog&quot; tabindex=&quot;-1&quot; style=&quot;display: block;&quot;&gt;
&lt;div class=&quot;modal-dialog&quot;&gt;
&lt;div class=&quot;modal-content&quot;&gt;
&lt;!-- 建立长连接 --&gt;
&lt;form role=&quot;form&quot; id=&quot;login-form&quot; class=&quot;form-horizontal&quot;&gt;
&lt;h2 class=&quot;desc-title&quot;&gt;RTC长连接&lt;/h2&gt;
&lt;div class=&quot;form-group&quot;&gt;
&lt;label for=&quot;name&quot; class=&quot;col-sm-2 control-label&quot;&gt;appId: &lt;/label&gt;
&lt;div class=&quot;col-sm-10&quot;&gt;
&lt;input type=&quot;text&quot; class=&quot;form-control&quot; name=&quot;appId&quot; placeholder=&quot;请输入appId&quot; required&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;form-group&quot;&gt;
&lt;label for=&quot;name&quot; class=&quot;col-sm-2 control-label&quot;&gt;uid: &lt;/label&gt;
&lt;div class=&quot;col-sm-10&quot;&gt;
&lt;input type=&quot;text&quot; class=&quot;form-control&quot; name=&quot;uid&quot; placeholder=&quot;请输入uid&quot; required&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;form-group&quot;&gt;
&lt;label for=&quot;name&quot; class=&quot;col-sm-2 control-label&quot;&gt;token: &lt;/label&gt;
&lt;div class=&quot;col-sm-10&quot;&gt;
&lt;input type=&quot;text&quot; class=&quot;form-control&quot; name=&quot;token&quot; placeholder=&quot;请输入token&quot; required&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;form-group&quot;&gt;
&lt;label for=&quot;name&quot; class=&quot;col-sm-2 control-label&quot;&gt;appName: &lt;/label&gt;
&lt;div class=&quot;col-sm-10&quot;&gt;
&lt;input type=&quot;text&quot; class=&quot;form-control&quot; name=&quot;appName&quot; placeholder=&quot;请输入appName&quot; required&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;button type=&quot;button&quot; class=&quot;btn btn-primary col-sm-offset-2&quot; onclick=&quot;checkLoginForm()&quot;&gt;建立连接&lt;/button&gt;
&lt;/form&gt;
&lt;!-- 呼叫音箱表单信息 --&gt;
&lt;form role=&quot;form&quot; id=&quot;device-form&quot; class=&quot;form-horizontal&quot; style=&quot;display: none;&quot;&gt;
&lt;!-- 手动入席离席 --&gt;
&lt;!-- &lt;select id=&quot;customer-select&quot; name=&quot;onlineStatus&quot; placeholder=&quot;请选择&quot;&gt;
&lt;option value=&quot;1&quot;&gt;入席&lt;/option&gt;
&lt;option value=&quot;0&quot;&gt;离席&lt;/option&gt;
&lt;/select&gt; --&gt;
&lt;h2 class=&quot;desc-title&quot;&gt;音箱呼叫&lt;/h2&gt;
&lt;div class=&quot;form-group&quot;&gt;
&lt;label for=&quot;appId&quot; class=&quot;col-sm-3 control-label&quot;&gt;appId:&lt;/label&gt;
&lt;div class=&quot;col-sm-9&quot;&gt;
&lt;input type=&quot;text&quot; class=&quot;form-control&quot; name=&quot;appId&quot; placeholder=&quot;请输入对端的appId&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;form-group&quot;&gt;
&lt;label for=&quot;uid&quot; class=&quot;col-sm-3 control-label&quot;&gt;uid:&lt;/label&gt;
&lt;div class=&quot;col-sm-9&quot;&gt;
&lt;input type=&quot;text&quot; class=&quot;form-control&quot; name=&quot;uid&quot; placeholder=&quot;请输入对端的uid&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;!--被叫方姓名,用于去电展示 --&gt;
&lt;div class=&quot;form-group&quot;&gt;
&lt;label for=&quot;name&quot; class=&quot;col-sm-3 control-label&quot;&gt;被叫姓名:&lt;/label&gt;
&lt;div class=&quot;col-sm-9&quot;&gt;
&lt;input type=&quot;text&quot; class=&quot;form-control&quot; name=&quot;name&quot; placeholder=&quot;请输入对端的姓名&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;form-group&quot;&gt;
&lt;label for=&quot;callMode&quot; class=&quot;col-sm-3 control-label&quot;&gt;呼叫方式:&lt;/label&gt;
&lt;div class=&quot;col-sm-9&quot;&gt;
&lt;select class=&quot;form-control&quot; name=&quot;callMode&quot; placeholder=&quot;请选择呼叫方式&quot;&gt;
&lt;option value=&quot;0&quot;&gt;视频通话&lt;/option&gt;
&lt;option value=&quot;1&quot;&gt;语音通话&lt;/option&gt;
&lt;/select&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;button type=&quot;button&quot; class=&quot;btn btn-primary col-sm-offset-3&quot; onclick=&quot;checkCallForm()&quot;&gt;呼叫&lt;/button&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;!-- 来电弹窗 --&gt;
&lt;div role=&quot;dialog&quot; class=&quot;modal fade&quot; id=&quot;incoming-call-dialog&quot; tabindex=&quot;-1&quot; aria-hidden=&quot;true&quot;&gt;
&lt;div class=&quot;modal-dialog modal-dialog-centered&quot; role=&quot;document&quot;&gt;
&lt;div class=&quot;modal-content&quot;&gt;
&lt;div class=&quot;modal-body&quot;&gt;
&lt;div class=&quot;usr-info&quot;&gt;
&lt;img class=&quot;usr-pho&quot; src=&quot;https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-7/1658388218664/pho.png&quot;&gt;
&lt;!--用于来电展示,接入方通过来电sn查询获取来电姓名 --&gt;
&lt;p class=&quot;usr-name&quot;&gt;未知来电&lt;/p&gt;
&lt;p class=&quot;incoming-call-tip&quot;&gt;邀请您通话&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;op-btns&quot;&gt;
&lt;div class=&quot;incoming-call-reject&quot;&gt;
&lt;img
onclick=&quot;rejectCall()&quot;
src=&quot;https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661433175110/reject.png&quot;
&gt;
&lt;p class=&quot;op-txt&quot;&gt;挂断&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;incoming-call-video&quot;&gt;
&lt;img
onclick=&quot;answerCall(0)&quot;
src=&quot;https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661433226356/videoCall.png&quot;
&gt;
&lt;p class=&quot;op-txt&quot;&gt;视频通话&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;incoming-call-audio&quot;&gt;
&lt;img
onclick=&quot;answerCall(1)&quot;
src=&quot;https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661433255465/audioCall.png&quot;
&gt;
&lt;p class=&quot;op-txt&quot;&gt;语音通话&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;!-- 去电响铃 --&gt;
&lt;div id=&quot;outing-call-view&quot; style=&quot;display: none;&quot;&gt;
&lt;div class=&quot;peer-info&quot;&gt;
&lt;img class=&quot;peer-pho&quot; src=&quot;https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-7/1658388218664/pho.png&quot;&gt;
&lt;!-- 业务方根据实际呼叫用户进行替换 --&gt;
&lt;p class=&quot;peer-name&quot;&gt;被叫名字&lt;/p&gt;
&lt;p class=&quot;outing-call-tip&quot;&gt;设备正在响铃中,请不要挂断...&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;op-btns&quot;&gt;
&lt;div class=&quot;out-call-mode&quot;&gt;
&lt;img
onclick=&quot;changeMode()&quot;
src=&quot;https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661828922567/videoCall0.png&quot;
&gt;
&lt;p class=&quot;out-call-mode-txt&quot;&gt;视频呼叫&lt;/p&gt;
&lt;/div&gt;
&lt;!-- &lt;div class=&quot;out-call-mode&quot;&gt;
&lt;img
onclick=&quot;changeMode()&quot;
src=&quot;https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661515364706/audio000.png&quot;
&gt;
&lt;p&gt;语音呼叫&lt;/p&gt;
&lt;/div&gt; --&gt;
&lt;div&gt;
&lt;img
onclick=&quot;dropCall()&quot;
src=&quot;https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661433175110/reject.png&quot;
&gt;
&lt;p style=&quot;color: #E24940&quot;&gt;挂断&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;!-- 通话界面 --&gt;
&lt;div id=&quot;call-view&quot; style=&quot;display: none;&quot;&gt;
&lt;div class=&quot;peer-view main-view&quot;&gt;
&lt;video id='video-peer' autoPlay&gt;&lt;/video&gt;
&lt;audio id='audio-peer' autoPlay&gt;&lt;/audio&gt;
&lt;div class=&quot;audio-tip-wrap&quot;&gt;
&lt;!-- &lt;p class=&quot;audio-name online-ellipsis&quot;&gt;对端姓名&lt;/p&gt; --&gt;
&lt;p class=&quot;audio-call&quot;&gt;语音通话中&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;local-view sub-view&quot;&gt;
&lt;video id='video-local' autoPlay&gt;&lt;/video&gt;
&lt;audio id='audio-local' autoPlay&gt;&lt;/audio&gt;
&lt;div class=&quot;audio-tip-wrap&quot;&gt;
&lt;p class=&quot;audio-name online-ellipsis&quot;&gt;本机&lt;/p&gt;
&lt;p class=&quot;audio-call&quot;&gt;语音通话中&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;op-btns&quot;&gt;
&lt;div class=&quot;mute-change-btn&quot;&gt;
&lt;img
onclick=&quot;changeMute()&quot;
src=&quot;https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661515279806/quite0.png&quot;
&gt;
&lt;p class=&quot;a-mute&quot;&gt;静音&lt;/p&gt;
&lt;/div&gt;
&lt;!-- &lt;div&gt;
&lt;img
onclick=&quot;changeAudioMute&quot;
src=&quot;https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661515279209/quite.png&quot;
&gt;
&lt;p class=&quot;a-mute&quot;&gt;已静音&lt;/p&gt;
&lt;/div&gt; --&gt;
&lt;div class=&quot;mode-change-btn&quot;&gt;
&lt;img
onclick=&quot;changeMode()&quot;
src=&quot;https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661828922567/videoCall0.png&quot;
&gt;
&lt;p class=&quot;v-mode&quot;&gt;视频通话&lt;/p&gt;
&lt;/div&gt;
&lt;!-- &lt;div&gt;
&lt;img
onclick=&quot;changeMode&quot;
src=&quot;https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661515364706/audio000.png&quot;
&gt;
&lt;p&gt;语音通话&lt;/p&gt;
&lt;/div&gt; --&gt;
&lt;div&gt;
&lt;img
onclick=&quot;dropCall()&quot;
src=&quot;https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661433175110/reject.png&quot;
&gt;
&lt;p style=&quot;color: #E24940&quot;&gt;挂断&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;audio id=&quot;ring-music&quot; loop&gt;
&lt;source src=&quot;https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-9/1662024495462/ring_new.mp3&quot; type=&quot;audio/mpeg&quot;&gt;
&lt;/audio&gt;
&lt;div class=&quot;alert alert-warning fade in&quot; id=&quot;message-alert&quot;&gt;
&lt;a href=&quot;#&quot; class=&quot;close&quot; data-dismiss=&quot;alert&quot;&gt;
&amp;times;
&lt;/a&gt;
&lt;span class=&quot;call-message&quot;&gt;呼叫超时,请稍后再试&lt;/span&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;script&gt;
const duerRtcSdk = window.DUER_rtcsdk;
const enbaleRtcDebugLog = true;
let duerRtc = null;
let customer = null;
let callInfo = {
mute: false,
mode: duerRtcSdk.CallMode.AUDIO_VIDEO
};
$(changeView());
$('#login-form').bootstrapValidator({
message: '请填写完整的信息',
feedbackIcons: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
fields: {
appId: {
validators: {
notEmpty: {
message: 'appId不能为空!'
}
}
},
uid: {
validators: {
notEmpty: {
message: 'uid不能为空!'
}
}
},
token: {
validators: {
notEmpty: {
message: 'token不能为空!'
}
}
},
appName: {
validators: {
notEmpty: {
message: 'appName不能为空!'
}
}
}
}
});
$('#device-form').bootstrapValidator({
message: '请填写完整的信息',
feedbackIcons: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
fields: {
appId: {
validators: {
notEmpty: {
message: 'appId不能为空!'
}
}
},
uid: {
validators: {
notEmpty: {
message: 'uid不能为空!'
}
}
},
name: {
validators: {
notEmpty: {
message: '被叫方姓名不能为空!'
}
}
},
callMode: {
validators: {
notEmpty: {
message: '呼叫方式不能为空!'
}
}
}
}
});
function checkLoginForm() {
$('#login-form').bootstrapValidator('validate');
const validRes = $('#login-form').data('bootstrapValidator');
if (validRes.isValid()) {
const formData = $('#login-form').serializeArray();
const loginParams = {};
for(const i in formData) {
loginParams[formData[i]['name']] = formData[i]['value'];
}
callInfo.loginParams = loginParams;
rtcListener(loginParams);
}
}
// 离席入席操作,入席web可以立即收到来电,离席web将不会收到任何来电
// $('#customer-select').change(_ =&gt; {
// const status = $('#customer-select').val();
// if (status == 1) {
// customer.join();
// } else if (status == 0) {
// customer.leave();
// }
// });
function checkCallForm() {
$('#device-form').bootstrapValidator('validate');
const validRes = $('#device-form').data('bootstrapValidator');
if (validRes.isValid()) {
const formData = $('#device-form').serializeArray();
const serialData = {};
for(const i in formData) {
serialData[formData[i]['name']] = formData[i]['value'];
}
Object.assign(callInfo, serialData);
let {appId, uid, callMode} = serialData;
makeCall(appId, uid, +callMode);
}
}
// 设置事件回调监听器
function rtcListener(loginParams) {
duerRtc = new duerRtcSdk.RtcContext({
onAuthStatusChanged: auth =&gt; {
if (auth.success) {
console.log('auth.success');
// 自动或手动入席离席只能二选一,不能混用!!!
// 开启自动入席离席
duerRtc.enableCustomer(true);
// 开启手动入席离席
// customer = duerRtc.enableCustomer(false);
// customer.join();
// this.setState({ isLogin: true })
} else {
switch (auth.code) {
case duerRtcSdk.AuthCode.PARAM_ERROR:
case duerRtcSdk.AuthCode.APPID_INVALID: {
// 联调阶段可能遇到的错误
break
}
case duerRtcSdk.AuthCode.TOKEN_INVALID:
case duerRtcSdk.AuthCode.TOKEN_EXPIRED: {
// 重新刷新token
break
}
case duerRtcSdk.AuthCode.NO_ERROR:
case duerRtcSdk.AuthCode.OTHER_DEVICE_LOGIN: {
break
}
}
}
}
}, enbaleRtcDebugLog);
duerRtc.setCallListener({
onIncomingCall: intent =&gt; {
const serviceInfo = intent.serviceInfo
&amp;&amp; JSON.parse(intent.serviceInfo)
|| {};
intent.serviceInfo = serviceInfo;
Object.assign(callInfo, intent);
incomingViewShow();
console.log(&quot;onIncomingCall&quot;, intent);
},
onAddConfereeStateChanged: state =&gt; {
console.log(&quot;onAddConfereeStateChanged&quot;, state);
},
onCallReplaced: replaced =&gt; {
console.log(&quot;onCallReplaced&quot;, replaced);
},
onCallStateChanged: stateInfo =&gt; {
if (stateInfo.state === duerRtcSdk.CallState.RINGBACK) {
// 被叫开始响铃
ringViewShow();
}
else if (stateInfo.state === duerRtcSdk.CallState.DISCONNECTED) {
// 通话已经断开
freeCallView();
if (stateInfo.reason === duerRtcSdk.CallReason.TIMEOUT) {
// 呼叫超时
callTimeout();
}
}
else if (stateInfo.state === duerRtcSdk.CallState.CONNECTED) {
// 通话被正常接听
callViewShow();
}
console.log(&quot;onCallStateChanged&quot;, stateInfo);
},
onConfereeLayout: layouts =&gt; {
setLayouts(layouts);
console.log(&quot;onConfereeLayout&quot;, layouts);
},
onRecordStateChanged: recordStateInfo =&gt; {
console.log(&quot;onRecordStateChanged&quot;, recordStateInfo);
}
});
duerRtc.setConnectListener({
onConnectionChanged: conn =&gt; {
if (conn === 2) {
// 长链接已建立
$('#login-form').hide();
$('#device-form').show();
}
if (conn === 3) {
// 长链接已断开
duerRtc = null;
}
console.log(&quot;onConnectionChanged&quot;, conn);
}
});
duerRtc.setMediaDeviceListener({
// 麦克风/摄像头状态
onMediaDeviceStateChanged: (device, state, error) =&gt; {
console.log('onMediaDeviceStateChanged', device, state, error);
}
});
rtcConnect(loginParams);
}
// 建立长连接
function rtcConnect(loginParams) {
let {uid, appId} = loginParams;
const uri = new duerRtcSdk.CallUri(uid, appId);
loginParams.uri = uri;
duerRtc.login(loginParams);
}
// 呼叫
function makeCall(appId, uid, callMode, callerRole = duerRtcSdk.CallerRole.CALL_CENTER) {
const calleeUri = new duerRtcSdk.CallUri(uid, appId);
let intent = duerRtcSdk.MakeCallIntent(calleeUri, duerRtcSdk.CallMode.AUDIO_VIDEO);
callMode &amp;&amp; (intent.callMode = callMode);
callerRole &amp;&amp; (intent.callerRole = callerRole);
callInfo.callMode = callMode;
const result = duerRtc.makeCall(intent)
console.info('makeCall action', intent, result)
if (duerRtcSdk.CallReason.NORMAL == result) {
// 呼出成功
} else if (duerRtcSdk.CallReason.ALREADY_IN_CALL == result || CallReason.EXCEPTION_INPUT_ILLEGAL == result) {
console.error('makeCall resaon', duerRtcSdk.CallReasonMap.get(result))
}
else {
// 其他原因,目前不会出现
console.warn('makeCall res', result)
}
}
// 来电接听
function answerCall(mode) {
duerRtc.answerCall(callInfo.index, mode, false);
callInfo.callMode = mode;
}
// 拒接来电
function rejectCall() {
duerRtc.rejectIncomingCall(callInfo.index, 'REJECT_CALL_USER_REASON');
}
// 改变通话模式 type 1去电 2通话中
function changeMode() {
const mode = callInfo.callMode == duerRtcSdk.CallMode.AUDIO_VIDEO
? duerRtcSdk.CallMode.AUDIO_ONLY
: duerRtcSdk.CallMode.AUDIO_VIDEO;
console.log(mode, callInfo.callMode);
if (mode == duerRtcSdk.CallMode.AUDIO_VIDEO) {
$('.out-call-mode img').attr('src', 'https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661515364706/audio000.png');
$('.out-call-mode-txt').text('语音通话');
$('.mode-change-btn img').attr('src', 'https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661515364706/audio000.png');
$('.v-mode').text('语音通话');
$('.audio-tip-wrap').hide();
} else if (mode == duerRtcSdk.CallMode.AUDIO_ONLY) {
$('.out-call-mode img').attr('src', 'https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661828922567/videoCall0.png');
$('.out-call-mode-txt').text('视频通话');
$('.mode-change-btn img').attr('src', 'https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661828922567/videoCall0.png');
$('.v-mode').text('视频通话');
$('.audio-tip-wrap').show();
}
duerRtc.changeCallMode(mode);
callInfo.callMode = mode;
}
// 静音状态切换
function changeMute() {
if (callInfo.mute) {
$('.mute-change-btn img').attr('src', 'https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661515279806/quite0.png');
$('.a-mute').text('静音');
} else {
$('.mute-change-btn img').attr('src', 'https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661515279209/quite.png');
$('.a-mute').text('已静音');
}
callInfo.mute = !callInfo.mute;
duerRtc.muteAudio(callInfo.mute);
}
// 挂断通话
function dropCall() {
duerRtc.dropCall('DROP_CALL_USER_REASON');
}
// 设置音视频
function setLayouts(layouts) {
if (!layouts) {
return;
}
// const audioLocal = $('#audio-local').get(0);
// const videoLocal = $('#video-local').get(0);
// const audioPeer = $('#audio-peer').get(0);
// const videoPeer = $('#video-peer').get(0);
const audioLocal = document.getElementById('audio-local');
const videoLocal = document.getElementById('video-local');
const audioPeer = document.getElementById('audio-peer');
const videoPeer = document.getElementById('video-peer');
const [layoutLocal, layoutPeer] = layouts;
if (layoutLocal.videoTrack) {
$('#video-local').show();
$('.local-view .audio-tip-wrap').hide();
const stream = new MediaStream;
stream.addTrack(layoutLocal.videoTrack);
videoLocal.srcObject = stream;
}
else {
$('#video-local').hide();
$('.local-view .audio-tip-wrap').show();
}
if (layoutLocal.audioTrack &amp;&amp; !layoutLocal.isLocal) {
const stream = new MediaStream;
stream.addTrack(layoutLocal.audioTrack);
audioLocal.srcObject = stream;
}
if (layoutPeer.videoTrack) {
$('#video-peer').show();
$('.peer-view .audio-tip-wrap').hide();
const stream = new MediaStream;
stream.addTrack(layoutPeer.videoTrack);
videoPeer.srcObject = stream;
}
else {
$('#video-peer').hide();
$('.peer-view .audio-tip-wrap').show();
}
if (layoutPeer.audioTrack) {
const stream = new MediaStream;
stream.addTrack(layoutPeer.audioTrack);
audioPeer.srcObject = stream;
}
}
// 视频大小窗口切换事件
function changeView() {
$('.peer-view').click(_ =&gt; {
const cList = $('.peer-view').attr('class');
if (~cList.indexOf('sub-view')) {
$('.peer-view').attr('class', 'peer-view main-view');
$('.local-view').attr('class', 'local-view sub-view');
}
});
$('.local-view').click(_ =&gt; {
const cList = $('.local-view').attr('class');
if (~cList.indexOf('sub-view')) {
$('.local-view').attr('class', 'local-view main-view');
$('.peer-view').attr('class', 'peer-view sub-view');
}
});
}
// 去电响铃时界面展示
function ringViewShow() {
$('#ring-music').get(0).play();
$('.peer-name').text(callInfo.name);
if (callInfo.callMode == duerRtcSdk.CallMode.AUDIO_VIDEO) {
// 当前为视频通话
$('.out-call-mode img').attr('src', 'https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661515364706/audio000.png');
$('.out-call-mode-txt').text('语音通话');
} else if (callInfo.callMode == duerRtcSdk.CallMode.AUDIO_ONLY) {
// 当前为音频通话
$('.out-call-mode img').attr('src', 'https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661828922567/videoCall0.png');
$('.out-call-mode-txt').text('视频通话');
}
$('#outing-call-view').show();
}
// 收到来电
function incomingViewShow() {
$('#incoming-call-dialog').modal('show');
$('#ring-music').get(0).play();
}
// 空闲状态
function freeCallView() {
$('#outing-call-view').hide();
$('#call-view').hide();
$('#incoming-call-dialog').modal('hide');
$('#ring-music').get(0).pause();
Object.assign(callInfo, {
mute: false
});
}
// 通话正常接听
function callViewShow() {
$('#ring-music').get(0).pause();
$('#incoming-call-dialog').modal('hide');
$('#outing-call-view').hide();
if (callInfo.mute) {
// 已静音
$('.mute-change-btn img').attr('src', 'https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661515279209/quite.png');
$('.a-mute').text('已静音');
} else {
$('.mute-change-btn img').attr('src', 'https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661515279806/quite0.png');
$('.a-mute').text('静音');
}
if (callInfo.callMode == duerRtcSdk.CallMode.AUDIO_VIDEO) {
// 当前为视频通话
$('.mode-change-btn img').attr('src', 'https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661515364706/audio000.png');
$('.v-mode').text('语音通话');
$('.audio-tip-wrap').hide();
} else if (callInfo.callMode == duerRtcSdk.CallMode.AUDIO_ONLY) {
// 当前为音频通话
$('.mode-change-btn img').attr('src', 'https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661828922567/videoCall0.png');
$('.v-mode').text('视频通话');
$('.audio-tip-wrap').show();
}
$('#call-view').show();
}
// 呼叫超时
function callTimeout() {
$('#outing-call-view').hide();
$('#message-alert').show();
}
// 获取浏览器权限,根据实际情况调用,只限于用户没有做过授权
function getDevice() {
navigator.getUserMedia = navigator.getUserMedia
|| navigator.webkitGetUserMedia
|| navigator.mozGetUserMedia
|| navigator.msGetUserMedia;
if (navigator.getUserMedia) {
navigator.getUserMedia({video: true}, function onSuccess(stream) {
console.log('摄像头开启成功');
}, function onError(error) {
alert(&quot;摄像头错误:&quot;, error);
});
navigator.getUserMedia({audio:true}, function onSuccess(stream) {
console.log('麦克风开启成功');
}, function onError(error) {
alert(&quot;麦克风错误:&quot;, error);
});
}
else {
alert('暂不支持');
}
}
// 定时获取摄像头麦克风权限,根据业务实际情况调用
// 用于定位音视频是否因为权限问题不显示
// setInterval(_ =&gt; {
// getDevice();
// }, 10000);
&lt;/script&gt;
&lt;style&gt;
body {
background-color: #141e30;
}
#login-form, #device-form {
width: 500px;
margin: 20px auto 20px;
}
.usr-info {
text-align: center;
}
.usr-pho {
margin-top: 35px;
width: 120px;
height: 120px;
}
.usr-name {
margin-top: 10px;
font-weight: 500;
font-size: 30px;
line-height: 42px;
color: #1A1A1A;
}
.incoming-call-tip {
font-size: 16px;
line-height: 22px;
color: #666666;
}
.op-btns {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.op-btns img {
width: 80px;
height: 80px;
margin: 16px 40px;
cursor: pointer;
}
.op-txt {
line-height: 20px;
text-align: center;
}
#outing-call-view, #call-view {
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: 10052;
background: #3c3667;
color: #fff;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
#outing-call-view .op-btns {
margin-top: 50px;
}
.peer-pho {
width: 104px;
height: 104px;
margin-top: 50px;
}
.peer-name {
font-size: 60px;
line-height: 86px;
}
.outing-call-tip {
font-size: 42px;
line-height: 60px;
color: rgba(225, 225, 225, .5);
}
#call-view .op-btns {
position: absolute;
bottom: 50px;
}
.main-view {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
background-image: url('https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661773897681/audioBg.png');
background-repeat: no-repeat;
background-size: 100% 100%;
color: #fff;
text-align: center;
}
.main-view video {
width: 100%;
object-fit: fill;
}
.main-view .audio-name {
margin-top: 100px;
font-size: 62px;
line-height: 87px;
}
.main-view .audio-call {
font-size: 36px;
line-height: 50px;
color: rgba(225, 225, 225, .5);
margin-top: 17px;
}
.main-view .audio-tip-wrap {
position: absolute;
top: 0;
}
.sub-view {
width: 320px;
height: 192px;
position: absolute;
left: 48px;
top: 48px;
background-image: url('https://dumi-dueros-bj-tob.cdn.bcebos.com/amis/2022-8/1661773897681/audioBg.png');
background-repeat: no-repeat;
background-size: 100%;
color: #fff;
z-index: 1;
}
.sub-view video {
width: 320px;
height: 192px;
object-fit: fill;
}
.sub-view .audio-tip-wrap {
position: absolute;
bottom: 10px;
right: 10px;
}
.sub-view .audio-name {
font-size: 48px;
line-height: 67px;
max-width: 300px;
}
.sub-view .audio-call {
font-size: 24px;
line-height: 34px;
text-align: right;
}
#message-alert {
position: fixed;
z-index: 1053;
width: 300px;
right: 0;
top: 10px;
display: none;
}
.desc-title {
text-align: center;
margin-bottom: 20px;
}
&lt;/style&gt;
&lt;/html&gt;</code></pre>