156 lines
6.1 KiB
JavaScript
Executable File
156 lines
6.1 KiB
JavaScript
Executable File
import { app } from '../../../scripts/app.js'
|
|
import { api } from '../../../scripts/api.js'
|
|
|
|
function chainCallback(object, property, callback) {
|
|
if (object == undefined) {
|
|
//This should not happen.
|
|
console.error("Tried to add callback to non-existant object")
|
|
return
|
|
}
|
|
if (property in object) {
|
|
const callback_orig = object[property]
|
|
object[property] = function () {
|
|
const r = callback_orig.apply(this, arguments)
|
|
callback.apply(this, arguments)
|
|
return r
|
|
}
|
|
} else {
|
|
object[property] = callback
|
|
}
|
|
}
|
|
|
|
function fitHeight(node) {
|
|
node.setSize([node.size[0], node.computeSize([node.size[0], node.size[1]])[1]])
|
|
node?.graph?.setDirtyCanvas(true)
|
|
}
|
|
|
|
function addVideoPreview(nodeType) {
|
|
chainCallback(nodeType.prototype, "onNodeCreated", function () {
|
|
var element = document.createElement("div")
|
|
const previewNode = this
|
|
var previewWidget = this.addDOMWidget("videopreview", "preview", element, {
|
|
serialize: false,
|
|
hideOnZoom: false,
|
|
getValue() {
|
|
return element.value
|
|
},
|
|
setValue(v) {
|
|
element.value = v
|
|
},
|
|
})
|
|
previewWidget.computeSize = function (width) {
|
|
if (this.aspectRatio && !this.parentEl.hidden) {
|
|
let height = (previewNode.size[0] - 20) / this.aspectRatio + 10
|
|
if (!(height > 0)) {
|
|
height = 0
|
|
}
|
|
this.computedHeight = height + 10
|
|
return [width, height]
|
|
}
|
|
return [width, -4]//no loaded src, widget should not display
|
|
}
|
|
element.style['pointer-events'] = "none"
|
|
previewWidget.value = { hidden: false, paused: false, params: {} }
|
|
previewWidget.parentEl = document.createElement("div")
|
|
previewWidget.parentEl.className = "vhs_preview"
|
|
previewWidget.parentEl.style['width'] = "100%"
|
|
element.appendChild(previewWidget.parentEl)
|
|
previewWidget.videoEl = document.createElement("video")
|
|
previewWidget.videoEl.controls = false
|
|
previewWidget.videoEl.loop = true
|
|
previewWidget.videoEl.muted = true
|
|
previewWidget.videoEl.style['width'] = "100%"
|
|
previewWidget.videoEl.addEventListener("loadedmetadata", () => {
|
|
previewWidget.aspectRatio = previewWidget.videoEl.videoWidth / previewWidget.videoEl.videoHeight
|
|
fitHeight(this)
|
|
})
|
|
previewWidget.videoEl.addEventListener("error", () => {
|
|
//TODO: consider a way to properly notify the user why a preview isn't shown.
|
|
previewWidget.parentEl.hidden = true
|
|
fitHeight(this)
|
|
})
|
|
|
|
previewWidget.imgEl = document.createElement("img")
|
|
previewWidget.imgEl.style['width'] = "100%"
|
|
previewWidget.imgEl.hidden = true
|
|
previewWidget.imgEl.onload = () => {
|
|
previewWidget.aspectRatio = previewWidget.imgEl.naturalWidth / previewWidget.imgEl.naturalHeight
|
|
fitHeight(this)
|
|
}
|
|
|
|
var timeout = null
|
|
this.updateParameters = (params, force_update) => {
|
|
if (!previewWidget.value.params) {
|
|
if (typeof (previewWidget.value != 'object')) {
|
|
previewWidget.value = { hidden: false, paused: false }
|
|
}
|
|
previewWidget.value.params = {}
|
|
}
|
|
Object.assign(previewWidget.value.params, params)
|
|
if (!force_update &&
|
|
!app.ui.settings.getSettingValue("VHS.AdvancedPreviews", false)) {
|
|
return
|
|
}
|
|
if (timeout) {
|
|
clearTimeout(timeout)
|
|
}
|
|
if (force_update) {
|
|
previewWidget.updateSource()
|
|
} else {
|
|
timeout = setTimeout(() => previewWidget.updateSource(), 100)
|
|
}
|
|
}
|
|
previewWidget.updateSource = function () {
|
|
if (this.value.params == undefined) {
|
|
return
|
|
}
|
|
let params = {}
|
|
Object.assign(params, this.value.params)//shallow copy
|
|
this.parentEl.hidden = this.value.hidden
|
|
if (
|
|
params.format?.split('/')[0] == 'video' ||
|
|
params.format == 'folder'
|
|
) {
|
|
this.videoEl.autoplay = !this.value.paused && !this.value.hidden
|
|
previewWidget.videoEl.src = api.apiURL('/view?' + new URLSearchParams(params))
|
|
this.videoEl.hidden = false
|
|
this.imgEl.hidden = true
|
|
} else if (params.format?.split('/')[0] == 'image') {
|
|
//Is animated image
|
|
this.imgEl.src = api.apiURL('/view?' + new URLSearchParams(params))
|
|
this.videoEl.hidden = true
|
|
this.imgEl.hidden = false
|
|
}
|
|
}
|
|
previewWidget.parentEl.appendChild(previewWidget.videoEl)
|
|
previewWidget.parentEl.appendChild(previewWidget.imgEl)
|
|
})
|
|
}
|
|
|
|
app.registerExtension({
|
|
name: "TranscriptionTools.core",
|
|
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
|
if (nodeData?.name == "TT-LoadVideoAudio") {
|
|
chainCallback(nodeType.prototype, "onNodeCreated", function () {
|
|
const pathWidget = this.widgets.find((w) => w.name === "video")
|
|
chainCallback(pathWidget, "callback", (value) => {
|
|
if (!value) {
|
|
return
|
|
}
|
|
let parts = ["input", value]
|
|
let extension_index = parts[1].lastIndexOf(".")
|
|
let extension = parts[1].slice(extension_index + 1)
|
|
let format = "video"
|
|
if (["gif", "webp", "avif"].includes(extension)) {
|
|
format = "image"
|
|
}
|
|
format += "/" + extension
|
|
let params = { filename: parts[1], type: parts[0], format: format }
|
|
this.updateParameters(params, true)
|
|
})
|
|
})
|
|
addVideoPreview(nodeType)
|
|
}
|
|
},
|
|
})
|