2
0
mirror of https://github.com/ad1217/PrinterStatus synced 2024-11-22 07:23:48 -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:
Adam Goldsmith 2021-11-18 19:45:51 -05:00
parent cc0f6d90d0
commit afe6a1aed5
5 changed files with 32 additions and 38 deletions

View File

@ -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);

View File

@ -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',

View File

@ -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) {

View File

@ -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
View File

@ -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;
} }