mirror of
https://github.com/ad1217/PrinterStatus
synced 2024-11-13 03:53:29 -05:00
Handle camera transforms in ffmpeg, rather than client side
This simplifies the client, as well as fixing rotation
This commit is contained in:
parent
cc0f6d90d0
commit
afe6a1aed5
@ -40,18 +40,13 @@ export default class OctoprintConnection {
|
|||||||
const webcamURL = new URL(settings.webcam.streamUrl, this.address);
|
const webcamURL = new URL(settings.webcam.streamUrl, this.address);
|
||||||
// TODO: handle recreating proxy on URL change
|
// TODO: handle recreating proxy on URL change
|
||||||
if (this.webcamStream === undefined) {
|
if (this.webcamStream === undefined) {
|
||||||
this.webcamStream = make_mp4frag(this.slug, webcamURL);
|
this.webcamStream = make_mp4frag(this.slug, webcamURL, settings.webcam);
|
||||||
}
|
}
|
||||||
this.settingsMessage = {
|
this.settingsMessage = {
|
||||||
kind: "settings",
|
kind: "settings",
|
||||||
printer: this.slug,
|
printer: this.slug,
|
||||||
name: settings.appearance.name,
|
name: settings.appearance.name,
|
||||||
color: settings.appearance.color,
|
color: settings.appearance.color,
|
||||||
webcam: {
|
|
||||||
flipH: settings.webcam.flipH,
|
|
||||||
flipV: settings.webcam.flipV,
|
|
||||||
rotate90: settings.webcam.rotate90,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.broadcast(this.settingsMessage);
|
this.broadcast(this.settingsMessage);
|
||||||
|
|
||||||
|
@ -1,7 +1,29 @@
|
|||||||
import * as ffmpeg from 'fluent-ffmpeg';
|
import * as ffmpeg from 'fluent-ffmpeg';
|
||||||
import * as Mp4Frag from 'mp4frag';
|
import * as Mp4Frag from 'mp4frag';
|
||||||
|
|
||||||
export function make_mp4frag(slug: string, url: URL | string): Mp4Frag {
|
interface WebcamSettings {
|
||||||
|
flipH: boolean;
|
||||||
|
flipV: boolean;
|
||||||
|
rotate90: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function make_mp4frag(
|
||||||
|
slug: string,
|
||||||
|
url: URL | string,
|
||||||
|
webcamSettings: WebcamSettings
|
||||||
|
): Mp4Frag {
|
||||||
|
let transforms = [];
|
||||||
|
if (webcamSettings.flipH) {
|
||||||
|
transforms.push('hflip');
|
||||||
|
}
|
||||||
|
if (webcamSettings.flipV) {
|
||||||
|
transforms.push('vflip');
|
||||||
|
}
|
||||||
|
if (webcamSettings.rotate90) {
|
||||||
|
transforms.push('transpose=2');
|
||||||
|
}
|
||||||
|
console.log(transforms);
|
||||||
|
|
||||||
const command = ffmpeg(url.toString())
|
const command = ffmpeg(url.toString())
|
||||||
.nativeFramerate()
|
.nativeFramerate()
|
||||||
.inputOptions([
|
.inputOptions([
|
||||||
@ -12,7 +34,9 @@ export function make_mp4frag(slug: string, url: URL | string): Mp4Frag {
|
|||||||
.noAudio()
|
.noAudio()
|
||||||
.videoCodec('libx264')
|
.videoCodec('libx264')
|
||||||
.size('640x480')
|
.size('640x480')
|
||||||
|
.autopad()
|
||||||
.videoFilter('hqdn3d')
|
.videoFilter('hqdn3d')
|
||||||
|
.videoFilters(transforms)
|
||||||
.format('mp4')
|
.format('mp4')
|
||||||
.outputOptions([
|
.outputOptions([
|
||||||
'-tune zerolatency',
|
'-tune zerolatency',
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, Ref } from 'vue';
|
import { computed, ref, Ref } from 'vue';
|
||||||
|
|
||||||
import { Message, WebcamSettings } from '../types/messages';
|
import { Message } from '../types/messages';
|
||||||
import PrinterCard, { PrinterInfo } from './PrinterCard.vue';
|
import PrinterCard, { PrinterInfo } from './PrinterCard.vue';
|
||||||
|
|
||||||
const printers: Ref<{ [key: string]: PrinterInfo }> = ref({});
|
const printers: Ref<{ [key: string]: PrinterInfo }> = ref({});
|
||||||
@ -52,7 +52,6 @@ function connectWebsocket() {
|
|||||||
if (!(event.printer in printers.value)) {
|
if (!(event.printer in printers.value)) {
|
||||||
printers.value[event.printer] = {
|
printers.value[event.printer] = {
|
||||||
status: null,
|
status: null,
|
||||||
webcam: null,
|
|
||||||
color: null,
|
color: null,
|
||||||
lastUpdate: new Date(),
|
lastUpdate: new Date(),
|
||||||
};
|
};
|
||||||
@ -61,7 +60,6 @@ function connectWebsocket() {
|
|||||||
|
|
||||||
if (event.kind === 'settings') {
|
if (event.kind === 'settings') {
|
||||||
printers.value[event.printer].name = event.name;
|
printers.value[event.printer].name = event.name;
|
||||||
printers.value[event.printer].webcam = event.webcam;
|
|
||||||
printers.value[event.printer].color = event.color;
|
printers.value[event.printer].color = event.color;
|
||||||
} else if (event.kind === 'status') {
|
} else if (event.kind === 'status') {
|
||||||
if ('current' in event.msg && event.msg.current) {
|
if ('current' in event.msg && event.msg.current) {
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
muted
|
muted
|
||||||
class="card-img webcam"
|
class="card-img webcam"
|
||||||
ref="video"
|
ref="video"
|
||||||
:style="webcamTransform"
|
|
||||||
></video>
|
></video>
|
||||||
<div class="card-body" v-if="status">
|
<div class="card-body" v-if="status">
|
||||||
<div>{{ status.state.text }}</div>
|
<div>{{ status.state.text }}</div>
|
||||||
@ -54,7 +53,7 @@ import { computed, onMounted, Ref, ref, watchEffect } from 'vue';
|
|||||||
import prettyMilliseconds from 'pretty-ms';
|
import prettyMilliseconds from 'pretty-ms';
|
||||||
|
|
||||||
import { CurrentOrHistoryPayload } from '../types/octoprint';
|
import { CurrentOrHistoryPayload } from '../types/octoprint';
|
||||||
import { WebcamSettings, OctoprintColor } from '../types/messages';
|
import { OctoprintColor } from '../types/messages';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
slug: string;
|
slug: string;
|
||||||
@ -62,7 +61,6 @@ interface Props {
|
|||||||
lastUpdate: Date;
|
lastUpdate: Date;
|
||||||
now: Date;
|
now: Date;
|
||||||
status: CurrentOrHistoryPayload | null;
|
status: CurrentOrHistoryPayload | null;
|
||||||
webcam: WebcamSettings | null;
|
|
||||||
color: OctoprintColor | null;
|
color: OctoprintColor | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,24 +114,6 @@ const lastUpdateString = computed(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const webcamTransform = computed(() => {
|
|
||||||
if (props.webcam) {
|
|
||||||
const transforms = [];
|
|
||||||
if (props.webcam.flipH) {
|
|
||||||
transforms.push('scaleX(-1)');
|
|
||||||
}
|
|
||||||
if (props.webcam.flipV) {
|
|
||||||
transforms.push('scaleY(-1)');
|
|
||||||
}
|
|
||||||
if (props.webcam.rotate90) {
|
|
||||||
transforms.push('rotate(90)');
|
|
||||||
}
|
|
||||||
return { transform: transforms.join(' ') };
|
|
||||||
} else {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
console.log(video.value, hls.value);
|
console.log(video.value, hls.value);
|
||||||
if (hls.value && video.value) {
|
if (hls.value && video.value) {
|
||||||
@ -171,4 +151,8 @@ $bs-colors: ('red', 'orange', 'yellow', 'green', 'blue', 'white');
|
|||||||
color: var(--bs-light);
|
color: var(--bs-light);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.webcam {
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
7
types/messages.d.ts
vendored
7
types/messages.d.ts
vendored
@ -9,18 +9,11 @@ export interface StatusMessage extends BaseMessage {
|
|||||||
msg: OctoprintMessage;
|
msg: OctoprintMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WebcamSettings {
|
|
||||||
flipH: boolean;
|
|
||||||
flipV: boolean;
|
|
||||||
rotate90: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type OctoprintColor = 'red' | 'orange' | 'yellow' | 'green' | 'blue' | 'violet' | 'black' | 'white' | 'default';
|
export type OctoprintColor = 'red' | 'orange' | 'yellow' | 'green' | 'blue' | 'violet' | 'black' | 'white' | 'default';
|
||||||
|
|
||||||
export interface SettingsMessage extends BaseMessage {
|
export interface SettingsMessage extends BaseMessage {
|
||||||
kind: 'settings';
|
kind: 'settings';
|
||||||
name: string;
|
name: string;
|
||||||
webcam: WebcamSettings;
|
|
||||||
color: OctoprintColor;
|
color: OctoprintColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user