initial
This commit is contained in:
97
src/App.svelte
Normal file
97
src/App.svelte
Normal 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
128
src/Filter.svelte
Normal 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
15
src/Input.svelte
Normal 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
5
src/Output.svelte
Normal file
@ -0,0 +1,5 @@
|
||||
<script>
|
||||
export let filename="";
|
||||
</script>
|
||||
|
||||
<input bind:value={filename} />
|
26
src/app.css
Normal file
26
src/app.css
Normal 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
46025
src/filters.json
Normal file
File diff suppressed because it is too large
Load Diff
8
src/main.js
Normal file
8
src/main.js
Normal 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
5
src/stores.js
Normal 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
2
src/vite-env.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/// <reference types="svelte" />
|
||||
/// <reference types="vite/client" />
|
Reference in New Issue
Block a user