feat: max webcam height to fit on the screen (#1246)

This commit is contained in:
Stefan Dej 2023-02-18 15:04:10 +01:00 committed by GitHub
parent 92438bf8a7
commit 43dc843eca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 106 additions and 65 deletions

View File

@ -6,7 +6,8 @@
:icon="mdiWebcam" :icon="mdiWebcam"
:title="$t('Panels.WebcamPanel.Headline')" :title="$t('Panels.WebcamPanel.Headline')"
:collapsible="$route.fullPath !== '/cam'" :collapsible="$route.fullPath !== '/cam'"
card-class="webcam-panel"> card-class="webcam-panel"
:margin-bottom="currentPage !== 'page'">
<template v-if="webcams.length > 1" #buttons> <template v-if="webcams.length > 1" #buttons>
<v-menu :offset-y="true" title="Webcam"> <v-menu :offset-y="true" title="Webcam">
<template #activator="{ on, attrs }"> <template #activator="{ on, attrs }">

View File

@ -1,4 +1,5 @@
<template> <template>
<div class="d-flex justify-center">
<video <video
ref="video" ref="video"
v-observe-visibility="visibilityChanged" v-observe-visibility="visibilityChanged"
@ -6,6 +7,7 @@
muted muted
:style="webcamStyle" :style="webcamStyle"
class="webcamImage" /> class="webcamImage" />
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -15,6 +17,7 @@ import Hls from 'hls.js'
@Component @Component
export default class Hlsstreamer extends Mixins(BaseMixin) { export default class Hlsstreamer extends Mixins(BaseMixin) {
private aspectRatio: null | number = null
private isVisible = true private isVisible = true
private hls: Hls | null = null private hls: Hls | null = null
@ -35,12 +38,24 @@ export default class Hlsstreamer extends Mixins(BaseMixin) {
} }
get webcamStyle() { get webcamStyle() {
const output = {
transform: 'none',
aspectRatio: 16 / 9,
maxHeight: window.innerHeight - 155 + 'px',
maxWidth: 'auto',
}
let transforms = '' let transforms = ''
if ('flipX' in this.camSettings && this.camSettings.flipX) transforms += ' scaleX(-1)' if ('flipX' in this.camSettings && this.camSettings.flipX) transforms += ' scaleX(-1)'
if ('flipX' in this.camSettings && this.camSettings.flipY) transforms += ' scaleY(-1)' if ('flipX' in this.camSettings && this.camSettings.flipY) transforms += ' scaleY(-1)'
if (transforms.trimStart().length) return { transform: transforms.trimStart() } if (transforms.trimStart().length) return { transform: transforms.trimStart() }
return '' if (this.aspectRatio) {
output.aspectRatio = this.aspectRatio
output.maxWidth = (window.innerHeight - 155) * this.aspectRatio + 'px'
}
return output
} }
visibilityChanged(isVisible: boolean) { visibilityChanged(isVisible: boolean) {
@ -49,6 +64,11 @@ export default class Hlsstreamer extends Mixins(BaseMixin) {
mounted() { mounted() {
this.play() this.play()
const video = this.$refs.video
video.onplaying = () => {
this.aspectRatio = video.videoWidth / video.videoHeight
}
} }
updated() { updated() {

View File

@ -1,22 +1,5 @@
<style scoped>
.webcamImage {
width: 100%;
background: lightgray;
}
.webcamFpsOutput {
display: inline-block;
position: absolute;
bottom: 6px;
right: 0;
background: rgba(0, 0, 0, 0.8);
padding: 3px 10px;
border-top-left-radius: 5px;
}
</style>
<template> <template>
<div style="position: relative"> <div style="position: relative" class="d-flex justify-center">
<img <img
ref="image" ref="image"
v-observe-visibility="viewportVisibilityChanged" v-observe-visibility="viewportVisibilityChanged"
@ -40,8 +23,10 @@ export default class Mjpegstreamer extends Mixins(BaseMixin) {
private currentFPS = 0 private currentFPS = 0
private streamState = false private streamState = false
private aspectRatio: null | number = null private aspectRatio: null | number = null
private timerFPS: number | null = null // eslint-disable-next-line no-undef
private timerRestart: number | null = null private timerFPS: NodeJS.Timeout | null = null
// eslint-disable-next-line no-undef
private timerRestart: NodeJS.Timeout | null = null
private stream: ReadableStream | null = null private stream: ReadableStream | null = null
private controller: AbortController | null = null private controller: AbortController | null = null
private isVisibleViewport = false private isVisibleViewport = false
@ -72,6 +57,8 @@ export default class Mjpegstreamer extends Mixins(BaseMixin) {
const output = { const output = {
transform: 'none', transform: 'none',
aspectRatio: 16 / 9, aspectRatio: 16 / 9,
maxHeight: window.innerHeight - 155 + 'px',
maxWidth: 'auto',
} }
let transforms = '' let transforms = ''
@ -79,7 +66,10 @@ export default class Mjpegstreamer extends Mixins(BaseMixin) {
if ('flipX' in this.camSettings && this.camSettings.flipY) transforms += ' scaleY(-1)' if ('flipX' in this.camSettings && this.camSettings.flipY) transforms += ' scaleY(-1)'
if (transforms.trimStart().length) output.transform = transforms.trimStart() if (transforms.trimStart().length) output.transform = transforms.trimStart()
if (this.aspectRatio) output.aspectRatio = this.aspectRatio if (this.aspectRatio) {
output.aspectRatio = this.aspectRatio
output.maxWidth = (window.innerHeight - 155) * this.aspectRatio + 'px'
}
return output return output
} }
@ -252,3 +242,20 @@ export default class Mjpegstreamer extends Mixins(BaseMixin) {
} }
} }
</script> </script>
<style scoped>
.webcamImage {
width: 100%;
background: lightgray;
}
.webcamFpsOutput {
display: inline-block;
position: absolute;
bottom: 6px;
right: 0;
background: rgba(0, 0, 0, 0.8);
padding: 3px 10px;
border-top-left-radius: 5px;
}
</style>

View File

@ -1,21 +1,5 @@
<style scoped>
.webcamImage {
width: 100%;
}
.webcamFpsOutput {
display: inline-block;
position: absolute;
bottom: 6px;
right: 0;
background: rgba(0, 0, 0, 0.8);
padding: 3px 10px;
border-top-left-radius: 5px;
}
</style>
<template> <template>
<div style="position: relative"> <div style="position: relative" class="d-flex justify-center">
<div v-if="!isLoaded" class="text-center py-5"> <div v-if="!isLoaded" class="text-center py-5">
<v-progress-circular indeterminate color="primary"></v-progress-circular> <v-progress-circular indeterminate color="primary"></v-progress-circular>
</div> </div>
@ -44,7 +28,8 @@ export default class MjpegstreamerAdaptive extends Mixins(BaseMixin) {
private isVisibleDocument = true private isVisibleDocument = true
private isVisibleViewport = false private isVisibleViewport = false
private isLoaded = true private isLoaded = true
private timer: number | undefined = undefined // eslint-disable-next-line no-undef
private timer: NodeJS.Timeout | undefined = undefined
private request_start_time = performance.now() private request_start_time = performance.now()
private start_time = performance.now() private start_time = performance.now()
@ -67,6 +52,8 @@ export default class MjpegstreamerAdaptive extends Mixins(BaseMixin) {
const output = { const output = {
transform: 'none', transform: 'none',
aspectRatio: 16 / 9, aspectRatio: 16 / 9,
maxHeight: window.innerHeight - 155 + 'px',
maxWidth: 'auto',
} }
let transforms = '' let transforms = ''
@ -75,7 +62,10 @@ export default class MjpegstreamerAdaptive extends Mixins(BaseMixin) {
if ((this.camSettings.rotate ?? 0) === 180) transforms += ' rotate(180deg)' if ((this.camSettings.rotate ?? 0) === 180) transforms += ' rotate(180deg)'
if (transforms.trimStart().length) output.transform = transforms.trimStart() if (transforms.trimStart().length) output.transform = transforms.trimStart()
if (this.aspectRatio) output.aspectRatio = this.aspectRatio if (this.aspectRatio) {
output.aspectRatio = this.aspectRatio
output.maxWidth = (window.innerHeight - 155) * this.aspectRatio + 'px'
}
return output return output
} }
@ -114,10 +104,10 @@ export default class MjpegstreamerAdaptive extends Mixins(BaseMixin) {
canvas.width = canvas.clientWidth canvas.width = canvas.clientWidth
if (this.rotate) { if (this.rotate) {
if (this.aspectRatio === null) this.aspectRatio = frame.height / frame.width if (this.aspectRatio === null) this.aspectRatio = frame.height / frame.width
canvas.height = canvas.clientWidth / (frame.height / frame.width) canvas.height = canvas.clientWidth / this.aspectRatio
} else { } else {
if (this.aspectRatio === null) this.aspectRatio = frame.width / frame.height if (this.aspectRatio === null) this.aspectRatio = frame.width / frame.height
canvas.height = canvas.clientWidth * (frame.width / frame.height) canvas.height = canvas.clientWidth * this.aspectRatio
} }
if (this.rotate) { if (this.rotate) {
@ -223,3 +213,19 @@ export default class MjpegstreamerAdaptive extends Mixins(BaseMixin) {
} }
} }
</script> </script>
<style scoped>
.webcamImage {
width: 100%;
}
.webcamFpsOutput {
display: inline-block;
position: absolute;
bottom: 6px;
right: 0;
background: rgba(0, 0, 0, 0.8);
padding: 3px 10px;
border-top-left-radius: 5px;
}
</style>

View File

@ -1,17 +1,12 @@
<style scoped>
.webcamImage {
width: 100%;
background: lightgray;
}
</style>
<template> <template>
<div class="d-flex justify-center">
<img <img
ref="webcamUv4lMjpegImage" ref="webcamUv4lMjpegImage"
v-observe-visibility="viewportVisibilityChanged" v-observe-visibility="viewportVisibilityChanged"
:style="webcamStyle" :style="webcamStyle"
class="webcamImage" class="webcamImage"
@load="onload" /> @load="onload" />
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -45,6 +40,8 @@ export default class Uv4lMjpeg extends Mixins(BaseMixin) {
const output = { const output = {
transform: 'none', transform: 'none',
aspectRatio: 16 / 9, aspectRatio: 16 / 9,
maxHeight: window.innerHeight - 155 + 'px',
maxWidth: 'auto',
} }
let transforms = '' let transforms = ''
@ -52,7 +49,10 @@ export default class Uv4lMjpeg extends Mixins(BaseMixin) {
if ('flipX' in this.camSettings && this.camSettings.flipY) transforms += ' scaleY(-1)' if ('flipX' in this.camSettings && this.camSettings.flipY) transforms += ' scaleY(-1)'
if (transforms.trimStart().length) output.transform = transforms.trimStart() if (transforms.trimStart().length) output.transform = transforms.trimStart()
if (this.aspectRatio) output.aspectRatio = this.aspectRatio if (this.aspectRatio) {
output.aspectRatio = this.aspectRatio
output.maxWidth = (window.innerHeight - 155) * this.aspectRatio + 'px'
}
return output return output
} }
@ -116,3 +116,10 @@ export default class Uv4lMjpeg extends Mixins(BaseMixin) {
} }
} }
</script> </script>
<style scoped>
.webcamImage {
width: 100%;
background: lightgray;
}
</style>