ffmpeg-explorer/src/stores.js

346 lines
7.9 KiB
JavaScript
Raw Normal View History

2023-08-22 12:05:49 -04:00
import { v4 as uuidv4 } from "uuid";
2023-08-22 21:57:53 -04:00
import { writable, derived, get } from "svelte/store";
2023-08-22 12:05:49 -04:00
2023-08-22 21:57:53 -04:00
// export const inputs = writable([]);
// export const output = writable("out.mp4");
// export const filters = writable([]);
export const nodes = writable([]);
export const edges = writable([]);
2023-08-24 12:09:55 -04:00
export const auto = writable(true);
2023-08-22 12:05:49 -04:00
2023-08-22 21:57:53 -04:00
addNode({ name: "punch.mp4" }, "input");
addNode({ name: "out.mp4" }, "output");
2023-08-22 12:05:49 -04:00
2023-08-22 21:57:53 -04:00
function makeFilterArgs(f) {
let fCommand = f.name;
if (f.params && f.params.length > 0) {
let params = f.params
.map((p) => {
if (p.value === "" || p.value === null || p.value === p.default) return null;
return `${p.name}=${p.value}`;
})
.filter((p) => p !== null)
.join(":");
if (params) fCommand += "=" + params;
}
return fCommand;
2023-08-22 12:05:49 -04:00
}
2023-08-23 16:27:48 -04:00
export const previewCommand = derived([edges, nodes], ([$edges, $nodes]) => {
// [0:v]f1=val,f2=val[out] -map out
// [0:v]f1=val,f2=val[1];[1][1:v]overlay[out] -map out`
let finalCommand = [];
2023-08-23 19:30:04 -04:00
let filtergraph = [];
const inputs = $nodes.filter(n => n.nodeType == "input");
const outputs = $nodes.filter(n => n.nodeType == "output");
const inputIds = {};
for (let i=0; i<inputs.length; i++) {
const inp = inputs[i];
inputIds[inp.id] = i;
}
const edgeIds = {};
for (let i = 0; i < $edges.length; i++) {
const e = $edges[i];
edgeIds[e.id] = i + 1;
const source = $nodes.find(n => "N-" + n.id === e.source);
const target = $nodes.find(n => "N-" + n.id === e.target);
2023-08-24 12:09:55 -04:00
if (!source || !target) continue;
2023-08-23 19:30:04 -04:00
if (source.nodeType === "input") {
if (e.sourceAnchor.startsWith("A-v")) {
edgeIds[e.id] = inputIds[source.id] + ":v";
}
if (e.sourceAnchor.startsWith("A-a")) {
edgeIds[e.id] = inputIds[source.id] + ":a";
}
}
if (target.nodeType === "output") {
edgeIds[e.id] = "out";
}
}
for (let n of $nodes.filter((n) => n.nodeType == "filter")) {
let cmd = "";
const outs = $edges.filter((e) => e.source == "N-" + n.id);
const ins = $edges.filter((e) => e.target == "N-" + n.id);
if (outs.length == 0 && ins.length == 0) continue;
for (let i of ins) {
const eid = edgeIds[i.id];
cmd += `[${eid}]`
}
cmd += makeFilterArgs(n.data);
for (let o of outs) {
const eid = edgeIds[o.id];
cmd += `[${eid}]`
}
filtergraph.push(cmd);
}
finalCommand.push("ffmpeg");
for (let inp of inputs) {
finalCommand.push("-i");
finalCommand.push(inp.data.name);
}
finalCommand.push("-filter_complex")
finalCommand.push('"' + filtergraph.join(';') + '"');
for (let out of outputs) {
finalCommand.push("-map");
finalCommand.push('"[out]"');
}
for (let inp of inputs) {
finalCommand.push("-map");
finalCommand.push(inputIds[inp.id] + ":a");
}
for (let out of outputs) {
finalCommand.push(out.data.name);
}
const entireCommand = finalCommand.join(" ");
return entireCommand;
});
export const previewCommandOld2 = derived([edges, nodes], ([$edges, $nodes]) => {
// [0:v]f1=val,f2=val[out] -map out
// [0:v]f1=val,f2=val[1];[1][1:v]overlay[out] -map out`
let finalCommand = [];
2023-08-23 16:27:48 -04:00
let filtergraph = [];
const inputs = $nodes.filter(n => n.nodeType == "input");
const outputs = $nodes.filter(n => n.nodeType == "output");
const inputIds = {};
for (let i=0; i<inputs.length; i++) {
const inp = inputs[i];
inputIds[inp.id] = i;
}
const edgeIds = {};
for (let i = 0; i < $edges.length; i++) {
const e = $edges[i];
edgeIds[e.id] = i + 1;
const source = $nodes.find(n => n.id === e.source);
const target = $nodes.find(n => n.id === e.target);
if (source.nodeType === "input") {
if (e.sourceHandle.includes("v")) {
edgeIds[e.id] = inputIds[source.id] + ":v";
}
if (e.sourceHandle.includes("a")) {
edgeIds[e.id] = inputIds[source.id] + ":a";
}
}
if (target.nodeType === "output") {
edgeIds[e.id] = "out";
}
}
for (let n of $nodes.filter((n) => n.nodeType == "filter")) {
let cmd = "";
const outs = $edges.filter((e) => e.source == n.id);
const ins = $edges.filter((e) => e.target == n.id);
if (outs.length == 0 && ins.length == 0) continue;
for (let i of ins) {
const eid = edgeIds[i.id];
cmd += `[${eid}]`
}
cmd += makeFilterArgs(n.data);
for (let o of outs) {
const eid = edgeIds[o.id];
cmd += `[${eid}]`
}
filtergraph.push(cmd);
}
finalCommand.push("ffmpeg");
for (let inp of inputs) {
finalCommand.push("-i");
finalCommand.push(inp.data.name);
}
finalCommand.push("-filter_complex")
finalCommand.push('"' + filtergraph.join(';') + '"');
for (let out of outputs) {
finalCommand.push("-map");
finalCommand.push('"[out]"');
}
for (let inp of inputs) {
finalCommand.push("-map");
finalCommand.push(inputIds[inp.id] + ":a");
}
for (let out of outputs) {
finalCommand.push(out.data.name);
}
const entireCommand = finalCommand.join(" ");
return entireCommand;
2023-08-22 21:57:53 -04:00
});
2023-08-22 12:05:49 -04:00
2023-08-23 16:27:48 -04:00
export const previewCommandOld = derived(nodes, ($nodes) => {
2023-08-22 21:57:53 -04:00
const cInputs = $nodes
.filter((n) => n.nodeType === "input")
.map((i) => `-i ${i.data.name}`)
.join(" ");
2023-08-22 12:05:49 -04:00
2023-08-22 21:57:53 -04:00
const cOutput = $nodes
.filter((n) => n.nodeType === "output")
.map((i) => `${i.data.name}`)
.join(" ");
2023-08-22 12:05:49 -04:00
2023-08-22 21:57:53 -04:00
const cFilters = $nodes
.filter((n) => n.nodeType === "filter")
.map((n) => n.data)
.map(makeFilterArgs)
.join(",");
let out = `ffmpeg ${cInputs}`;
if (cFilters) out += ` -filter_complex "${cFilters}"`;
out += ` ${cOutput}`;
return out;
});
export const inputs = derived(nodes, ($nodes) => {
return $nodes.filter((n) => n.nodeType === "input").map((n) => n.data);
});
export const filters = derived(nodes, ($nodes) => {
return $nodes.filter((n) => n.nodeType === "filter").map((n) => n.data);
});
export const output = derived(nodes, ($nodes) => {
return $nodes.filter((n) => n.nodeType === "output").map((n) => n.data);
});
2023-08-22 12:05:49 -04:00
2023-08-22 21:57:53 -04:00
export function addNode(data, type) {
let ins = [];
let outs = [];
if (type === "input") {
outs = ["v", "a"];
} else if (type === "output") {
ins = ["v", "a"];
} else if (type === "filter") {
const [_ins, _outs] = data.type.split("->");
ins = _ins.toLowerCase().split("");
outs = _outs.toLowerCase().split("");
if (data.params) {
data.params = data.params.map((p) => {
p.value = null;
if (p.default != null) p.value = p.default;
return p;
});
}
}
let x = 0;
let y = 0;
const w = 100;
const h = 50;
const margin = 10;
const existing = get(nodes);
2023-08-24 12:09:55 -04:00
const ouputNode = existing.find(n => n.nodeType === 'output');
const inputNodes = existing.find(n => n.nodeType === "input");
2023-08-22 21:57:53 -04:00
if (type === "input") {
const inps = existing.filter((n) => n.nodeType === "input");
y = inps.length * h;
} else if (type === "filter") {
const flts = existing.filter((n) => n.nodeType === "filter");
x = (flts.length + 1) * w;
} else if (type === "output") {
x = 500;
}
data.inputs = ins;
data.outputs = outs;
2023-08-24 12:09:55 -04:00
2023-08-22 21:57:53 -04:00
let node = {
id: uuidv4(),
type: "ffmpeg",
data: data,
nodeType: type,
position: { x, y },
};
nodes.update((n) => {
n.push(node);
return n;
});
2023-08-24 12:09:55 -04:00
if (auto) {
const prev = existing[existing.length - 2];
if (prev) {
// set each prev out to new node in
// set new node out to output in
}
}
//autolayout();
2023-08-23 16:27:48 -04:00
// edges.update((_edges) => {
// const target = existing[existing.length - 2];
// if (!target) return _edges;
// const newEdge = {
// id: uuidv4(),
// type: "default",
// source: target.id,
// target: node.id,
// };
// _edges.push(newEdge);
// return _edges;
// });
2023-08-22 21:57:53 -04:00
}
2023-08-22 12:05:49 -04:00
2023-08-22 21:57:53 -04:00
export function removeNode(id) {
nodes.update((_nodes) => {
const index = _nodes.findIndex((n) => n.id === id);
_nodes.splice(index, 1);
return _nodes;
});
2023-08-24 12:09:55 -04:00
edges.update((_edges) => {
for (let i=_edges.length-1; i--; i>=0) {
const e = _edges[i];
if ("N-" + e.source === id || "N-" + e.target === id) {
_edges.splice(i, 1);
}
}
return _edges;
});
2023-08-22 12:05:49 -04:00
}