import 'bulma'; import $ from 'jquery'; import * as Cookies from 'js-cookie'; import { merge } from 'lodash'; import '@/assets/css/icons.css'; import '@/assets/global.scss'; import './meeting2.scss'; import ButtonControl from '@/utils/ButtonControl'; import { isSafari, isMobileSize, isChrome, isFirefox } from '@/utils/BrowserCheck'; import Notify from '@/utils/Notify'; import Renderer from '@/utils/Render'; import { RESOLUTION_ARR, APP_ID } from '@/utils/Settings'; import { logger, log } from '../../utils/Logger'; // eslint-disable-next-line import Polyfill from '@/utils/Polyfill'; // If display a window to show video info const DUAL_STREAM_DEBUG = false; let options = {}; let client = {}; let localStream = {}; let streamList = []; let mainId = 1; let mainStream; const globalLog = logger.init('global', 'blue'); const localLog = logger.init('local', 'green'); const optionsInit = () => { let options = { videoProfile: '480p_4', videoProfileLow: '120p,120p_1', // cameraId: Cookies.get('cameraId'), // microphoneId: Cookies.get('microphoneId'), channel: 'test', transcode: 'h264_interop', attendeeMode: 'audio-only', baseMode: 'avc', displayMode: 2, // 0 Tile, 1 PIP, 2 screen share uid: undefined, // In default it is dynamically generated resolution: undefined }; let tempProfile = RESOLUTION_ARR['480p_4']; options.resolution = tempProfile[0] / tempProfile[1] || 4 / 3; if (options.baseMode === 'avc') { options.key = APP_ID; } return options; }; const uiInit = options => { Renderer.init('ag-canvas', 9 / 16, 8 / 5); // Mobile page should remove title and footer // if (isMobileSize()) { // Renderer.enterFullScreen(); // } // Only firefox and chrome support screen sharing $('#room-name').html(options.channel); switch (options.attendeeMode) { case 'audio-only': ButtonControl.hide(['.videoControlBtn']); break; case 'audience': ButtonControl.hide(['.videoControlBtn', '.audioControlBtn']); break; default: case 'video': break; } }; const clientInit = (client, options) => { return new Promise((resolve, reject) => { client.init(options.key, () => { globalLog('AgoraRTC client initialized'); let lowStreamParam = RESOLUTION_ARR[options.videoProfileLow]; client.join( options.key, options.channel, options.uid, uid => { log(uid, 'brown', `User ${uid} join channel successfully`); log(uid, 'brown', new Date().toLocaleTimeString()); client.setLowStreamParameter({ width: lowStreamParam[0], height: lowStreamParam[1], framerate: lowStreamParam[2], bitrate: lowStreamParam[3] }); // Create localstream resolve(uid); }, err => { reject(err); } ); }); }); }; /** * * @param {*} uid * @param {*} options global option * @param {*} config stream config */ const streamInit = (uid, options, config) => { let defaultConfig = { streamID: uid, audio: true, video: false, screen: false }; // eslint-disable-next-line let stream = AgoraRTC.createStream(merge(defaultConfig, config)); alert(stream); stream.setVideoProfile(options.videoProfile); return stream; }; window.installSuccess = (...args) => { globalLog(...args); }; window.installError = (...args) => { globalLog(...args); Notify.danger( 'Failed to install the extension, please check the network and console.', 3000 ); }; const removeStream = id => { streamList.map((item, index) => { if (item.getId() === id) { streamList[index].close(); $('#video-item-' + id).remove(); streamList.splice(index, 1); return 1; } return 0; }); if (streamList.length <= 4 && options.displayMode !== 2) { ButtonControl.enable('.displayModeBtn'); } Renderer.customRender(streamList, options.displayMode, mainId); }; const addStream = (stream, push = false) => { let id = stream.getId(); // Check for redundant let redundant = streamList.some(item => { return item.getId() === id; }); if (redundant) { return; } // Do push for localStream and unshift for other streams push ? streamList.push(stream) : streamList.unshift(stream); if (streamList.length > 4) { options.displayMode = options.displayMode === 1 ? 0 : options.displayMode; ButtonControl.disable(['.displayModeBtn', '.disableRemoteBtn']); } Renderer.customRender(streamList, options.displayMode, mainId); }; const getStreamById = id => { return streamList.filter(item => { return item.getId() === id; })[0]; }; const enableDualStream = () => { client.enableDualStream( function() { localLog('Enable dual stream success!'); }, function(e) { localLog(e); } ); }; const setHighStream = (prev, next) => { if (prev === next) { return; } let prevStream; let nextStream; // Get stream by id for (let stream of streamList) { let id = stream.getId(); if (id === prev) { prevStream = stream; } else if (id === next) { nextStream = stream; } else { // Do nothing } } // Set prev stream to low prevStream && client.setRemoteVideoStreamType(prevStream, 1); // Set next stream to high nextStream && client.setRemoteVideoStreamType(nextStream, 0); }; /** * Add callback for client event to control streams * @param {*} client * @param {*} streamList */ const subscribeStreamEvents = () => { client.on('stream-added', function(evt) { let stream = evt.stream; let id = stream.getId(); localLog('New stream added: ' + id); localLog(new Date().toLocaleTimeString()); localLog('Subscribe ', stream); alert(id); if (id === 1) { options.displayMode = 2; mainId = id; mainStream = stream; // ButtonControl.disable(['.displayModeBtn', '.disableRemoteBtn']); } if (id !== mainId) { client.setRemoteVideoStreamType(stream, 1); // if (options.displayMode === 2) { // client.setRemoteVideoStreamType(stream, 1); // } else { // mainStream && client.setRemoteVideoStreamType(mainStream, 1); // mainStream = stream; // mainId = id; // } } client.subscribe(stream, function(err) { localLog('Subscribe stream failed', err); }); }); client.on('peer-leave', function(evt) { let id = evt.uid; localLog('Peer has left: ' + id); localLog(new Date().toLocaleTimeString()); removeStream(evt.uid); }); client.on('stream-subscribed', function(evt) { let stream = evt.stream; localLog('Got stream-subscribed event'); localLog(new Date().toLocaleTimeString()); localLog('Subscribe remote stream successfully: ' + stream.getId()); addStream(stream); }); client.on('stream-removed', function(evt) { let stream = evt.stream; let id = stream.getId(); localLog('Stream removed: ' + id); localLog(new Date().toLocaleTimeString()); removeStream(stream.getId()); }); }; const subscribeMouseEvents = () => { $('.exitBtn').on('click', function() { try { client && client.unpublish(localStream); localStream && localStream.close(); client && client.leave( () => { localLog('Client succeed to leave.'); }, () => { localLog('Client failed to leave.'); } ); } finally { // Redirect to index window.location.href = 'index.html'; } }); $('.audioControlBtn').on('click', function() { $('.audioControlBtn').toggleClass('off'); localStream.isAudioOn() ? localStream.disableAudio() : localStream.enableAudio(); }); // $(window).resize(function(_) { // if (isMobileSize()) { // Renderer.enterFullScreen(); // } else { // Renderer.exitFullScreen(); // } // Renderer.customRender(streamList, options.displayMode, mainId); // }); // Dbl click to switch high/low stream $('.ag-container').dblclick(function(e) { let dom = e.target; while (!dom.classList.contains('video-item')) { dom = dom.parentNode; if (dom.classList.contains('ag-main')) { return; } } let id = parseInt(dom.id.split('-')[2], 10); if (id !== mainId) { let next = options.displayMode === 2 ? 1 : id; // Force to swtich setHighStream(mainId, next); mainId = next; mainStream = getStreamById(mainId); } Renderer.customRender(streamList, options.displayMode, mainId); }); $(document).mousemove(function(_) { if (global._toolbarToggle) { clearTimeout(global._toolbarToggle); } $('.ag-btn-group').addClass('active'); global._toolbarToggle = setTimeout(function() { $('.ag-btn-group').removeClass('active'); }, 2500); }); }; const infoDetectSchedule = () => { let no = streamList.length; for (let i = 0; i < no; i++) { let item = streamList[i]; let id = item.getId(); let box = $(`#video-item-${id} .video-item-box`); let width; let height; let frameRate; let HighOrLow; // Whether high or low stream if (id === mainId) { HighOrLow = 'High'; } else { HighOrLow = 'Low'; } if (i === no - 1) { HighOrLow = 'local'; } item.getStats(function(e) { if (i === no - 1) { width = e.videoSendResolutionWidth; height = e.videoSendResolutionHeight; frameRate = e.videoSendFrameRate; } else { width = e.videoReceivedResolutionWidth; height = e.videoReceivedResolutionHeight; frameRate = e.videoReceiveFrameRate; } let str = `

