From 0178935b2a19efd39b090540738ed968e3998cd0 Mon Sep 17 00:00:00 2001 From: Miroslav Pejic Date: Mon, 29 Jul 2024 09:50:07 +0200 Subject: [PATCH] [mirotalksfu] - improve RTMP Streamer UI --- app/src/Server.js | 2 +- package.json | 2 +- public/css/RtmpStreamer.css | 72 +++++++++++++++++++++++++----- public/js/Room.js | 6 +-- public/js/RoomClient.js | 9 +++- public/js/RtmpStreamer.js | 80 ++++++++++++++++++++++++++++++++++ public/views/Room.html | 3 ++ public/views/RtmpStreamer.html | 20 ++++++--- 8 files changed, 171 insertions(+), 23 deletions(-) diff --git a/app/src/Server.js b/app/src/Server.js index 391cf9d2..e59dccc5 100644 --- a/app/src/Server.js +++ b/app/src/Server.js @@ -44,7 +44,7 @@ dependencies: { * @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.5.28 + * @version 1.5.29 * */ diff --git a/package.json b/package.json index c8af28d7..db775388 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mirotalksfu", - "version": "1.5.28", + "version": "1.5.29", "description": "WebRTC SFU browser-based video calls", "main": "Server.js", "scripts": { diff --git a/public/css/RtmpStreamer.css b/public/css/RtmpStreamer.css index 86540282..bd1988b8 100644 --- a/public/css/RtmpStreamer.css +++ b/public/css/RtmpStreamer.css @@ -19,8 +19,9 @@ body { padding: 20px; background: var(--body-bg); color: #fff; - border-radius: 8px; - box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + border-radius: 10px; + border: var(--border); + box-shadow: var(--box-shadow); } h1 { @@ -29,10 +30,10 @@ h1 { } video { - border: 0.1px solid #ccc; margin: 10px 0; - border-radius: 8px; - box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); + border-radius: 10px; + border: var(--border); + box-shadow: var(--box-shadow); } .input-group-inline { @@ -60,7 +61,7 @@ video { input, button { - padding: 10px; + padding: 15px; font-size: 16px; border: none; border-radius: 4px; @@ -71,28 +72,32 @@ button { input[type='text'], input[type='password'] { flex: 1; - background: #2c2c2c; color: #fff; + border: var(--border); + background: var(--body-bg); } input[type='text'][readonly] { - background: #2c2c2c; color: #fff; + border: var(--border); + background: var(--body-bg); } button { cursor: pointer; - background-color: #007bff; color: #fff; + border: var(--border); + background: var(--btns-bg-color); transition: background-color 0.3s ease; } button:disabled { - background: #2c2c2c; + color: grey; + background: var(--body-bg); cursor: not-allowed; } button:hover { - background-color: #0056b3; + background-color: var(--select-bg); } .button-group { display: flex; @@ -114,7 +119,7 @@ button:hover { color: white; padding: 15px; border-radius: 5px; - box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + box-shadow: var(--box-shadow); z-index: 1000; display: flex; align-items: center; @@ -204,3 +209,46 @@ footer { padding: 8px; } } + +/*-------------------------------------------------------------- +# Keyframes +--------------------------------------------------------------*/ + +@-webkit-keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@-moz-keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +.fadein { + -webkit-animation: fadeIn ease-in 1; + -moz-animation: fadeIn ease-in 1; + animation: fadeIn ease-in 1; + -webkit-animation-fill-mode: forwards; + -moz-animation-fill-mode: forwards; + animation-fill-mode: forwards; + -webkit-animation-duration: 1s; + -moz-animation-duration: 1s; + animation-duration: 1s; +} diff --git a/public/js/Room.js b/public/js/Room.js index b29ebe6d..f0060938 100644 --- a/public/js/Room.js +++ b/public/js/Room.js @@ -11,7 +11,7 @@ if (location.href.substr(0, 5) !== 'https') location.href = 'https' + location.h * @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.5.28 + * @version 1.5.29 * */ @@ -1794,7 +1794,7 @@ function handleButtons() { rc.stopRTMP(); }; streamerRtmpButton.onclick = () => { - openURL(`/rtmp?v=${videoSelect.value}&a=${microphoneSelect.value}`, true); + rc.openRTMPStreamer(); }; startRtmpURLButton.onclick = () => { rc.startRTMPfromURL(rtmpStreamURL.value); @@ -4318,7 +4318,7 @@ function showAbout() { imageUrl: image.about, customClass: { image: 'img-about' }, position: 'center', - title: 'WebRTC SFU v1.5.28', + title: 'WebRTC SFU v1.5.29', html: `
diff --git a/public/js/RoomClient.js b/public/js/RoomClient.js index d1cf5b7e..7cba8077 100644 --- a/public/js/RoomClient.js +++ b/public/js/RoomClient.js @@ -9,7 +9,7 @@ * @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.5.28 + * @version 1.5.29 * */ @@ -8056,6 +8056,13 @@ class RoomClient { // RTMP common // ############################################## + openRTMPStreamer() { + const color = encodeURIComponent(themeCustom.color); + const options = `&t=${selectTheme.value}` + (themeCustom.keep ? `&c=${color}` : ''); + const url = `/rtmp?v=${videoSelect.value}&a=${microphoneSelect.value}${options}`; + openURL(url, true); + } + isRTMPVideoSupported(video) { if (video.endsWith('.mp4') || video.endsWith('.webm')) return true; return false; diff --git a/public/js/RtmpStreamer.js b/public/js/RtmpStreamer.js index 048683ab..a0e9d8a2 100644 --- a/public/js/RtmpStreamer.js +++ b/public/js/RtmpStreamer.js @@ -14,6 +14,8 @@ const closePopup = document.getElementById('closePopup'); const qs = new URLSearchParams(window.location.search); const videoId = filterXSS(qs.get('v')); const audioId = filterXSS(qs.get('a')); +const theme = filterXSS(qs.get('t')); +const color = filterXSS(qs.get('c')); console.log('Video/Audio id', { video: videoId, @@ -252,12 +254,90 @@ function copyRTMP() { showPopup('Copied: ' + rtmpInput.value, 'success'); } +function setCustomTheme() { + document.documentElement.style.setProperty('--body-bg', `radial-gradient(${color}, ${color})`); + document.documentElement.style.setProperty('--select-bg', `${color}`); + document.documentElement.style.setProperty('--btns-bg-color', 'rgba(0, 0, 0, 0.7)'); + document.body.style.background = `radial-gradient(${color}, ${color})`; +} + +function setTheme() { + switch (theme) { + case 'elegant': + document.documentElement.style.setProperty('--body-bg', 'linear-gradient(135deg, #000000, #434343)'); + document.documentElement.style.setProperty('--select-bg', '#333333'); + document.documentElement.style.setProperty('--btns-bg-color', 'rgba(0, 0, 0, 0.7)'); + document.body.style.background = 'linear-gradient(135deg, #000000, #434343)'; + break; + case 'dark': + document.documentElement.style.setProperty('--body-bg', 'linear-gradient(135deg, #000000, #1a1a1a)'); + document.documentElement.style.setProperty('--select-bg', '#1a1a1a'); + document.documentElement.style.setProperty('--btns-bg-color', 'rgba(0, 0, 0, 0.85)'); + document.body.style.background = 'linear-gradient(135deg, #000000, #1a1a1a)'; + break; + case 'grey': + document.documentElement.style.setProperty('--body-bg', 'linear-gradient(135deg, #1a1a1a, #4f4f4f)'); + document.documentElement.style.setProperty('--select-bg', '#2a2a2a'); + document.documentElement.style.setProperty('--btns-bg-color', 'rgba(0, 0, 0, 0.7)'); + document.body.style.background = 'linear-gradient(135deg, #1a1a1a, #4f4f4f)'; + break; + case 'green': + document.documentElement.style.setProperty('--body-bg', 'linear-gradient(135deg, #002a22, #004d40)'); + document.documentElement.style.setProperty('--select-bg', '#002a22'); + document.documentElement.style.setProperty('--settings-bg', 'linear-gradient(135deg, #002a22, #004d40)'); + document.documentElement.style.setProperty('--btns-bg-color', 'rgba(0, 42, 34, 0.7)'); + document.body.style.background = 'linear-gradient(135deg, #002a22, #004d40)'; + break; + case 'blue': + document.documentElement.style.setProperty('--body-bg', 'linear-gradient(135deg, #00274d, #004d80)'); + document.documentElement.style.setProperty('--select-bg', '#00274d'); + document.documentElement.style.setProperty('--btns-bg-color', 'rgba(0, 39, 77, 0.7)'); + document.body.style.background = 'linear-gradient(135deg, #00274d, #004d80)'; + break; + case 'red': + document.documentElement.style.setProperty('--body-bg', 'linear-gradient(135deg, #2a0d0d, #4d1a1a)'); + document.documentElement.style.setProperty('--select-bg', '#2a0d0d'); + document.documentElement.style.setProperty('--btns-bg-color', 'rgba(42, 13, 13, 0.7)'); + document.body.style.background = 'linear-gradient(135deg, #2a0d0d, #4d1a1a)'; + break; + case 'purple': + document.documentElement.style.setProperty('--body-bg', 'linear-gradient(135deg, #2a001d, #4d004a)'); + document.documentElement.style.setProperty('--select-bg', '#2a001d'); + document.documentElement.style.setProperty('--btns-bg-color', 'rgba(42, 0, 29, 0.7)'); + document.body.style.background = 'linear-gradient(135deg, #2a001d, #4d004a)'; + break; + case 'orange': + document.documentElement.style.setProperty('--body-bg', 'linear-gradient(135deg, #3d1a00, #ff8c00)'); + document.documentElement.style.setProperty('--select-bg', '#3d1a00'); + document.documentElement.style.setProperty('--wb-bg', 'linear-gradient(135deg, #3d1a00, #ff8c00)'); + document.documentElement.style.setProperty('--btns-bg-color', 'rgba(61, 26, 0, 0.7)'); + document.body.style.background = 'linear-gradient(135deg, #3d1a00, #ff8c00)'; + break; + case 'pink': + document.documentElement.style.setProperty('--body-bg', 'linear-gradient(135deg, #4d001d, #ff66b2)'); + document.documentElement.style.setProperty('--select-bg', '#4d001d'); + document.documentElement.style.setProperty('--tab-btn-active', '#ff66b2'); + document.body.style.background = 'linear-gradient(135deg, #4d001d, #ff66b2)'; + break; + case 'yellow': + document.documentElement.style.setProperty('--body-bg', 'linear-gradient(135deg, #4d3b00, #ffc107)'); + document.documentElement.style.setProperty('--select-bg', '#4d3b00'); + document.documentElement.style.setProperty('--btns-bg-color', 'rgba(77, 59, 0, 0.7)'); + document.body.style.background = 'linear-gradient(135deg, #4d3b00, #ffc107)'; + break; + default: + break; + } +} + startCameraButton.addEventListener('click', startCameraStreaming); startScreenButton.addEventListener('click', startScreenStreaming); stopButton.addEventListener('click', stopRTMP); copyButton.addEventListener('click', copyRTMP); closePopup.addEventListener('click', hidePopup); +window.addEventListener('load', color ? setCustomTheme : setTheme); + // Stop RTMP streaming when the browser tab is closed window.addEventListener('beforeunload', async (event) => { if (mediaRecorder) { diff --git a/public/views/Room.html b/public/views/Room.html index 736f9d07..aa7cb692 100644 --- a/public/views/Room.html +++ b/public/views/Room.html @@ -1017,6 +1017,9 @@ access to use this app.
+

+ Select your desired video and audio sources from settings, then begin RTMP streaming +

diff --git a/public/views/RtmpStreamer.html b/public/views/RtmpStreamer.html index 7d31d78c..15375e69 100644 --- a/public/views/RtmpStreamer.html +++ b/public/views/RtmpStreamer.html @@ -45,6 +45,10 @@ + + + + @@ -60,7 +64,7 @@
-
+

MiroTalk RTMP Streamer

- +
- - - + + +