playing with graphs
This commit is contained in:
parent
9289f78f4d
commit
326aedb3fd
|
@ -16,6 +16,7 @@
|
|||
"@sveltejs/vite-plugin-svelte": "^2.4.2",
|
||||
"svelte": "^4.0.5",
|
||||
"svelte-dnd-action": "^0.9.25",
|
||||
"svelvet": "^8.1.0",
|
||||
"uuid": "^9.0.0",
|
||||
"vite": "^4.4.5"
|
||||
}
|
||||
|
@ -842,6 +843,15 @@
|
|||
"svelte": "^3.19.0 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/svelvet": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/svelvet/-/svelvet-8.1.0.tgz",
|
||||
"integrity": "sha512-rH67tgb7e2aTBQZBCW+V5hSvulLwvzBiOml9Dzdz2ATkgQr58mHi2WtlQFOOb+eZt6zH/J10a2MataC29Qdpuw==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"svelte": ">=3.59.2 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
"@sveltejs/vite-plugin-svelte": "^2.4.2",
|
||||
"svelte": "^4.0.5",
|
||||
"svelte-dnd-action": "^0.9.25",
|
||||
"svelvet": "^8.1.0",
|
||||
"uuid": "^9.0.0",
|
||||
"vite": "^4.4.5"
|
||||
},
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
<script>
|
||||
import { onMount } from "svelte";
|
||||
import { inputs, output, filters } from "./stores.js";
|
||||
import { inputs, addInput, output, filters } from "./stores.js";
|
||||
import Input from "./Input.svelte";
|
||||
import Output from "./Output.svelte";
|
||||
import Filter from "./Filter.svelte";
|
||||
import FilterPicker from "./FilterPicker.svelte";
|
||||
import Graph from "./Graph.svelte";
|
||||
import { FFmpeg } from "@ffmpeg/ffmpeg";
|
||||
import { fetchFile, toBlobURL } from "@ffmpeg/util";
|
||||
import { dndzone } from "svelte-dnd-action";
|
||||
|
@ -17,7 +18,7 @@
|
|||
const ffmpeg = new FFmpeg();
|
||||
|
||||
let command = "";
|
||||
let videoValue = "/" + $inputs[0];
|
||||
let videoValue = "/" + $inputs[0].name;
|
||||
let ffmpegLoaded = false;
|
||||
let rendering = false;
|
||||
let log = "";
|
||||
|
@ -25,7 +26,7 @@
|
|||
let commandRef;
|
||||
|
||||
function newInput() {
|
||||
$inputs = [...$inputs, "punch.mp4"];
|
||||
addInput("punch.mp4");
|
||||
}
|
||||
|
||||
function render() {
|
||||
|
@ -42,7 +43,7 @@
|
|||
rendering = true;
|
||||
try {
|
||||
for (let vid of $inputs) {
|
||||
await ffmpeg.writeFile(vid, await fetchFile("/" + vid));
|
||||
await ffmpeg.writeFile(vid.name, await fetchFile("/" + vid.name));
|
||||
}
|
||||
const clist = commandList();
|
||||
console.log(clist);
|
||||
|
@ -81,7 +82,8 @@
|
|||
}
|
||||
|
||||
function updateCommand() {
|
||||
const cInputs = $inputs.map((i) => `-i ${i}`).join(" ");
|
||||
console.log($inputs);
|
||||
const cInputs = $inputs.map((i) => `-i ${i.name}`).join(" ");
|
||||
|
||||
const cOutput = $output;
|
||||
|
||||
|
@ -116,7 +118,7 @@
|
|||
let command = [];
|
||||
for (let vid of $inputs) {
|
||||
command.push("-i");
|
||||
command.push(vid);
|
||||
command.push(vid.name);
|
||||
}
|
||||
// const audioFilters = $filters.filter(f => f.type[0] === "A").map(makeFilterArgs);
|
||||
// const videoFilters = $filters.filter(f => f.type[0] === "V").map(makeFilterArgs);
|
||||
|
@ -179,7 +181,7 @@
|
|||
<button on:click={newInput}>Add Input</button>
|
||||
</div>
|
||||
{#each $inputs as inp, index}
|
||||
<Input bind:filename={inp} {index} />
|
||||
<Input bind:filename={inp.name} id={inp.id} {index} />
|
||||
{/each}
|
||||
</section>
|
||||
|
||||
|
@ -233,6 +235,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="graph">
|
||||
<Graph />
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { filters } from "./stores.js";
|
||||
import { filters, removeFilter } from "./stores.js";
|
||||
|
||||
export let filter = {
|
||||
name: "",
|
||||
|
@ -10,9 +10,7 @@
|
|||
let show = false;
|
||||
|
||||
function remove() {
|
||||
const index = $filters.findIndex((f) => f.id === filter.id);
|
||||
$filters.splice(index, 1);
|
||||
$filters = $filters;
|
||||
removeFilter(filter.id);
|
||||
}
|
||||
|
||||
function reset() {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<script>
|
||||
import uFuzzy from "@leeoniya/ufuzzy";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import FILTERS from "./filters.json";
|
||||
import { filters } from "./stores.js";
|
||||
import { addFilter } from "./stores.js";
|
||||
|
||||
export let select = "video";
|
||||
$: selectedFilters = selectFilters(select);
|
||||
|
@ -26,16 +25,7 @@
|
|||
}
|
||||
|
||||
function add(f) {
|
||||
const newFilter = { ...f, filterId: f.id, id: uuidv4() };
|
||||
if (f.params) {
|
||||
newFilter.params = f.params.map((p) => {
|
||||
p.value = null;
|
||||
if (p.default != null) p.value = p.default;
|
||||
return p;
|
||||
});
|
||||
}
|
||||
$filters = [...$filters, newFilter];
|
||||
console.log(newFilter);
|
||||
addFilter(f);
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
<script>
|
||||
import { inputs, output, filters } from "./stores.js";
|
||||
import { Anchor, Node, Svelvet, Minimap, Controls } from "svelvet";
|
||||
import { generateInput, generateOutput } from "svelvet";
|
||||
|
||||
function countInputs(f) {
|
||||
const [ins, outs] = f.type.split("->");
|
||||
if (ins == "N") return 1;
|
||||
return ins.length;
|
||||
}
|
||||
|
||||
function countCons(f) {
|
||||
const [ins, outs] = f.type.split("->");
|
||||
return { in: ins.split(""), out: outs.split("") };
|
||||
}
|
||||
|
||||
function countOutputs(f) {
|
||||
const [ins, outs] = f.type.split("->");
|
||||
if (outs == "N") return 1;
|
||||
return outs.length;
|
||||
}
|
||||
|
||||
function onConnect(e) {
|
||||
const sourceAnchor = e.detail.sourceAnchor;
|
||||
const targetAnchor = e.detail.targetAnchor;
|
||||
const sourceNode = e.detail.sourceNode;
|
||||
const targetNode = e.detail.targetNode;
|
||||
console.log(sourceNode.id, "->", targetNode.id)
|
||||
console.log(sourceAnchor.id, "->", targetAnchor.id)
|
||||
}
|
||||
function onDisconnect(e) {
|
||||
const sourceAnchor = e.detail.sourceAnchor;
|
||||
const targetAnchor = e.detail.targetAnchor;
|
||||
const sourceNode = e.detail.sourceNode;
|
||||
const targetNode = e.detail.targetNode;
|
||||
console.log(sourceNode.id, "-/>", targetNode.id)
|
||||
console.log(sourceAnchor.id, "-/>", targetAnchor.id)
|
||||
}
|
||||
</script>
|
||||
|
||||
<Svelvet
|
||||
id="my-canvas"
|
||||
width={800}
|
||||
height={500}
|
||||
snapTo={25}
|
||||
on:disconnection={onDisconnect}
|
||||
on:connection={onConnect}
|
||||
>
|
||||
{#each $inputs as inp, index}
|
||||
<Node inputs={0} outputs={2}>
|
||||
<div class="node">
|
||||
<div class="header">
|
||||
{inp}
|
||||
</div>
|
||||
<slot />
|
||||
</div>
|
||||
<div class="output-anchors">
|
||||
<Anchor id={"v" + index} let:linked let:connecting let:hovering output>
|
||||
<div class:linked class:hovering class:connecting class="anchor video">v</div>
|
||||
</Anchor>
|
||||
<Anchor id={"a" + index} let:linked let:connecting let:hovering output>
|
||||
<div class:linked class:hovering class:connecting class="anchor audio">a</div>
|
||||
</Anchor>
|
||||
</div>
|
||||
</Node>
|
||||
{/each}
|
||||
|
||||
{#each $filters as f, index}
|
||||
<Node inputs={countInputs(f)} outputs={countOutputs(f)}>
|
||||
<div class="node">
|
||||
<div class="header">
|
||||
{f.name}
|
||||
</div>
|
||||
<slot />
|
||||
</div>
|
||||
<div class="input-anchors">
|
||||
{#each countCons(f).in as inp}
|
||||
<Anchor let:linked let:connecting let:hovering input>
|
||||
<div class:linked class:hovering class:connecting class="anchor in {inp}">{inp}</div>
|
||||
</Anchor>
|
||||
{/each}
|
||||
</div>
|
||||
<div class="output-anchors">
|
||||
{#each countCons(f).out as out}
|
||||
<Anchor let:linked let:connecting let:hovering output>
|
||||
<div class:linked class:hovering class:connecting class="anchor in {out}">{out}</div>
|
||||
</Anchor>
|
||||
{/each}
|
||||
</div>
|
||||
</Node>
|
||||
{/each}
|
||||
|
||||
<Node inputs={2} outputs="0" position={{ x: 600, y: 250 }}>
|
||||
<div class="node">
|
||||
<div class="header">
|
||||
{$output}
|
||||
</div>
|
||||
<slot />
|
||||
</div>
|
||||
<div class="input-anchors">
|
||||
<Anchor id={"output_video"} let:linked let:connecting let:hovering input>
|
||||
<div class:linked class:hovering class:connecting class="anchor video">v</div>
|
||||
</Anchor>
|
||||
<Anchor id={"output_audio"} let:linked let:connecting let:hovering input>
|
||||
<div class:linked class:hovering class:connecting class="anchor audio">a</div>
|
||||
</Anchor>
|
||||
</div>
|
||||
</Node>
|
||||
<Controls />
|
||||
</Svelvet>
|
||||
|
||||
<style>
|
||||
.node {
|
||||
box-sizing: border-box;
|
||||
width: fit-content;
|
||||
height: fit-content;
|
||||
position: relative;
|
||||
pointer-events: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 10px;
|
||||
gap: 10px;
|
||||
background-color: #fff;
|
||||
border: 1px solid var(--b1);
|
||||
font: 12px Times, serif;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.output-anchors {
|
||||
position: absolute;
|
||||
right: -16px;
|
||||
top: 0px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
.input-anchors {
|
||||
position: absolute;
|
||||
left: -16px;
|
||||
top: 0px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
.anchor {
|
||||
background-color: #fff;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
line-height: 12px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
font-family: Times, serif;
|
||||
border: solid 1px white;
|
||||
border-color: var(--b1);
|
||||
}
|
||||
.hovering {
|
||||
scale: 1.2;
|
||||
}
|
||||
.linked {
|
||||
background-color: rgb(17, 214, 17) !important;
|
||||
}
|
||||
.connecting {
|
||||
background-color: goldenrod;
|
||||
}
|
||||
</style>
|
|
@ -1,11 +1,12 @@
|
|||
<script>
|
||||
import { inputs } from "./stores.js";
|
||||
import { removeInput } from "./stores.js";
|
||||
export let filename = "punch.mp4";
|
||||
export let id;
|
||||
export let index;
|
||||
|
||||
function remove() {
|
||||
$inputs.splice(index, 1);
|
||||
$inputs = $inputs;
|
||||
console.log(id);
|
||||
removeInput(id);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,5 +1,55 @@
|
|||
import { v4 as uuidv4 } from "uuid";
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
export const inputs = writable(["punch.mp4"]);
|
||||
export const inputs = writable([{name: "punch.mp4", id: uuidv4()}]);
|
||||
export const output = writable("out.mp4");
|
||||
export const filters = writable([]);
|
||||
|
||||
export function addFilter(f) {
|
||||
const newFilter = { ...f, filterId: f.id, id: uuidv4() };
|
||||
if (f.params) {
|
||||
newFilter.params = f.params.map((p) => {
|
||||
p.value = null;
|
||||
if (p.default != null) p.value = p.default;
|
||||
return p;
|
||||
});
|
||||
}
|
||||
filters.update((filts) => {
|
||||
filts.push(newFilter)
|
||||
return filts;
|
||||
})
|
||||
}
|
||||
|
||||
export function removeFilter(id) {
|
||||
filters.update((filts) => {
|
||||
const index = filts.findIndex((f) => f.id === id);
|
||||
filts.splice(index, 1);
|
||||
return filts;
|
||||
});
|
||||
}
|
||||
|
||||
export function addOutput(f) {
|
||||
|
||||
}
|
||||
|
||||
export function removeOutput(f) {
|
||||
|
||||
}
|
||||
|
||||
export function addInput(f) {
|
||||
const newInput = {name: f, id: uuidv4()}
|
||||
inputs.update((inps) => {
|
||||
inps.push(newInput);
|
||||
return inps;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
export function removeInput(id) {
|
||||
inputs.update((inps) => {
|
||||
const index = inps.findIndex((f) => f.id === id);
|
||||
inps.splice(index, 1);
|
||||
return inps;
|
||||
});
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue