This commit is contained in:
Sam Lavigne
2023-08-18 17:23:56 -04:00
parent 74eadfce99
commit 94279a0265
21 changed files with 47817 additions and 2 deletions

97
src/App.svelte Normal file
View File

@ -0,0 +1,97 @@
<script>
import FILTERS from "./filters.json";
import { inputs, output, filters } from "./stores.js";
import Input from "./Input.svelte";
import Output from "./Output.svelte";
import Filter from "./Filter.svelte";
function newInput() {
$inputs = [...$inputs, ""];
}
function newFilter() {
$filters = [...$filters, {}];
}
let command = "";
inputs.subscribe(updateCommand);
output.subscribe(updateCommand);
filters.subscribe(updateCommand);
function updateCommand() {
const cInputs = $inputs.map((i) => `-i ${i}`).join(" ");
const cOutput = $output;
const cFilters = $filters
.map((f) => {
let fCommand = f.name;
if (f.params && f.params.length > 0) {
let params = f.params
.map((p) => {
if (p.value === "" || p.value === null) return null;
return `${p.name}=${p.value}`;
})
.filter((p) => p !== null)
.join(":");
fCommand += "=" + params;
}
return fCommand;
})
.join(",");
let out = `ffmpeg ${cInputs}`;
if (cFilters) out += `-vf "${cFilters}"`;
out += ` ${cOutput}`;
command = out;
return out;
}
</script>
<main>
<section class="command">{command}</section>
<section class="inputs">
<h3>Inputs</h3>
{#each $inputs as inp, index}
<Input bind:filename={inp} {index} />
{/each}
<button on:click={newInput}>New Input</button>
{#each $inputs as inp}
<p>{inp}</p>
{/each}
</section>
<section class="filters">
<!-- {JSON.stringify($filters)} -->
<h3>Filters</h3>
<button on:click={newFilter}>Add Filter</button>
<div class="filters-holder">
{#each $filters as f, index}
<div class="filter">
<Filter bind:filter={f} {index} />
</div>
{/each}
</div>
</section>
<section class="output">
<h3>Output</h3>
<Output bind:filename={$output} />
<p>{$output}</p>
</section>
</main>
<style>
.filters-holder {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.filter {
margin: 10px;
}
</style>

128
src/Filter.svelte Normal file
View File

@ -0,0 +1,128 @@
<script>
import FILTERS from "./filters.json";
import { filters } from "./stores.js";
export let filter = {
name: "",
params: [],
description: "",
};
let filterIndex;
export let index;
console.log(index);
function remove() {
console.log(index);
$filters.splice(index, 1);
$filters = $filters;
}
function changeFilter() {
filter = {
name: current.name,
description: current.description,
params: current.params.map((p) => {
p.value = null;
if (p.default != null) p.value = p.default;
return p;
}),
};
console.log(filter);
}
$: current = FILTERS[filterIndex];
</script>
<div class="filter-holder">
<div class="head">
<select bind:value={filterIndex} on:change={changeFilter}>
<option />
{#each FILTERS as f, i}
<option value={i}>{f.name}</option>
{/each}
</select>
<button on:click={remove}>X</button>
</div>
{#if filter.name}
<div class="description">{current.description}</div>
{#if filter.params.length > 0}
<div class="options">
{#each filter.params as p}
<!-- <p>{p.min} {p.max} {p.default}</p> -->
<div class="param-holder">
<div class="param">
<span class="p-name">{p.name}</span>
<span class="p-value">
{#if p.options && p.options.length > 0}
<select bind:value={p.value}>
{#each p.options as o}
<option value={o.value}>{o.value}
{#if o.desc}({o.desc}){/if}
</option>
{/each}
</select>
{:else}
{#if p.type == "float" || p.type == "double" || p.type == "long" || p.type=="int"}
<input type="range" min={p.min} max={p.max} bind:value={p.value} />
<input bind:value={p.value} />
{:else}
<input bind:value={p.value} />
{/if}
{/if}
</span>
</div>
<div class="p-description">{p.desc}</div>
</div>
{/each}
</div>
{/if}
{/if}
</div>
<style>
.filter-holder {
background-color: #fff;
padding: 10px;
}
.filter-holder,
input,
select {
font-size: 14px;
font-family: "Times New Roman", Times, serif;
}
.description {
margin: 10px 0px;
}
.head {
display: flex;
justify-content: space-between;
}
.options {
/* margin-top: 10px; */
/* padding-top: 10px; */
}
.param {
margin-bottom: 5px;
display: flex;
justify-content: space-between;
}
.param-holder {
border-top: 1px solid #999;
padding: 10px 0px;
}
.param-holder:last-child {
padding-bottom: 0;
}
.p-description {
opacity: 0.8;
font-size: 0.9em;
}
p {
margin: 0;
}
</style>

15
src/Input.svelte Normal file
View File

@ -0,0 +1,15 @@
<script>
import { inputs } from './stores.js';
export let filename="";
export let index;
function remove() {
$inputs.splice(index, 1);
$inputs = $inputs;
}
</script>
<div>
<input bind:value={filename} />
<button on:click={remove}>Remove</button>
</div>

5
src/Output.svelte Normal file
View File

@ -0,0 +1,5 @@
<script>
export let filename="";
</script>
<input bind:value={filename} />

26
src/app.css Normal file
View File

@ -0,0 +1,26 @@
:root {
}
a {
}
a:hover {
}
body {
background-color: #eee;
}
h1 {
}
#app {
}
button {
}
button:hover {
}
button:focus,
button:focus-visible {
}

46025
src/filters.json Normal file

File diff suppressed because it is too large Load Diff

8
src/main.js Normal file
View File

@ -0,0 +1,8 @@
import './app.css'
import App from './App.svelte'
const app = new App({
target: document.getElementById('app'),
})
export default app

5
src/stores.js Normal file
View File

@ -0,0 +1,5 @@
import { writable } from 'svelte/store';
export const inputs = writable(["input.mp4"]);
export const output = writable("output.mp4");
export const filters = writable([]);

2
src/vite-env.d.ts vendored Normal file
View File

@ -0,0 +1,2 @@
/// <reference types="svelte" />
/// <reference types="vite/client" />