diff --git a/solid-src/src/App.tsx b/solid-src/src/App.tsx index a78912a..29fa15b 100644 --- a/solid-src/src/App.tsx +++ b/solid-src/src/App.tsx @@ -17,12 +17,13 @@ import { playFile, videoFileExtensions, type CodecInfo, + type CodecList, type FFmpegParams, } from "./util/ffmpeg"; import Neutralino from "@neutralinojs/lib"; import H264Options from "./components/H264Options"; import { openFile } from "./util/oshelper"; -import { getTemporaryFilePath } from "./util/path"; +import { getTemporaryFilePath, getVencoderFolder } from "./util/path"; import { generateRandomString } from "./util/string"; import "./css/icons.css"; import BreezeIcon from "./components/BreezeIcon"; @@ -41,6 +42,7 @@ function App() { const [windowFocused, setWindowFocused] = createSignal(true); const [displayedCodecs, setDisplayedCodecs]: Signal = createSignal([] as CodecInfo[]); + const [audioCodecList, setAudioCodecList] = createSignal([] as CodecInfo[]); const [fileList, setFileList] = createSignal([] as string[]); const [selectedClip, setSelectedClip] = createSignal(""); const [outputCommand, setOutputCommand] = createSignal( @@ -56,8 +58,9 @@ function App() { const [globalopts, setGlobalopts] = createSignal(""); const [inputopts, setInputopts] = createSignal(""); const [outputopts, setOutputopts] = createSignal(""); + const [audioCodec, setAudioCodec] = createSignal("copy"); const logs: { [id: number]: string[] } = {}; - let supportedCodecs: CodecInfo[] = []; + let supportedCodecs: CodecList = { vcodecs: [], acodecs: [] }; let ffmpegParams: FFmpegParams = { vcodec: "", useropts: { @@ -127,6 +130,7 @@ function App() { supportedCodecs = await getAvailableCodecs(); filterDisplayedCodecs(); + setAudioCodecList(supportedCodecs.acodecs); const firstCodec = displayedCodecs()[0]; @@ -180,12 +184,14 @@ function App() { function filterDisplayedCodecs() { if (showCommonCodecs()) { setDisplayedCodecs( - supportedCodecs.filter((v) => commonCodecs.has(v.shortName)), + supportedCodecs.vcodecs.filter((v) => + commonCodecs.has(v.shortName), + ), ); return; } - setDisplayedCodecs(supportedCodecs); + setDisplayedCodecs(supportedCodecs.vcodecs); } function showCommonCodecsChanged(e: InputEvent) { @@ -248,7 +254,7 @@ function App() { ffmpegParams = { vcodec: selectedCodec()?.shortName ?? "", encoder, - acodec: ffmpegParams.acodec, + acodec: audioCodec(), abitrate: ffmpegParams.abitrate, crf: ffmpegParams.crf, doNotUseAn: ffmpegParams.doNotUseAn, @@ -282,14 +288,7 @@ function App() { ? videoFileExtensions[selectedCodec()?.shortName ?? ""] : customExt; - switch (window.NL_OS) { - case "Linux": - ffmpegParams.outputFile = `${await Neutralino.os.getEnv("HOME")}/Vencoder/${fileName}.${fileExt}`; - break; - case "Windows": - ffmpegParams.outputFile = `${await Neutralino.os.getEnv("HOMEPATH")}\\Vencoder\\${fileName}.${fileExt}`; - break; - } + ffmpegParams.outputFile = `${await getVencoderFolder()}${fileName}.${fileExt}`; const outputDir = ( await Neutralino.filesystem.getPathParts( @@ -401,289 +400,256 @@ function App() { } return ( -
-
-
-
-
+
+
+
Vencoder
+
+
+
    + + {(item, _) => ( +
  • setSelectedClip(item)} + > + {item} +
  • + )} +
    +
+
+ + +
-
+ + - - - - -
-
-
-
-
+ +
-
-
-
e.preventDefault()} - > - - -
-
- - -
- - - setCustomFileExt(e.target.value) - } - placeholder="Leave blank to guess from codec" - /> - - - - -
-
}> - - - - - - - - - - -
-

- Extra Arguments -

-
-
e.preventDefault()} - > - - { - ffmpegParams.useropts.global = - e.target.value; - setGlobalopts(e.target.value); - }} - /> - - { - ffmpegParams.useropts.input = - e.target.value; - setInputopts(e.target.value); - }} - /> - - { - ffmpegParams.useropts.output = - e.target.value; - setOutputopts(e.target.value); - }} - /> -
-
-
- -
-                                    {outputCommand()}
-                                
-
-
-
- - -
+ +
+
+
+
Conversion Settings
+
+
+
+
e.preventDefault()} + > + + +
+
+ + +
+ + + setCustomFileExt(e.target.value) + } + placeholder="Leave blank to guess from codec" + /> + + + + +
+
}> + + + + + + + + + + +
+

Audio

+
+
+ + +
+
+

+ Extra Arguments +

+
+
e.preventDefault()} + > + + { + ffmpegParams.useropts.global = + e.target.value; + setGlobalopts(e.target.value); + }} + /> + + { + ffmpegParams.useropts.input = + e.target.value; + setInputopts(e.target.value); + }} + /> + + { + ffmpegParams.useropts.output = + e.target.value; + setOutputopts(e.target.value); + }} + /> +
+
+
+
+
+ +
+                            {outputCommand()}
+                        
+
+
+ + +
+
+
); } diff --git a/solid-src/src/css/index.css b/solid-src/src/css/index.css index 2d254f6..f1bbe9b 100644 --- a/solid-src/src/css/index.css +++ b/solid-src/src/css/index.css @@ -92,3 +92,13 @@ h2 { gap: var(--k-medium-spacing); align-items: center; } + +.page-content { + display: flex; + flex-direction: column; + flex: 1; + padding: var(--k-grid-unit) var(--k-small-spacing); + overflow-x: hidden; + overflow-y: auto; + max-height: 90vh; +} diff --git a/solid-src/src/pages/ProgressPage.tsx b/solid-src/src/pages/ProgressPage.tsx index e857027..b3162b4 100644 --- a/solid-src/src/pages/ProgressPage.tsx +++ b/solid-src/src/pages/ProgressPage.tsx @@ -1,3 +1,4 @@ +import { getVencoderFolder } from "@/util/path"; import { events, os, storage } from "@neutralinojs/lib"; import { createSignal, onMount, onCleanup, Show, Index } from "solid-js"; @@ -131,6 +132,14 @@ function ProgressPage() { setFinished(true); } + async function openFolder() { + const folder = await getVencoderFolder(); + + if (folder) { + os.open(folder); + } + } + return (
@@ -182,20 +191,24 @@ function ProgressPage() { )}
- -
+ + Cancel + + } > - -
-
+ +
); diff --git a/solid-src/src/util/ffmpeg.ts b/solid-src/src/util/ffmpeg.ts index ff1175b..ab74b59 100644 --- a/solid-src/src/util/ffmpeg.ts +++ b/solid-src/src/util/ffmpeg.ts @@ -7,24 +7,27 @@ export interface CodecInfo { encoders: string[]; } -export async function getAvailableCodecs(): Promise { +export type CodecList = { + vcodecs: CodecInfo[], + acodecs: CodecInfo[] +} + +export async function getAvailableCodecs(): Promise { const seperator = "-------"; - const videoEncodingSupported = /.EV.../; const wideFormattingSpaces = / {2,}/; const decodeEncodeSpecification = / \(((decoders)|(encoders)):.+\)/g; const result = await Neutralino.os.execCommand("ffmpeg -codecs"); const rawCodecList = result.stdOut .substring(result.stdOut.indexOf(seperator) + seperator.length) .split("\n"); - let codecs = []; + let vcodecs = []; + let acodecs = []; for (let codec of rawCodecList) { codec = codec.trim(); const flags = codec.substring(0, 6); - if (!videoEncodingSupported.test(flags)) { - continue; - } + if (flags[1] !== "E") continue; const nameAndDescription = codec .substring(7) @@ -48,15 +51,27 @@ export async function getAvailableCodecs(): Promise { .split(" "); } - codecs.push({ - flags, - shortName, - description, - encoders, - }); + if (flags[2] === "V") { + vcodecs.push({ + flags, + shortName, + description, + encoders, + }); + } else if (flags[2] === "A") { + acodecs.push({ + flags, + shortName, + description, + encoders, + }); + } } - return codecs; + return { + vcodecs, + acodecs + }; } export function playFile(path: string) { diff --git a/solid-src/src/util/path.ts b/solid-src/src/util/path.ts index 22a275a..47486ab 100644 --- a/solid-src/src/util/path.ts +++ b/solid-src/src/util/path.ts @@ -1,3 +1,5 @@ +import Neutralino from "@neutralinojs/lib"; + export function getTemporaryFilePath() { switch (window.NL_OS) { case "Windows": @@ -8,3 +10,12 @@ export function getTemporaryFilePath() { return "."; } } + +export async function getVencoderFolder() { + switch (window.NL_OS) { + case "Linux": + return `${await Neutralino.os.getEnv("HOME")}/Vencoder/`; + case "Windows": + return `${await Neutralino.os.getEnv("HOMEPATH")}\\Vencoder\\`; + } +}