[mirotalksfu] - add YouTube share video

main
Miroslav Pejic 5 years ago
parent d9082c8ac0
commit 447040110a

@ -20,6 +20,7 @@ Powered by `WebRTC` with [SFU](https://mediasoup.org) integrated server.
- Collaborative whiteboard for the teachers
- Select Microphone - Speaker and Video source
- Recording your Screen, Audio or Video
- Share any YouTube video in real time to your participants
- Full Screen Mode on mouse click on the Video element
- Supports [REST API](api/README.md) (Application Programming Interface)

@ -139,6 +139,14 @@ access to use this app.
<button id="startScreenButton" class="hidden"><i class="fas fa-desktop"></i> Start screen</button>
<button id="stopScreenButton" class="hidden"><i class="fas fa-stop-circle"></i> Stop screen</button>
<button id="fileShareButton" class="hidden"><i class="fas fa-folder-open"></i> File Sharing</button>
<div class="dropdown">
<button id="youTubeShareButton" class="hidden"><i class="fab fa-youtube"></i> YouTube</button>
<div id="youTubeSettings" class="dropdown-content fadein">
<div id="youTubeOptions">
<button id="youTubeCloseBtn"><i class="fas fa-times"></i> Close Video</button>
</div>
</div>
</div>
<div class="dropdown">
<button id="whiteboardButton" class="hidden">
<i class="fas fa-chalkboard-teacher"></i> Whiteboard

@ -611,6 +611,20 @@ progress {
min-width: 100%;
}
/*--------------------------------------------------------------
# YouTube Video
--------------------------------------------------------------*/
#youTubeSettings {
display: 'none';
position: relative;
background: var(--body-bg);
}
#youTubeCloseBtn:hover {
color: red;
}
/*--------------------------------------------------------------
# Whiteboard
--------------------------------------------------------------*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

@ -434,6 +434,7 @@ function roomIsReady() {
show(raiseHandButton);
if (isAudioAllowed) show(startAudioButton);
if (isVideoAllowed) show(startVideoButton);
show(youTubeShareButton);
show(fileShareButton);
show(whiteboardButton);
show(participantsButton);
@ -612,6 +613,12 @@ function handleButtons() {
fileShareButton.onclick = () => {
rc.selectFileToShare();
};
youTubeShareButton.onclick = () => {
rc.youTubeShareVideo();
};
youTubeCloseBtn.onclick = () => {
rc.closeYouTube(true);
};
sendAbortBtn.onclick = () => {
rc.abortFileTransfer();
};

@ -18,6 +18,7 @@ const image = {
locked: '../images/locked.png',
mute: '../images/mute.png',
hide: '../images/hide.png',
youtube: '../images/youtube.png',
};
const mediaType = {
@ -458,6 +459,13 @@ class RoomClient {
}.bind(this),
);
this.socket.on(
'youTubeAction',
function (data) {
this.youTubeAction(data);
}.bind(this),
);
this.socket.on(
'fileAbort',
function (data) {
@ -1857,6 +1865,117 @@ class RoomClient {
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
}
// ####################################################
// YOUTUBE SHARE VIDEO
// ####################################################
youTubeShareVideo() {
rc.sound('open');
Swal.fire({
background: swalBackground,
position: 'center',
imageUrl: image.youtube,
title: 'Share YouTube Video',
text: 'Past YouTube video URL',
input: 'text',
showCancelButton: true,
confirmButtonText: `Share`,
showClass: {
popup: 'animate__animated animate__fadeInDown',
},
hideClass: {
popup: 'animate__animated animate__fadeOutUp',
},
}).then((result) => {
if (result.value) {
if (!this.thereIsParticipants()) {
userLog('info', 'No participants detected', 'top-end');
return;
}
// https://www.youtube.com/watch?v=RT6_Id5-7-s
let you_tube_url = this.getYoutubeEmbed(result.value);
if (you_tube_url) {
let data = {
peer_name: this.peer_name,
you_tube_url: you_tube_url,
action: 'open',
};
console.log('YouTube video URL: ', you_tube_url);
this.socket.emit('youTubeAction', data);
this.openYouTube(data);
} else {
this.userLog('error', 'Not valid YouTube URL', 'top-end');
}
}
});
}
getYoutubeEmbed(url) {
let regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/;
let match = url.match(regExp);
return match && match[7].length == 11 ? 'https://www.youtube.com/embed/' + match[7] + '?autoplay=1' : false;
}
youTubeAction(data) {
let action = data.action;
switch (action) {
case 'open':
this.userLog('info', `${peer_name} <i class="fab fa-youtube"></i> opened the YouTube video`, 'top-end');
this.openYouTube(data);
break;
case 'close':
this.userLog('info', `${peer_name} <i class="fab fa-youtube"></i> closed the YouTube video`, 'top-end');
this.closeYouTube();
break;
}
}
openYouTube(data) {
let d, iframe;
let peer_name = data.peer_name;
let you_tube_url = data.you_tube_url;
this.closeYouTube();
youTubeSettings.style.display = 'block';
d = document.createElement('div');
d.className = 'Camera';
d.id = '__youTube';
iframe = document.createElement('iframe');
iframe.setAttribute('id', '__youTubeIframe');
iframe.setAttribute('title', peer_name);
iframe.setAttribute('width', '100%');
iframe.setAttribute('height', '100%');
iframe.setAttribute('src', you_tube_url);
iframe.setAttribute(
'allow',
'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture',
);
iframe.setAttribute('frameborder', '0');
iframe.setAttribute('allowfullscreen', true);
d.appendChild(iframe);
this.videoMediaContainer.appendChild(d);
resizeVideoMedia();
rc.sound('joined');
}
closeYouTube(emit = false) {
if (emit) {
let data = {
peer_name: this.peer_name,
action: 'close',
};
this.socket.emit('youTubeAction', data);
}
let youTubeDiv = this.getId('__youTube');
if (youTubeDiv) {
youTubeSettings.style.display = 'none';
youTubeDiv.parentNode.removeChild(youTubeDiv);
resizeVideoMedia();
rc.sound('left');
}
}
// ####################################################
// ROOM ACTION
// ####################################################

@ -117,8 +117,8 @@
</h2>
<p class="section-paragraph mb-0">
MiroTalk with SFU integrated Server. We engineered a platform with maximum video
quality lowest latency that makes your calls crystal clear. Desktop and Mobile
compatible!
quality lowest latency that makes your calls crystal clear. Compatible with Desktop
and Mobile devices!
</p>
</div>
</div>

@ -140,7 +140,7 @@ async function ngrokStart() {
tunnel: tunnel,
});
} catch (err) {
console.error('Ngrok Start error: ', err);
log.error('Ngrok Start error: ', err);
process.exit(1);
}
}
@ -192,7 +192,7 @@ async function createWorkers() {
rtcMaxPort: config.mediasoup.worker.rtcMaxPort,
});
worker.on('died', () => {
console.error('Mediasoup worker died, exiting in 2 seconds... [pid:%d]', worker.pid);
log.error('Mediasoup worker died, exiting in 2 seconds... [pid:%d]', worker.pid);
setTimeout(() => process.exit(1), 2000);
});
workers.push(worker);
@ -265,6 +265,11 @@ io.on('connection', (socket) => {
roomList.get(socket.room_id).broadCast(socket.id, 'fileAbort', data);
});
socket.on('youTubeAction', (data) => {
log.debug('YouTube: ', data);
roomList.get(socket.room_id).broadCast(socket.id, 'youTubeAction', data);
});
socket.on('wbCanvasToJson', (data) => {
// let objLength = bytesToSize(Object.keys(data).length);
// log.debug('Send Whiteboard canvas JSON', { length: objLength });
@ -328,7 +333,7 @@ io.on('connection', (socket) => {
const { params } = await roomList.get(socket.room_id).createWebRtcTransport(socket.id);
callback(params);
} catch (err) {
console.error('Create WebRtc Transport error: ', err);
log.error('Create WebRtc Transport error: ', err);
callback({
error: err.message,
});

Loading…
Cancel
Save