From 0ac42d5b9d0aacae3ed37ac023289edfe72b1258 Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 29 Jun 2025 13:45:39 +0600 Subject: [PATCH] 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 --- web/src/lib/device.ts | 2 +- web/src/lib/libav.ts | 7 ------- web/src/lib/task-manager/run-worker.ts | 2 ++ web/src/lib/task-manager/runners/ffmpeg.ts | 10 ++++++++-- web/src/lib/task-manager/workers/ffmpeg.ts | 12 +++++++++--- 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/web/src/lib/device.ts b/web/src/lib/device.ts index ad927c28..2b8dc894 100644 --- a/web/src/lib/device.ts +++ b/web/src/lib/device.ts @@ -86,7 +86,7 @@ if (browser) { // enable local processing by default everywhere but android chrome defaultLocalProcessing: !(device.is.android && device.browser.chrome), - multithreading: !iOS || (iOS && iosVersion >= 18), + multithreading: !iOS || iosVersion >= 18, }; device.userAgent = navigator.userAgent; diff --git a/web/src/lib/libav.ts b/web/src/lib/libav.ts index 598000f2..6c154022 100644 --- a/web/src/lib/libav.ts +++ b/web/src/lib/libav.ts @@ -5,12 +5,6 @@ import EncodeLibAV from "@imput/libav.js-encode-cli"; import type { FfprobeData } from "fluent-ffmpeg"; 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 { libav: Promise | null; concurrency: number; @@ -38,7 +32,6 @@ export default class LibAVWrapper { this.libav = constructor({ ...options, variant: undefined, - yesthreads: !iOS || modernIOS, base: '/_libav' }); } diff --git a/web/src/lib/task-manager/run-worker.ts b/web/src/lib/task-manager/run-worker.ts index 021fda0d..b9994661 100644 --- a/web/src/lib/task-manager/run-worker.ts +++ b/web/src/lib/task-manager/run-worker.ts @@ -1,4 +1,5 @@ import { get } from "svelte/store"; +import { device } from "$lib/device"; import { queue, itemError } from "$lib/state/task-manager/queue"; import { runFFmpegWorker } from "$lib/task-manager/runners/ffmpeg"; @@ -42,6 +43,7 @@ export const startWorker = async ({ worker, workerId, dependsOn, parentId, worke workerArgs.ffargs, workerArgs.output, worker, + device.supports.multithreading, /*resetStartCounter=*/true, ); } else { diff --git a/web/src/lib/task-manager/runners/ffmpeg.ts b/web/src/lib/task-manager/runners/ffmpeg.ts index 43d75cbe..0a83f3fb 100644 --- a/web/src/lib/task-manager/runners/ffmpeg.ts +++ b/web/src/lib/task-manager/runners/ffmpeg.ts @@ -16,7 +16,8 @@ export const runFFmpegWorker = async ( args: string[], output: FileInfo, variant: 'remux' | 'encode', - resetStartCounter = false + yesthreads: boolean, + resetStartCounter = false, ) => { const worker = new FFmpegWorker(); @@ -34,7 +35,11 @@ export const runFFmpegWorker = async ( startAttempts++; if (startAttempts <= 10) { killWorker(worker, unsubscribe, startCheck); - return await runFFmpegWorker(workerId, parentId, files, args, output, variant); + return await runFFmpegWorker( + workerId, parentId, + files, args, output, + variant, yesthreads + ); } else { killWorker(worker, unsubscribe, startCheck); return itemError(parentId, workerId, "queue.worker_didnt_start"); @@ -54,6 +59,7 @@ export const runFFmpegWorker = async ( files, args, output, + yesthreads, } }); diff --git a/web/src/lib/task-manager/workers/ffmpeg.ts b/web/src/lib/task-manager/workers/ffmpeg.ts index cfb4868d..7f7577f2 100644 --- a/web/src/lib/task-manager/workers/ffmpeg.ts +++ b/web/src/lib/task-manager/workers/ffmpeg.ts @@ -1,7 +1,13 @@ import LibAVWrapper from "$lib/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)) { self.postMessage({ 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) => { self.postMessage({ @@ -122,6 +128,6 @@ const ffmpeg = async (variant: string, files: File[], args: string[], output: Fi self.onmessage = async (event: MessageEvent) => { const ed = event.data.cobaltFFmpegWorker; 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); } }