From bfc40f337351cc2b12e394aa94586f944a4dab90 Mon Sep 17 00:00:00 2001 From: Rafael Araujo Lehmkuhl Date: Sun, 7 Sep 2025 11:54:19 +0100 Subject: [PATCH 1/2] widgets: video-player: Add reload button to configuration dialog Clicking this button basically disconnects the stream from the widget, wait a second and then reconnects. It works well. --- src/components/widgets/VideoPlayer.vue | 103 +++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/src/components/widgets/VideoPlayer.vue b/src/components/widgets/VideoPlayer.vue index 61bb3dd997..669927be1c 100644 --- a/src/components/widgets/VideoPlayer.vue +++ b/src/components/widgets/VideoPlayer.vue @@ -100,6 +100,20 @@ Rotate Left Rotate Right +
+ + Reload Stream + +
+
+ +

Reloading... {{ Math.round(reloadProgress) }}%

+
@@ -134,6 +148,10 @@ const nameSelectedStream = ref() const videoElement = ref() const mediaStream = ref() const streamConnected = ref(false) +const isReloading = ref(false) +const reloadProgress = ref(0) +const previousStream = ref() +const hasBeenMountedFor5Seconds = ref(false) onBeforeMount(() => { // Set the default initial values that are not present in the widget options @@ -147,6 +165,11 @@ onBeforeMount(() => { } widget.value.options = Object.assign({}, defaultOptions, widget.value.options) nameSelectedStream.value = widget.value.options.internalStreamName + + // Set the 5-second delay before showing reload buttons + setTimeout(() => { + hasBeenMountedFor5Seconds.value = true + }, 5000) }) const externalStreamId = computed(() => { @@ -229,6 +252,34 @@ const rotateVideo = (angle: number): void => { widget.value.options.rotationAngle += angle } +const reloadVideo = (): void => { + if (isReloading.value || !nameSelectedStream.value) return + + // Store the current stream to re-select later + previousStream.value = nameSelectedStream.value + isReloading.value = true + reloadProgress.value = 0 + + // Clear the current stream + nameSelectedStream.value = undefined + + // Progress bar animation + const progressInterval = setInterval(() => { + reloadProgress.value += 100 / 30 // Update 30 times over 3 seconds + if (reloadProgress.value >= 100) { + clearInterval(progressInterval) + } + }, 100) + + // Re-select the stream after 3 seconds + setTimeout(() => { + nameSelectedStream.value = previousStream.value + isReloading.value = false + reloadProgress.value = 0 + clearInterval(progressInterval) + }, 3000) +} + const flipStyle = computed(() => { return `scale(${widget.value.options.flipHorizontally ? -1 : 1}, ${widget.value.options.flipVertically ? -1 : 1})` }) @@ -289,4 +340,56 @@ video { color: white; border: 2px solid rgb(0, 20, 80); } + +.reload-section { + margin-top: 2rem; + display: flex; + flex-direction: column; + align-items: center; + gap: 0.5rem; +} + +.reload-button { + border-color: rgba(255, 255, 255, 0.6) !important; + color: white !important; + transition: all 0.3s ease; +} + +.reload-button:hover { + border-color: white !important; + background-color: rgba(255, 255, 255, 0.1) !important; + transform: rotate(90deg); +} + +.reload-progress-section { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 2rem; +} + +.reload-icon { + animation: spin 2s linear infinite; +} + +.reload-progress-bar { + width: 200px; + max-width: 80%; +} + +@keyframes spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +.reload-progress-config { + display: flex; + flex-direction: column; + align-items: center; +} From 1e788b783cf1ec7c813ba3e866f309ef537f85b7 Mon Sep 17 00:00:00 2001 From: Rafael Araujo Lehmkuhl Date: Tue, 9 Dec 2025 16:03:26 -0300 Subject: [PATCH 2/2] video: Add debug console to the video player widget --- src/components/WebRTCDebugConsole.vue | 212 +++++++++++++++++++++++++ src/components/widgets/VideoPlayer.vue | 150 ++++++++++------- src/composables/webRTC.ts | 20 +++ src/composables/webRTCDebugConsole.ts | 78 +++++++++ 4 files changed, 401 insertions(+), 59 deletions(-) create mode 100644 src/components/WebRTCDebugConsole.vue create mode 100644 src/composables/webRTCDebugConsole.ts diff --git a/src/components/WebRTCDebugConsole.vue b/src/components/WebRTCDebugConsole.vue new file mode 100644 index 0000000000..a0a5f1523a --- /dev/null +++ b/src/components/WebRTCDebugConsole.vue @@ -0,0 +1,212 @@ + + + + + diff --git a/src/components/widgets/VideoPlayer.vue b/src/components/widgets/VideoPlayer.vue index 669927be1c..0b8c1bfcde 100644 --- a/src/components/widgets/VideoPlayer.vue +++ b/src/components/widgets/VideoPlayer.vue @@ -46,74 +46,98 @@ Your browser does not support the video tag. - - + + Video widget config - - - - Saved stream name: "{{ widget.options.internalStreamName }}" - - - -
- Rotate Left - Rotate Right + + +
+ +
+ + +
+ +
+ + + +
+ + +
+ Fit style + + + + + +
-
+ + +
+ + - Reload Stream + Reload stream
-
- -

Reloading... {{ Math.round(reloadProgress) }}%

-
+ + + + + + + Debug console + + +
Select a stream to view debug logs.
+
+
+
@@ -124,6 +148,7 @@ import { storeToRefs } from 'pinia' import { computed, onBeforeMount, onBeforeUnmount, ref, toRefs, watch } from 'vue' import StatsForNerds from '@/components/VideoPlayerStatsForNerds.vue' +import WebRTCDebugConsole from '@/components/WebRTCDebugConsole.vue' import { useAppInterfaceStore } from '@/stores/appInterface' import { useVideoStore } from '@/stores/video' import { useWidgetManagerStore } from '@/stores/widgetManager' @@ -152,6 +177,7 @@ const isReloading = ref(false) const reloadProgress = ref(0) const previousStream = ref() const hasBeenMountedFor5Seconds = ref(false) +const debugPanelExpanded = ref() onBeforeMount(() => { // Set the default initial values that are not present in the widget options @@ -307,6 +333,12 @@ const streamStatus = computed(() => { } return videoStore.getStreamData(externalStreamId.value)?.webRtcManager.streamStatus ?? 'Unknown.' }) + +const debugStreamId = computed(() => { + if (!externalStreamId.value) return undefined + const streamData = videoStore.getStreamData(externalStreamId.value) + return streamData?.webRtcManager.getDebugStreamId() +})