|
|
|
|
@ -14,6 +14,61 @@ let cachedVideos = []
|
|
|
|
|
|
|
|
|
|
let showText = true |
|
|
|
|
|
|
|
|
|
const parameterStore = { |
|
|
|
|
blendModeParams: { |
|
|
|
|
mode: "tile", // New blend mode for tiling
|
|
|
|
|
opacity: 1, |
|
|
|
|
// Additional parameters specific to the tile blend mode
|
|
|
|
|
tilePositionX: 0, // X-coordinate for positioning the tiled video
|
|
|
|
|
tilePositionY: 0, // Y-coordinate for positioning the tiled video
|
|
|
|
|
tileScaleX: 1, // Scale factor along the X-axis for the tiled video
|
|
|
|
|
tileScaleY: 1, // Scale factor along the Y-axis for the tiled video
|
|
|
|
|
}, |
|
|
|
|
filterParams: { |
|
|
|
|
grayscale: 0, |
|
|
|
|
blur: 0, |
|
|
|
|
// Add more filter parameters as needed
|
|
|
|
|
}, |
|
|
|
|
presets: { |
|
|
|
|
default: { |
|
|
|
|
blendModeParams: { mode: "screen", opacity: 1 }, |
|
|
|
|
}, |
|
|
|
|
sepia: { |
|
|
|
|
blendModeParams: { mode: "overlay", opacity: 0.5 }, |
|
|
|
|
}, |
|
|
|
|
tile: { |
|
|
|
|
tilePositionX: 0, |
|
|
|
|
tilePositionY: 0, |
|
|
|
|
tileScaleX: 1, |
|
|
|
|
tileScaleY: 1, |
|
|
|
|
}, |
|
|
|
|
// Add more presets as needed
|
|
|
|
|
}, |
|
|
|
|
selectedPreset: "default", |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
function applyPreset(presetName) { |
|
|
|
|
const preset = parameterStore.presets[presetName]; |
|
|
|
|
if (preset) { |
|
|
|
|
for (const [category, categoryParams] of Object.entries(preset)) { |
|
|
|
|
// Check if the category exists in the parameter store
|
|
|
|
|
if (parameterStore.hasOwnProperty(category)) { |
|
|
|
|
// Iterate over each parameter in the preset
|
|
|
|
|
for (const [paramKey, paramValue] of Object.entries(categoryParams)) { |
|
|
|
|
// Update the corresponding parameter in the parameter store
|
|
|
|
|
parameterStore[category][paramKey] = paramValue; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
console.error(`Category "${category}" not found in parameter store.`); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Update selected preset
|
|
|
|
|
parameterStore.selectedPreset = presetName; |
|
|
|
|
} else { |
|
|
|
|
console.error(`Preset "${presetName}" not found.`); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function debugLog(...args) { |
|
|
|
|
if (debugMode) { |
|
|
|
|
console.log(...args) |
|
|
|
|
@ -68,7 +123,7 @@ function handleVideoEnded(event) {
|
|
|
|
|
function drawVideos() { |
|
|
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height) |
|
|
|
|
|
|
|
|
|
let blendModes = ["source-over","overlay","screen"] |
|
|
|
|
let blendModes = ["screen","overlay","difference","lighten"] |
|
|
|
|
|
|
|
|
|
videos.forEach((video,i) => { |
|
|
|
|
// Calculate scaling factor to fit the canvas
|
|
|
|
|
@ -84,9 +139,9 @@ function drawVideos() {
|
|
|
|
|
|
|
|
|
|
// Use default blend mode for first video (i=0), repeat the rest of blendModes
|
|
|
|
|
if (i === 0) { |
|
|
|
|
ctx.globalCompositeOperation = blendModes[0] |
|
|
|
|
ctx.globalCompositeOperation = "source-over" |
|
|
|
|
} else { |
|
|
|
|
ctx.globalCompositeOperation = blendModes[(i - 1) % (blendModes.length - 1) + 1] |
|
|
|
|
ctx.globalCompositeOperation = blendModes[i % blendModes.length] |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Draw the current video frame onto the canvas
|
|
|
|
|
@ -109,9 +164,23 @@ function drawDebugText() {
|
|
|
|
|
// Set font style and color
|
|
|
|
|
ctx.font = "16px Arial" |
|
|
|
|
ctx.fillStyle = "white" |
|
|
|
|
let padding = 20 |
|
|
|
|
|
|
|
|
|
// Calculate the position for the active preset text at the top center of the canvas
|
|
|
|
|
const presetText = `${parameterStore.selectedPreset}`; |
|
|
|
|
const textWidth = ctx.measureText(presetText).width; |
|
|
|
|
const centerX = canvas.width / 2; |
|
|
|
|
const positionX = centerX - textWidth / 2; |
|
|
|
|
const positionY = padding; |
|
|
|
|
|
|
|
|
|
// Set text alignment to center horizontally
|
|
|
|
|
ctx.textAlign = "center"; |
|
|
|
|
ctx.textBaseline = "top"; |
|
|
|
|
|
|
|
|
|
// Draw the active preset text
|
|
|
|
|
ctx.fillText(presetText, positionX, positionY); |
|
|
|
|
|
|
|
|
|
let corners = [[0, 0], [1, 1], [0, 1], [1, 0]]; // Top-left, bottom-right, top-right, bottom-left
|
|
|
|
|
let padding = 20 |
|
|
|
|
|
|
|
|
|
videos.forEach((video, i) => { |
|
|
|
|
// Get the corner coordinates for the current video
|
|
|
|
|
@ -166,12 +235,12 @@ window.addEventListener("resize", updateCanvasSize)
|
|
|
|
|
function getSourceFiles() { |
|
|
|
|
debugLog("Getting source files") |
|
|
|
|
return fetch("/api/videos") |
|
|
|
|
.then(response => response.json()) |
|
|
|
|
.then(videoFiles => { |
|
|
|
|
debugLog("Success") |
|
|
|
|
cachedVideos = videoFiles; |
|
|
|
|
}) |
|
|
|
|
.catch(error => console.error("Error fetching videos:", error)); |
|
|
|
|
.then(response => response.json()) |
|
|
|
|
.then(videoFiles => { |
|
|
|
|
debugLog("Success") |
|
|
|
|
cachedVideos = videoFiles; |
|
|
|
|
}) |
|
|
|
|
.catch(error => console.error("Error fetching videos:", error)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function selectRandomVideo(videoElement) { |
|
|
|
|
@ -179,14 +248,14 @@ function selectRandomVideo(videoElement) {
|
|
|
|
|
const currentSrc = videoElement.src; |
|
|
|
|
const filteredVideos = cachedVideos.filter(video => video.src !== currentSrc); |
|
|
|
|
if (filteredVideos.length > 0) { |
|
|
|
|
const randomIndex = Math.floor(Math.random() * filteredVideos.length); |
|
|
|
|
const randomVideo = filteredVideos[randomIndex]; |
|
|
|
|
videoElement.src = randomVideo.src; |
|
|
|
|
const randomIndex = Math.floor(Math.random() * filteredVideos.length); |
|
|
|
|
const randomVideo = filteredVideos[randomIndex]; |
|
|
|
|
videoElement.src = randomVideo.src; |
|
|
|
|
} else { |
|
|
|
|
debugLog("No other videos available."); |
|
|
|
|
getSourceFiles().then(()=>{ |
|
|
|
|
selectRandomVideo(videoElement) |
|
|
|
|
}) |
|
|
|
|
debugLog("No other videos available."); |
|
|
|
|
getSourceFiles().then(()=>{ |
|
|
|
|
selectRandomVideo(videoElement) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
debugLog("Cache empty, doing new request") |
|
|
|
|
@ -197,17 +266,17 @@ function selectRandomVideo(videoElement) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
document.addEventListener('keydown', function(event) { |
|
|
|
|
console.log('keyDown',event) |
|
|
|
|
// Check if the pressed key is the one you want to bind
|
|
|
|
|
if (event.key === 'Enter') { |
|
|
|
|
showText = !showText |
|
|
|
|
} |
|
|
|
|
if (event.key === 'ArrowDown') { |
|
|
|
|
loadVideos(-1) |
|
|
|
|
} |
|
|
|
|
if (event.key === 'ArrowUp') { |
|
|
|
|
loadVideos(1) |
|
|
|
|
} |
|
|
|
|
console.log('keyDown',event) |
|
|
|
|
// Check if the pressed key is the one you want to bind
|
|
|
|
|
if (event.key === 'Enter') { |
|
|
|
|
showText = !showText |
|
|
|
|
} |
|
|
|
|
if (event.key === 'ArrowDown') { |
|
|
|
|
loadVideos(-1) |
|
|
|
|
} |
|
|
|
|
if (event.key === 'ArrowUp') { |
|
|
|
|
loadVideos(1) |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
getSourceFiles().then(()=>{ |
|
|
|
|
|