From f708f57b3747215280778b2a2a4b171f0a37fbf9 Mon Sep 17 00:00:00 2001 From: Sam Lavigne Date: Sat, 19 Aug 2023 17:31:55 -0400 Subject: [PATCH] a bit better --- src/App.svelte | 255 +++++++++++++++++++++++++++++----------- src/Filter.svelte | 18 ++- src/FilterPicker.svelte | 53 +++++++-- src/Input.svelte | 33 ++++-- src/app.css | 11 ++ src/stores.js | 2 +- 6 files changed, 277 insertions(+), 95 deletions(-) diff --git a/src/App.svelte b/src/App.svelte index 42c4ddf..a278a1c 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -5,43 +5,46 @@ import Output from "./Output.svelte"; import Filter from "./Filter.svelte"; import FilterPicker from "./FilterPicker.svelte"; - import Modal from "./Modal.svelte"; import { FFmpeg } from "@ffmpeg/ffmpeg"; import { fetchFile, toBlobURL } from "@ffmpeg/util"; const baseURL = "https://unpkg.com/@ffmpeg/core-mt@0.12.2/dist/esm"; // const baseURL = ""; // const videoURL = "https://ffmpegwasm.netlify.app/video/video-15s.avi"; - const videoURL = "/example.mp4"; const TIMEOUT = 40000; const ffmpeg = new FFmpeg(); - let showFilterModal = false; let command = ""; let message = ""; - let videoValue = null; + let videoValue = "/" + $inputs[0]; let ffmpegLoaded = false; let rendering = false; + let log = ""; + let logbox; + let commandRef; function newInput() { - $inputs = [...$inputs, ""]; - } - - function newFilter() { - showFilterModal = true; + $inputs = [...$inputs, "punch.mp4"]; } function render() { transcode(); } + function copyCommand() { + commandRef.select(); + document.execCommand("copy"); + } + async function transcode() { // try { message = "Start transcoding"; videoValue = null; rendering = true; - await ffmpeg.writeFile("example.mp4", await fetchFile(videoURL)); + for (let vid of $inputs) { + await ffmpeg.writeFile(vid, await fetchFile("/" + vid)); + } // const infile = await ffmpeg.readFile("example.mp4"); // videoValue = URL.createObjectURL(new Blob([infile.buffer], { type: "video/mp4" })); // console.log("VIDEO", videoValue); @@ -65,22 +68,7 @@ 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(","); + const cFilters = $filters.map(makeFilterArgs).join(","); let out = `ffmpeg ${cInputs}`; @@ -102,16 +90,21 @@ }) .filter((p) => p !== null) .join(":"); - fCommand += "=" + params; + if (params) fCommand += "=" + params; } return fCommand; } function commandList() { - let command = ["-i", "example.mp4"]; + let command = []; + for (let vid of $inputs) { + command.push("-i"); + command.push(vid); + } + // let command = ["-i", "example.mp4"]; - // const audioFilters = $filters.filter(f => f.type[0] === "A").map(makeFilterArgs); - // const videoFilters = $filters.filter(f => f.type[0] === "V").map(makeFilterArgs); + // const audioFilters = $filters.filter(f => f.type[0] === "A").map(makeFilterArgs); + // const videoFilters = $filters.filter(f => f.type[0] === "V").map(makeFilterArgs); const cFilters = $filters.map(makeFilterArgs).join(","); @@ -133,6 +126,8 @@ onMount(async () => { ffmpeg.on("log", ({ message: msg }) => { console.log(msg); + log += msg + "\n"; + logbox.scrollTop = logbox.scrollHeight; // message = msg; }); await ffmpeg.load({ @@ -143,68 +138,192 @@ wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, "application/wasm"), workerURL: await toBlobURL(`${baseURL}/ffmpeg-core.worker.js`, "text/javascript"), }); - console.log(ffmpeg); ffmpegLoaded = true; });
- {message} -
{command}
+
+

FFmpeg Explorer

+

+ A tool to help you explore FFmpeg filters and options. To use: select one or more input videos + (there are currently two options), export and add some filters, and then hit "render" to + preview the output in browser. + Note: this is a work in progress, many things may still be broken! By Sam Lavigne. +

+
+ +
+ +
+ + +
+
+
-

Inputs

+
+

Inputs

+ +
{#each $inputs as inp, index} {/each} - - - {#each $inputs as inp} -

{inp}

- {/each}
-
- -

Filters

- - - - -
- {#each $filters as f, index} -
- -
- {/each} -
+
+

FFmpeg Log

+ +
+ +
+

Output

- - {#if videoValue} -
+ +
+

Filters

+
+
+ +
+
+ {#each $filters as f, index} +
+ +
+ {/each} +
+
diff --git a/src/Filter.svelte b/src/Filter.svelte index 52fb4d4..9b72944 100644 --- a/src/Filter.svelte +++ b/src/Filter.svelte @@ -9,6 +9,7 @@ }; export let index; + let show = false; function remove() { $filters.splice(index, 1); @@ -18,13 +19,16 @@
-
{filter.name}
- +

{filter.name}

+
+ + +
{filter.description}
- {#if filter.params.length > 0} + {#if filter.params && filter.params.length > 0 && show}
{#each filter.params as p}
@@ -41,7 +45,7 @@ {/each} {:else if p.type == "float" || p.type == "double" || p.type == "long" || p.type == "int"} - + {:else} @@ -56,6 +60,12 @@
diff --git a/src/app.css b/src/app.css index 9e16065..6d44166 100644 --- a/src/app.css +++ b/src/app.css @@ -1,13 +1,24 @@ +* { + box-sizing: border-box; +} :root { } a { + color: #000; } a:hover { } body { background-color: #eee; + font: 16px Times, serif; +} +textrea, select, input, button { + font: inherit; +} +video { + width: 100%; } h1 { diff --git a/src/stores.js b/src/stores.js index 86720f2..c6e1556 100644 --- a/src/stores.js +++ b/src/stores.js @@ -1,5 +1,5 @@ import { writable } from 'svelte/store'; -export const inputs = writable(["example.mp4"]); +export const inputs = writable(["punch.mp4"]); export const output = writable("out.mp4"); export const filters = writable([]);