beelink/public/js/device-testing.js
2020-11-12 17:27:59 +08:00

839 lines
25 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 设备检测demo
*/
/* global $ TRTC presetting getOS getBroswer cameraId micId */
// 用于记录检测结果,生成检测报告
let hasCameraDevice = false,
hasMicAndVoiceDevice = false,
hasCameraConnect,
hasVoiceConnect,
hasMicConnect,
hasNetworkConnect;
let cameraTestingResult = {};
let voiceTestingResult = {};
let micTestingResult = {};
let networkTestingResult = {};
// 记录检测步骤,用于关闭时清空弹窗
let completedTestingPageIdList = [];
let curTestingPageId = '';
let localStream = null;
let client = null;
let timeout = null;
// 监听到network-quality事件的次数
let networkQualityNum = 0;
const deviceFailAttention =
'1. 若浏览器弹出提示,请选择“允许”<br>' +
'2. 若杀毒软件弹出提示,请选择“允许”<br>' +
'3. 检查浏览器设置,允许网页访问摄像头及麦克风<br>' +
'4. 检查摄像头/麦克风是否正确连接并开启<br>' +
'5. 尝试重新连接摄像头/麦克风<br>' +
'6. 尝试重启电脑后重新检测';
const networkFailAttention =
'1. 请检查设备是否联网<br>' + '2. 请刷新网页后再次检测<br>' + '3. 请尝试更换网络后再次检测';
// 网络参数对照表
const NETWORK_QUALITY = {
'0': '未知',
'1': '极佳',
'2': '较好',
'3': '一般',
'4': '差',
'5': '极差',
'6': '断开'
};
// 设备检测tab页签对应的执行方法
const pageCallbackConfig = {
'camera-testing-body': 'startCameraTesting',
'voice-testing-body': 'startVoiceTesting',
'mic-testing-body': 'startMicTesting',
'network-testing-body': 'startNetworkTesting'
};
// 判断是否为safari浏览器
let isSafari = /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);
hideVoiceForSafari();
/**
* safari浏览器中隐藏扬声器相关检测
*/
function hideVoiceForSafari() {
if (!isSafari) return;
$('#connect-voice').hide();
$('#device-voice').hide();
$('#voice-testing').hide();
$('#voice-report').hide();
$('#device-mic').addClass('safari');
$('#device-network').addClass('safari');
$('#mic-testing').addClass('safari');
$('#network-testing').addClass('safari');
}
// 是否是本地路径打开
let isFilePath = location.href.indexOf('file://') > -1;
/**
* 设备检测初始化
*/
async function deviceTestingInit() {
// 点击【设备检测】文字, 点击 【重新连接】按钮
$('#device-testing-btn, #connect-again-btn').on('click', () => {
startDeviceConnect();
});
// 连接设备错误icon
$('#connect-attention-icon').on('mouseover', () => {
$('#connect-attention-info').show();
});
// 连接设备错误icon
$('#connect-attention-icon').on('mouseout', () => {
$('#connect-attention-info').hide();
});
// 【开始检测】开始设备检测按钮
$('#start-test-btn').on('click', function() {
if ($(this).hasClass('start-gray')) return;
$('#device-testing-prepare').hide();
$('#device-testing').show();
startCameraTesting();
});
// 摄像头检测失败/成功
$('#camera-fail, #camera-success').on('click', function() {
cameraTestingResult.statusResult = $(this).attr('id') === 'camera-success';
$('#camera-testing-body').hide();
localStream.close();
// safari浏览器跳过扬声器检测
isSafari ? startMicTesting() : startVoiceTesting();
});
// 播放器检测失败/成功
$('#voice-fail, #voice-success').on('click', function() {
voiceTestingResult.statusResult = $(this).attr('id') === 'voice-success';
$('#voice-testing-body').hide();
let audioPlayer = document.querySelector('#audio-player');
if (!audioPlayer.paused) {
audioPlayer.pause();
}
startMicTesting();
});
// 麦克风测试失败/成功
$('#mic-fail, #mic-success').on('click', function() {
micTestingResult.statusResult = $(this).attr('id') === 'mic-success';
$('#mic-testing-body').hide();
localStream.close();
startNetworkTesting();
});
// 点击【查看检测报告】按钮
$('#testing-report-btn').on('click', () => {
showTestingReport();
localStream.close();
client && client.leave();
client && client.off('network-quality');
});
// 点击【重新测试】按钮
$('#testing-again').on('click', () => {
$('#device-testing-report').hide();
startDeviceConnect();
completedTestingPageIdList = [];
});
// 点击【测试完成】按钮 / 点击关闭图标
$('#testing-finish, #device-testing-close-btn').on('click', () => {
finishDeviceTesting();
});
// 测试tab页切换
$('#camera-testing, #voice-testing, #mic-testing, #network-testing').on('click', function() {
let targetPageId = $(this).attr('id') + '-body';
if (
targetPageId !== curTestingPageId &&
completedTestingPageIdList.indexOf(targetPageId) > -1
) {
$(`#${curTestingPageId}`).hide();
localStream && localStream.close();
client && client.leave();
client && client.off('network-quality');
// 停止播放器的音乐
let audioPlayer = document.querySelector('#audio-player');
if (!audioPlayer.paused) {
audioPlayer.pause();
}
// 展示要切换的设备检测tab页面
$(`#${targetPageId}`).show();
window[pageCallbackConfig[targetPageId]] && window[pageCallbackConfig[targetPageId]]();
}
});
// 摄像头设备切换
$('#camera-select').change(async function() {
let newCameraId = $(this)
.children('option:selected')
.val();
localStorage.setItem('txy_webRTC_cameraId', newCameraId);
cameraTestingResult.device = {
label: $(this)
.children('option:selected')
.text(),
deviceId: $(this)
.children('option:selected')
.val(),
kind: 'videoinput'
};
await localStream.switchDevice('video', newCameraId);
});
// 扬声器设备切换
$('#voice-select').change(async function() {
let newVoiceId = $(this)
.children('option:selected')
.val();
localStorage.setItem('txy_webRTC_voiceId', newVoiceId);
voiceTestingResult.device = {
label: $(this)
.children('option:selected')
.text(),
deviceId: $(this)
.children('option:selected')
.val(),
kind: 'audiooutput'
};
let audioPlayer = document.querySelector('#audio-player');
await audioPlayer.setSinkId(newVoiceId);
});
// 麦克风设备切换
$('#mic-select').change(async function() {
let newMicID = $(this)
.children('option:selected')
.val();
localStorage.setItem('txy_webRTC_micId', newMicID);
micTestingResult.device = {
label: $(this)
.children('option:selected')
.text(),
deviceId: $(this)
.children('option:selected')
.val(),
kind: 'audioinput'
};
await localStream.switchDevice('audio', newMicID);
});
$('body').on('click', function() {
$('#device-connect-list').hide();
});
// 获取设备信息
await getDevicesInfo();
// 初始化设备弹窗信息
deviceDialogInit();
}
/**
* 获取设备信息及网络连接信息
*/
async function getDevicesInfo() {
let micList = await TRTC.getMicrophones();
let voiceList = await TRTC.getSpeakers();
let cameraList = await TRTC.getCameras();
let index = isFilePath ? 'label' : 'deviceId';
if (cameraList.length > 0) {
hasCameraDevice = true;
}
if (micList.length > 0) {
hasMicAndVoiceDevice = true;
}
cameraList.forEach(camera => {
if (camera[index].length > 0) {
hasCameraConnect = true;
}
});
micList.forEach(mic => {
if (mic[index].length > 0) {
hasMicConnect = true;
}
});
if (isSafari) {
hasVoiceConnect = true;
} else {
voiceList.forEach(voice => {
if (voice[index].length > 0) {
hasVoiceConnect = true;
}
});
}
hasNetworkConnect = !!navigator.onLine;
}
/**
* 判断是否展示弹窗
*/
function deviceDialogInit() {
if (!localStorage.getItem('txy_device_testing')) {
localStorage.setItem('txy_device_testing', Date.now());
startDeviceConnect();
} else {
// 在首页展示设备连接结果
let showDeviceStatus = function() {
$('#device-connect-list').show();
timeout = setTimeout(() => {
$('#device-connect-list').hide();
}, 3000);
$('#connect-camera').css('color', `${hasCameraConnect ? 'green' : 'red'}`);
$('#connect-voice').css('color', `${hasVoiceConnect ? 'green' : 'red'}`);
$('#connect-mic').css('color', `${hasMicConnect ? 'green' : 'red'}`);
$('#connect-network').css('color', `${hasNetworkConnect ? 'green' : 'red'}`);
if (!(hasCameraConnect && hasVoiceConnect && hasMicConnect && hasNetworkConnect)) {
$('#device-testing-btn').css('color', 'red');
} else {
$('#device-testing-btn').css('color', 'green');
}
};
showDeviceStatus();
if (!(hasCameraConnect && hasVoiceConnect && hasMicConnect)) {
navigator.mediaDevices
.getUserMedia({ video: hasCameraDevice, audio: hasMicAndVoiceDevice })
.then(async () => {
// 重新获取设备信息
await getDevicesInfo();
// 更新首页popover的option list
getDevicesList();
// 展示连接结果
showDeviceStatus();
})
.catch(err => {});
}
}
}
/**
* 弹窗-设备连接检查
*/
function startDeviceConnect() {
// 显示设备检测弹窗
$('#device-testing-root').show();
// 设备检测弹窗-设备连接页
$('#device-testing-prepare').show();
curTestingPageId = 'device-testing-prepare';
initTestingTabTitle();
// 在设备检测弹窗显示设备连接信息
let showDeviceConnectInfo = function() {
if (!(hasCameraConnect && hasVoiceConnect && hasMicConnect && hasNetworkConnect)) {
$('#device-testing-btn').css('color', 'red');
} else {
$('#device-testing-btn').css('color', 'green');
}
// 隐藏设备连接失败提示
$('#connect-attention-container').hide();
// 设备连接中
$('#device-loading').show();
$('#connect-info')
.text('设备正在连接中,请稍等')
.css('color', '#cccccc');
$('#device-camera, #device-voice, #device-mic, #device-network').removeClass(
'connect-success connect-fail'
);
$('#connect-again-btn').hide();
$('#start-test-btn')
.addClass('start-gray')
.show();
// 设备连接结束,展示连接结果
setTimeout(() => {
$('#device-loading').hide();
$('#device-camera')
.removeClass('connect-success connect-fail')
.addClass(`${hasCameraConnect ? 'connect-success' : 'connect-fail'}`);
$('#device-voice')
.removeClass('connect-success connect-fail')
.addClass(`${hasVoiceConnect ? 'connect-success' : 'connect-fail'}`);
$('#device-mic')
.removeClass('connect-success connect-fail')
.addClass(`${hasMicConnect ? 'connect-success' : 'connect-fail'}`);
$('#device-network')
.removeClass('connect-success connect-fail')
.addClass(`${hasNetworkConnect ? 'connect-success' : 'connect-fail'}`);
if (!(hasCameraConnect && hasVoiceConnect && hasMicConnect)) {
let connectInfo = hasNetworkConnect
? '设备连接失败,请允许网页访问摄像头及麦克风'
: '设备及网络连接失败,请允许网页访问摄像头及麦克风并检查网络连接';
$('#connect-info')
.text(connectInfo)
.css('color', 'red');
// 显示设备连接失败引导
$('#connect-attention-container').show();
$('#connect-attention-info').html(deviceFailAttention);
// 切换按钮状态
$('#start-test-btn').hide();
$('#connect-again-btn').show();
}
if (hasCameraConnect && hasVoiceConnect && hasMicConnect && !hasNetworkConnect) {
$('#connect-info')
.text('网络连接失败,请检查网络连接')
.css('color', 'red');
// 显示网络连接失败引导
$('#connect-attention-container').show();
$('#connect-attention-info').html(networkFailAttention);
// 切换按钮状态
$('#start-test-btn').hide();
$('#connect-again-btn').show();
}
if (hasCameraConnect && hasVoiceConnect && hasMicConnect && hasNetworkConnect) {
$('#connect-info')
.text('设备及网络连接成功,请开始设备检测')
.css('color', '#32CD32');
$('#connect-again-btn').hide();
$('#start-test-btn')
.removeClass('start-gray')
.show();
}
}, 2000);
};
showDeviceConnectInfo();
// 如果有设备未连接,唤起请求弹窗
if (!(hasCameraConnect && hasVoiceConnect && hasMicConnect)) {
navigator.mediaDevices
.getUserMedia({ video: hasCameraDevice, audio: hasMicAndVoiceDevice })
.then(async () => {
// 重新获取设备信息
await getDevicesInfo();
// 更新首页popover的option list
getDevicesList();
// 显示设备连接信息
showDeviceConnectInfo();
})
.catch(err => {
console.log('err', err.name);
});
}
}
/**
* 更新首页popover的option list
*/
function getDevicesList() {
// populate camera options
TRTC.getCameras().then(devices => {
$('#camera-option').empty();
devices.forEach(device => {
if (!cameraId) {
// eslint-disable-next-line no-global-assign
cameraId = device.deviceId;
}
let div = $('<div></div>');
div.attr('id', device.deviceId);
div.html(device.label);
div.appendTo('#camera-option');
});
});
// populate microphone options
TRTC.getMicrophones().then(devices => {
$('#mic-option').empty();
devices.forEach(device => {
if (!micId) {
// eslint-disable-next-line no-global-assign
micId = device.deviceId;
}
let div = $('<div></div>');
div.attr('id', device.deviceId);
div.html(device.label);
div.appendTo('#mic-option');
});
});
}
/**
* 摄像头检测页-检测展示摄像头设备选择列表
*/
async function updateCameraDeviceList() {
let cameraDevices = await TRTC.getCameras();
cameraDevices.filter(camera => camera.deviceId !== 'default');
$('#camera-select').empty();
cameraDevices.forEach(camera => {
let option = $('<option></option>');
option.attr('value', camera.deviceId);
option.html(camera.label);
option.appendTo('#camera-select');
});
// 如果有用户设备选择缓存优先使用缓存的deviceId
let cacheCameraDevice = cameraDevices.filter(
camera => camera.deviceId === localStorage.getItem('txy_webRTC_cameraId')
);
if (cacheCameraDevice.length > 0) {
$('#camera-select').val(localStorage.getItem('txy_webRTC_cameraId'));
cameraTestingResult.device = cacheCameraDevice[0];
} else {
$('#camera-select').val(cameraDevices[0].deviceId);
cameraTestingResult.device = cameraDevices[0];
}
}
/**
* 摄像头设备测试
*/
async function startCameraTesting() {
$('#camera-testing-body').show();
curTestingPageId = 'camera-testing-body';
$('#camera-testing')
.removeClass('icon-normal')
.addClass('icon-blue complete');
completedTestingPageIdList.push('camera-testing-body');
completedTestingPageIdList = [...new Set(completedTestingPageIdList)];
await updateCameraDeviceList();
// 创建本地视频流
await createLocalStream(
{
audio: false,
video: true,
cameraId: cameraTestingResult.device.deviceId
},
'camera-video'
);
}
/**
* 初始化/更新扬声器设备数组
*/
async function updateVoiceDeviceList() {
// 获取扬声器设备并展示在界面中
let voiceDevices = await TRTC.getSpeakers();
voiceDevices = voiceDevices.filter(voice => voice.deviceId !== 'default');
$('#voice-select').empty();
voiceDevices.forEach(voice => {
let option = $('<option></option>');
option.attr('value', voice.deviceId);
option.html(voice.label);
option.appendTo('#voice-select');
});
// 如果有用户设备选择缓存优先使用缓存的deviceId
let cacheVoiceDevice = voiceDevices.filter(
mic => mic.deviceId === localStorage.getItem('txy_webRTC_voiceId')
);
if (cacheVoiceDevice.length > 0) {
$('#voice-select').val(localStorage.getItem('txy_webRTC_voiceId'));
voiceTestingResult.device = cacheVoiceDevice[0];
} else {
$('#voice-select').val(voiceDevices[0].deviceId);
voiceTestingResult.device = voiceDevices[0];
}
}
/**
* 播放器设备测试
*/
async function startVoiceTesting() {
$('#voice-testing-body').show();
curTestingPageId = 'voice-testing-body';
$('#voice-testing')
.removeClass('icon-gray')
.addClass('icon-blue complete');
completedTestingPageIdList.push('voice-testing-body');
completedTestingPageIdList = [...new Set(completedTestingPageIdList)];
await updateVoiceDeviceList();
}
/**
* 更新/初始化麦克风设备
*/
async function updateMicDeviceList() {
// 展示麦克风设备选择
let micDevices = await TRTC.getMicrophones();
micDevices = micDevices.filter(mic => mic.deviceId !== 'default');
$('#mic-select').empty();
micDevices.forEach(mic => {
let option = $('<option></option>');
option.attr('value', mic.deviceId);
option.html(mic.label);
option.appendTo('#mic-select');
});
// 如果有用户设备选择缓存优先使用缓存的deviceId
let cacheMicDevice = micDevices.filter(
mic => mic.deviceId === localStorage.getItem('txy_webRTC_micId')
);
if (cacheMicDevice.length > 0) {
$('#mic-select').val(localStorage.getItem('txy_webRTC_micId'));
micTestingResult.device = cacheMicDevice[0];
} else {
$('#mic-select').val(micDevices[0].deviceId);
micTestingResult.device = micDevices[0];
}
}
/**
* 麦克风设备测试
*/
async function startMicTesting() {
$('#mic-testing-body').show();
curTestingPageId = 'mic-testing-body';
$('#mic-testing')
.removeClass('icon-gray')
.addClass('icon-blue complete');
completedTestingPageIdList.push('mic-testing-body');
completedTestingPageIdList = [...new Set(completedTestingPageIdList)];
await updateMicDeviceList();
// 展示麦克风的声音大小显示
if ($('#mic-bar-container').children().length === 0) {
for (let index = 0; index < 28; index++) {
$('<div></div>')
.addClass('mic-bar')
.appendTo('#mic-bar-container');
}
}
// 创建本地音频流
await createLocalStream(
{
audio: true,
microphoneId: micTestingResult.device.deviceId,
video: false
},
'audio-container'
);
// 监听音量,并量化显示出来
setInterval(() => {
let volume = localStream.getAudioLevel();
let num = Math.ceil(28 * volume);
$('#mic-bar-container')
.children('.active')
.removeClass('active');
for (let i = 0; i < num; i++) {
$('#mic-bar-container')
.children()
.slice(0, i)
.addClass('active');
}
}, 100);
}
/**
* 系统信息展示
*/
async function startNetworkTesting() {
$('#network-testing-body').show();
$('#testing-report-btn').hide();
curTestingPageId = 'network-testing-body';
$('#network-testing')
.removeClass('icon-gray')
.addClass('icon-blue complete');
completedTestingPageIdList.push('network-testing-body');
completedTestingPageIdList = [...new Set(completedTestingPageIdList)];
networkQualityNum = 0;
$('#uplink-network')
.addClass('network-loading')
.text('');
// 获取系统信息
$('#system').empty();
let OSInfo = getOS();
$('<div></div>')
.text(OSInfo.osName)
.appendTo('#system');
// 获取浏览器及版本信息
$('#browser').empty();
let browser = getBroswer();
$('<div></div>')
.text(`${browser.broswer} ${browser.version}`)
.appendTo('#browser');
// 获取ip地址信息
// $('#ip').empty();
// let IPAddress = await getIPAddress();
// $('<div></div>').text(IPAddress).appendTo('#ip');
// networkTestingResult.IPAddress = IPAddress;
// 是否支持屏幕分享能力
$('#screen-share').empty();
let isScreenShareSupported = TRTC.isScreenShareSupported();
$('<div></div>')
.text(isScreenShareSupported ? '支持' : '不支持')
.appendTo('#screen-share');
// 上下行网络质量
presetting.login(false, async options => {
client = TRTC.createClient({ mode: 'rtc', ...options });
client.on('network-quality', event => {
networkQualityNum++;
// 收到3次'network-quality'事件的时候认为拿到了网络实际质量
if (networkQualityNum === 3) {
networkTestingResult.upLinkNetwork = event.uplinkNetworkQuality;
networkTestingResult.downLinkNetwork = event.downlinkNetworkQuality;
$('#uplink-network')
.removeClass('network-loading')
.text(NETWORK_QUALITY[String(networkTestingResult.upLinkNetwork)]);
$('#testing-report-btn').show();
client && client.leave();
client && client.off('network-quality');
}
});
await client.join({
roomId: options.roomId
});
await createLocalStream(
{
audio: true,
video: false
},
'audio-container'
);
await client.publish(localStream);
// 音频轨道静音
localStream.muteAudio();
});
}
/**
* 展示检测报告
*/
function showTestingReport() {
$('#device-testing').hide();
$('#network-testing-body').hide();
$('#device-testing-report').show();
curTestingPageId = 'device-testing-report';
// 摄像头检测结果
$('#camera-name').text(cameraTestingResult.device.label);
if (cameraTestingResult.statusResult) {
$('#camera-testing-result')
.text('正常')
.css('color', 'green');
} else {
$('#camera-testing-result')
.text('异常')
.css('color', 'red');
}
// 扬声器检测结果(safari浏览器不显示扬声器检测结果)
if (!isSafari) {
$('#voice-name').text(voiceTestingResult.device.label);
if (voiceTestingResult.statusResult) {
$('#voice-testing-result')
.text('正常')
.css('color', 'green');
} else {
$('#voice-testing-result')
.text('异常')
.css('color', 'red');
}
}
// 麦克风检测结果
$('#mic-name').text(micTestingResult.device.label);
if (micTestingResult.statusResult) {
$('#mic-testing-result')
.text('正常')
.css('color', 'green');
} else {
$('#mic-testing-result')
.text('异常')
.css('color', 'red');
}
// 网络检测结果
// $('#network-name').text(networkTestingResult.IPAddress);
$('#network-name').text('网络质量');
$('#network-testing-result')
.html(`${NETWORK_QUALITY[String(networkTestingResult.upLinkNetwork)]}`)
.css('color', `${Number(networkTestingResult.upLinkNetwork) > 3 ? 'red' : 'green'}`);
}
/**
* 结束设备检测,隐藏设备检测弹窗
*/
function finishDeviceTesting() {
$('#device-testing-root').hide();
$('#device-testing').hide();
$(`#${curTestingPageId}`).hide();
curTestingPageId = '';
completedTestingPageIdList = [];
// 停止摄像头/麦克风的流采集并释放摄像头/麦克风设备
localStream && localStream.close();
client && client.leave();
client && client.off('network-quality');
// 停止播放器的音乐
let audioPlayer = document.querySelector('#audio-player');
if (!audioPlayer.paused) {
audioPlayer.pause();
}
audioPlayer.currentTime = 0;
}
/**
* 恢复检测页面头部图标的状态
*/
function initTestingTabTitle() {
['camera', 'voice', 'mic', 'network'].forEach(item => {
$(`#${item}-testing`)
.removeClass('icon-blue complete')
.addClass('icon-gray');
});
}
/**
* 监听设备变化
*/
navigator.mediaDevices.ondevicechange = async function(event) {
// 当前在摄像头检测页
if (curTestingPageId === 'camera-testing-body') {
await updateCameraDeviceList();
return;
}
// 当前在扬声器检测页
if (curTestingPageId === 'voice-testing-body') {
await updateVoiceDeviceList();
return;
}
// 当前在麦克风检测页
if (curTestingPageId === 'mic-testing-body') {
await updateMicDeviceList();
return;
}
};
/**
* 抽离createStream的公共处理函数
*/
async function createLocalStream(constraints, container) {
localStream = TRTC.createStream(constraints);
try {
await localStream.initialize();
} catch (error) {
switch (error.name) {
case 'NotReadableError':
// 当系统或浏览器异常的时候,可能会出现此错误,您可能需要引导用户重启电脑/浏览器来尝试恢复。
alert('暂时无法访问摄像头/麦克风,请确保当前没有其他应用请求访问摄像头/麦克风,并重试');
return;
case 'NotAllowedError':
// 用户拒绝授权访问摄像头或麦克风 | 屏幕分享,您需要引导客户来授权访问
alert('用户已拒绝授权访问摄像头或麦克风');
return;
case 'NotFoundError':
// 找不到摄像头或麦克风设备
alert('找不到摄像头或麦克风设备');
return;
case 'OverConstrainedError':
alert(
'采集属性设置错误,如果您指定了 cameraId/microphoneId请确保它们是一个有效的非空字符串'
);
return;
default:
alert('未知错误');
return;
}
}
container && localStream.play(container);
}