web/ffmpeg: define multithreading support outside of web worker context

there's no navigator.maxTouchPoints in web worker context, so previously there was no way to detect whether safari is running on ipad or not
This commit is contained in:
wukko 2025-06-29 13:45:39 +06:00
parent b2c5c42ae3
commit 0ac42d5b9d
No known key found for this signature in database
GPG Key ID: 3E30B3F26C7B4AA2
5 changed files with 20 additions and 13 deletions

View File

@ -86,7 +86,7 @@ if (browser) {
// enable local processing by default everywhere but android chrome // enable local processing by default everywhere but android chrome
defaultLocalProcessing: !(device.is.android && device.browser.chrome), defaultLocalProcessing: !(device.is.android && device.browser.chrome),
multithreading: !iOS || (iOS && iosVersion >= 18), multithreading: !iOS || iosVersion >= 18,
}; };
device.userAgent = navigator.userAgent; device.userAgent = navigator.userAgent;

View File

@ -5,12 +5,6 @@ import EncodeLibAV from "@imput/libav.js-encode-cli";
import type { FfprobeData } from "fluent-ffmpeg"; import type { FfprobeData } from "fluent-ffmpeg";
import type { FFmpegProgressCallback, FFmpegProgressEvent, FFmpegProgressStatus, RenderParams } from "$lib/types/libav"; import type { FFmpegProgressCallback, FFmpegProgressEvent, FFmpegProgressStatus, RenderParams } from "$lib/types/libav";
const ua = navigator.userAgent.toLowerCase();
const iPhone = ua.includes("iphone os");
const iPad = !iPhone && ua.includes("mac os") && navigator.maxTouchPoints > 0;
const iOS = iPhone || iPad;
const modernIOS = iOS && Number(ua.match(/version\/(\d+)/)?.[1]) >= 18;
export default class LibAVWrapper { export default class LibAVWrapper {
libav: Promise<LibAVInstance> | null; libav: Promise<LibAVInstance> | null;
concurrency: number; concurrency: number;
@ -38,7 +32,6 @@ export default class LibAVWrapper {
this.libav = constructor({ this.libav = constructor({
...options, ...options,
variant: undefined, variant: undefined,
yesthreads: !iOS || modernIOS,
base: '/_libav' base: '/_libav'
}); });
} }

View File

@ -1,4 +1,5 @@
import { get } from "svelte/store"; import { get } from "svelte/store";
import { device } from "$lib/device";
import { queue, itemError } from "$lib/state/task-manager/queue"; import { queue, itemError } from "$lib/state/task-manager/queue";
import { runFFmpegWorker } from "$lib/task-manager/runners/ffmpeg"; import { runFFmpegWorker } from "$lib/task-manager/runners/ffmpeg";
@ -42,6 +43,7 @@ export const startWorker = async ({ worker, workerId, dependsOn, parentId, worke
workerArgs.ffargs, workerArgs.ffargs,
workerArgs.output, workerArgs.output,
worker, worker,
device.supports.multithreading,
/*resetStartCounter=*/true, /*resetStartCounter=*/true,
); );
} else { } else {

View File

@ -16,7 +16,8 @@ export const runFFmpegWorker = async (
args: string[], args: string[],
output: FileInfo, output: FileInfo,
variant: 'remux' | 'encode', variant: 'remux' | 'encode',
resetStartCounter = false yesthreads: boolean,
resetStartCounter = false,
) => { ) => {
const worker = new FFmpegWorker(); const worker = new FFmpegWorker();
@ -34,7 +35,11 @@ export const runFFmpegWorker = async (
startAttempts++; startAttempts++;
if (startAttempts <= 10) { if (startAttempts <= 10) {
killWorker(worker, unsubscribe, startCheck); killWorker(worker, unsubscribe, startCheck);
return await runFFmpegWorker(workerId, parentId, files, args, output, variant); return await runFFmpegWorker(
workerId, parentId,
files, args, output,
variant, yesthreads
);
} else { } else {
killWorker(worker, unsubscribe, startCheck); killWorker(worker, unsubscribe, startCheck);
return itemError(parentId, workerId, "queue.worker_didnt_start"); return itemError(parentId, workerId, "queue.worker_didnt_start");
@ -54,6 +59,7 @@ export const runFFmpegWorker = async (
files, files,
args, args,
output, output,
yesthreads,
} }
}); });

View File

@ -1,7 +1,13 @@
import LibAVWrapper from "$lib/libav"; import LibAVWrapper from "$lib/libav";
import type { FileInfo } from "$lib/types/libav"; import type { FileInfo } from "$lib/types/libav";
const ffmpeg = async (variant: string, files: File[], args: string[], output: FileInfo) => { const ffmpeg = async (
variant: string,
files: File[],
args: string[],
output: FileInfo,
yesthreads: boolean = false,
) => {
if (!(files && output && args)) { if (!(files && output && args)) {
self.postMessage({ self.postMessage({
cobaltFFmpegWorker: { cobaltFFmpegWorker: {
@ -25,7 +31,7 @@ const ffmpeg = async (variant: string, files: File[], args: string[], output: Fi
}) })
}); });
ff.init({ variant }); ff.init({ variant, yesthreads });
const error = (code: string) => { const error = (code: string) => {
self.postMessage({ self.postMessage({
@ -122,6 +128,6 @@ const ffmpeg = async (variant: string, files: File[], args: string[], output: Fi
self.onmessage = async (event: MessageEvent) => { self.onmessage = async (event: MessageEvent) => {
const ed = event.data.cobaltFFmpegWorker; const ed = event.data.cobaltFFmpegWorker;
if (ed?.variant && ed?.files && ed?.args && ed?.output) { if (ed?.variant && ed?.files && ed?.args && ed?.output) {
await ffmpeg(ed.variant, ed.files, ed.args, ed.output); await ffmpeg(ed.variant, ed.files, ed.args, ed.output, ed.yesthreads);
} }
} }