feat(ffmpeg): add wav-3cx telephony preset and URL-param format pre-selection

WAV preset for 3CX / telephony systems
---------------------------------------
Adds `wav-3cx` as a new FFmpeg output target that produces a WAV file
with the parameters required by 3CX and similar telephony platforms:
  - Channel: mono   (-ac 1)
  - Sample rate: 8 kHz  (-ar 8000)
  - Bit depth: 16-bit PCM  (-sample_fmt s16)

The target appears in the UI alongside the regular `wav` option under the
ffmpeg converter group.  `normalizeOutputFiletype` maps `wav-3cx` → `wav`
so the downloaded file has the correct `.wav` extension.

URL query-param pre-selection
------------------------------
Adds support for `?to=<format>&converter=<name>` query parameters on the
root page.  When a user lands on the page with these params set, the
format selector is automatically pre-populated as soon as conversion
options finish loading (after the first file is selected).

Example:
  http://localhost:3000/?to=wav-3cx&converter=ffmpeg

Closes #559

Signed-off-by: Radhakrishnan Pachyappan <gingeekrishna@gmail.com>
This commit is contained in:
Radhakrishnan Pachyappan 2026-06-22 00:08:08 +05:30
parent 0965928949
commit 17a683186d
3 changed files with 29 additions and 0 deletions

View file

@ -7,6 +7,10 @@ let fileType;
let pendingFiles = 0;
let formatSelected = false;
const urlParams = new URLSearchParams(window.location.search);
const defaultTo = urlParams.get("to");
const defaultConverter = urlParams.get("converter");
dropZone.addEventListener("dragover", (e) => {
e.preventDefault();
dropZone.classList.add("dragover");
@ -59,6 +63,23 @@ function handleFile(file) {
.then((html) => {
selectContainer.innerHTML = html;
updateSearchBar();
if (defaultTo) {
const selector = defaultConverter
? `.target[data-value="${defaultTo},${defaultConverter}"]`
: `.target[data-target="${defaultTo}"]`;
const targetBtn = document.querySelector(selector);
if (targetBtn) {
const convertToEl = document.querySelector("select[name='convert_to']");
const convertToInputEl = document.querySelector("input[name='convert_to_search']");
convertToEl.value = targetBtn.dataset.value;
convertToInputEl.value = `${targetBtn.dataset.target} using ${targetBtn.dataset.converter}`;
formatSelected = true;
if (pendingFiles === 0 && fileNames.length > 0) {
convertButton.disabled = false;
}
}
}
})
.catch(console.error);
}

View file

@ -670,6 +670,7 @@ export const properties = {
"vvc",
"w64",
"wav",
"wav-3cx",
"wbmp",
"webm",
"webp",
@ -708,6 +709,11 @@ export async function convert(
message = "Done: resized to 256x256";
}
if (convertTo === "wav-3cx") {
// 3CX telephony preset: mono, 8 kHz, 16-bit PCM
extraArgs.push("-ac", "1", "-ar", "8000", "-sample_fmt", "s16");
}
if (convertTo.split(".").length > 1) {
// Support av1.mkv and av1.mp4 and h265.mp4 etc.
const split = convertTo.split(".");

View file

@ -49,6 +49,8 @@ export const normalizeOutputFiletype = (filetype: string): string => {
return "fbx";
case "assjson":
return "json";
case "wav-3cx":
return "wav";
default:
return lowercaseFiletype;
}