uid: ${id}

${width}*${height} ${frameRate}fps

${HighOrLow}

`; box.html(str); }); } }; // ------------- start -------------- // ---------------------------------- if (!AgoraRTC.checkSystemRequirements()) { alert("browser is no support webRTC"); } options = optionsInit(); uiInit(options); // eslint-disable-next-line client = AgoraRTC.createClient({ mode: options.transcode }); subscribeMouseEvents(); subscribeStreamEvents(); clientInit(client, options).then(uid => { // 获取麦克风 AgoraRTC.getDevices(function(devices) { let microphoneId = ''; devices.forEach(function(item) { if (item.kind === 'audioinput') { microphoneId = item.deviceId; } // if (item.kind === 'videoinput') { // cameraId = item.deviceId; // } }); if(microphoneId == '') { alert('没有检测到麦克风,请您插入麦克风。'); return; } // Use selected device let config = { // cameraId: cameraId, microphoneId: microphoneId }; alert('streamInit Begin'); localStream = streamInit(uid, options, config); // enableDualStream(); localStream.init( () => { addStream(localStream, true); client.publish(localStream, err => { alert('error!'+ err) localLog('Publish local stream error: ' + err); }); }, err => { localLog('getUserMedia failed', err); } ); }); }); if (DUAL_STREAM_DEBUG) { setInterval(infoDetectSchedule, 10000); }