1 Commits

Author SHA1 Message Date
linesofcodes 37568aa0d1 Pixel Format & Audio Encoder fix
Build / build (push) Successful in 1m14s
2025-09-22 00:24:52 +07:00
2 changed files with 69 additions and 3 deletions
+36 -2
View File
@@ -14,6 +14,7 @@ import {
generateOutputCommand, generateOutputCommand,
getAvailableCodecs, getAvailableCodecs,
getLengthMicroseconds, getLengthMicroseconds,
getPixelFormats,
playFile, playFile,
videoFileExtensions, videoFileExtensions,
type CodecInfo, type CodecInfo,
@@ -60,6 +61,8 @@ function App() {
const [outputopts, setOutputopts] = createSignal(""); const [outputopts, setOutputopts] = createSignal("");
const [audioCodec, setAudioCodec] = createSignal("copy"); const [audioCodec, setAudioCodec] = createSignal("copy");
const [audioEncoder, setAudioEncoder] = createSignal(""); const [audioEncoder, setAudioEncoder] = createSignal("");
const [pixelFormatList, setPixelFormatList] = createSignal([] as string[]);
const [pixelFormat, setPixelFormat] = createSignal("");
const logs: { [id: number]: string[] } = {}; const logs: { [id: number]: string[] } = {};
let supportedCodecs: CodecList = { vcodecs: [], acodecs: [] }; let supportedCodecs: CodecList = { vcodecs: [], acodecs: [] };
let ffmpegParams: FFmpegParams = { let ffmpegParams: FFmpegParams = {
@@ -139,6 +142,8 @@ function App() {
ffmpegParams.encoder = firstCodec.encoders[0]; ffmpegParams.encoder = firstCodec.encoders[0];
setSelectedCodec(firstCodec); setSelectedCodec(firstCodec);
setSelectedEncoder(firstCodec.encoders[0]); setSelectedEncoder(firstCodec.encoders[0]);
setPixelFormatList(await getPixelFormats());
}); });
onCleanup(() => { onCleanup(() => {
@@ -231,7 +236,7 @@ function App() {
function getAudioEncoders() { function getAudioEncoders() {
const codec = audioCodec(); const codec = audioCodec();
const encoders = audioCodecList().find( let encoders = audioCodecList().find(
(v) => v.shortName === codec, (v) => v.shortName === codec,
)?.encoders; )?.encoders;
@@ -239,6 +244,10 @@ function App() {
setAudioEncoder(encoders[0]); setAudioEncoder(encoders[0]);
} }
if (encoders instanceof Array && encoders.length === 0) {
encoders = undefined;
}
return encoders; return encoders;
} }
@@ -265,10 +274,18 @@ function App() {
encoder = undefined; encoder = undefined;
} }
let acodec = audioEncoder();
if (acodec === "") {
acodec = audioCodec();
}
const pixFmt = pixelFormat();
ffmpegParams = { ffmpegParams = {
vcodec: selectedCodec()?.shortName ?? "", vcodec: selectedCodec()?.shortName ?? "",
encoder, encoder,
acodec: audioCodec(), acodec,
abitrate: ffmpegParams.abitrate, abitrate: ffmpegParams.abitrate,
crf: ffmpegParams.crf, crf: ffmpegParams.crf,
doNotUseAn: ffmpegParams.doNotUseAn, doNotUseAn: ffmpegParams.doNotUseAn,
@@ -283,6 +300,7 @@ function App() {
input: inputopts(), input: inputopts(),
output: outputopts(), output: outputopts(),
}, },
pixelFormat: pixFmt === "" ? undefined : pixFmt,
}; };
setOutputCommand(generateOutputCommand(ffmpegParams)); setOutputCommand(generateOutputCommand(ffmpegParams));
@@ -542,6 +560,22 @@ function App() {
</For> </For>
</select> </select>
</Show> </Show>
<label for="pixelFormat">Pixel Format</label>
<select
name="pixelFormat"
id="pixelFormat"
class="k-dropdown"
title="This option is here for the people who knows what they're doing. Not all encoders will support every pixel format."
value={pixelFormat()}
oninput={(e) => setPixelFormat(e.target.value)}
>
<option value="">Same as source</option>
<For each={pixelFormatList()}>
{(item, _) => (
<option value={item}>{item}</option>
)}
</For>
</select>
</form> </form>
<Switch fallback={<div></div>}> <Switch fallback={<div></div>}>
<Match <Match
+33 -1
View File
@@ -74,6 +74,28 @@ export async function getAvailableCodecs(): Promise<CodecList> {
}; };
} }
export async function getPixelFormats(): Promise<string[]> {
const seperator = "-----";
const result = await Neutralino.os.execCommand("ffmpeg -pix_fmts");
const rawFormatList = result.stdOut
.substring(result.stdOut.indexOf(seperator) + seperator.length)
.split("\n");
let outputFormats = [];
for (let format of rawFormatList) {
format = format.trim();
const flags = format.substring(0, 5);
if (flags[1] !== "O") continue;
const parts = format.substring(6).split(/ +/);
outputFormats.push(parts[0]);
}
return outputFormats;
}
export function playFile(path: string) { export function playFile(path: string) {
Neutralino.os.execCommand(`ffplay "${path}"`); Neutralino.os.execCommand(`ffplay "${path}"`);
} }
@@ -114,6 +136,7 @@ export interface FFmpegParams {
faststart?: boolean; faststart?: boolean;
doNotUseAn?: boolean; doNotUseAn?: boolean;
speed?: number; speed?: number;
pixelFormat?: string;
/** /**
* Extra parameters defined by users * Extra parameters defined by users
*/ */
@@ -156,8 +179,17 @@ export function generateOutputCommand(params: FFmpegParams) {
globalopts += " " + params.useropts.global; globalopts += " " + params.useropts.global;
} }
if (params.pixelFormat) {
if (params.outputopts === undefined) {
params.outputopts = {};
}
params.outputopts = {
"pix_fmt": params.pixelFormat
};
}
if (params.outputopts !== undefined) { if (params.outputopts !== undefined) {
console.log(params.outputopts);
for (const key of Object.keys(params.outputopts)) { for (const key of Object.keys(params.outputopts)) {
outputopts += ` -${key} ${params.outputopts[key]}`.trimEnd(); outputopts += ` -${key} ${params.outputopts[key]}`.trimEnd();
} }