diff options
| author | Maze Winther <mazewinther@gmail.com> | 2026-04-20 11:31:17 +0200 |
|---|---|---|
| committer | Maze Winther <mazewinther@gmail.com> | 2026-04-20 11:31:17 +0200 |
| commit | 3e89d2998588f8e35c524e523ba2ee853f0f6475 (patch) | |
| tree | 57221f96c1259b3b07e3ddf8c1adefc502b9d8eb /apps/web/src/lib/fps/utils.ts | |
| parent | 729d10592f4e802f91c555c309ff3ba4b119f843 (diff) | |
| download | opencut-3e89d2998588f8e35c524e523ba2ee853f0f6475.tar.gz | |
refactor: restructure files to their domains, new preview overlay system, and dep graph
Diffstat (limited to 'apps/web/src/lib/fps/utils.ts')
| -rw-r--r-- | apps/web/src/lib/fps/utils.ts | 95 |
1 files changed, 0 insertions, 95 deletions
diff --git a/apps/web/src/lib/fps/utils.ts b/apps/web/src/lib/fps/utils.ts deleted file mode 100644 index 932788c4..00000000 --- a/apps/web/src/lib/fps/utils.ts +++ /dev/null @@ -1,95 +0,0 @@ -import type { FrameRate } from "opencut-wasm"; -import type { MediaAsset } from "@/lib/media/types"; - -type MediaAssetFpsInput = Pick<MediaAsset, "type" | "fps">; - -const STANDARD_FRAME_RATES: Array<{ value: number; rate: FrameRate }> = [ - { value: 24_000 / 1_001, rate: { numerator: 24_000, denominator: 1_001 } }, - { value: 24, rate: { numerator: 24, denominator: 1 } }, - { value: 25, rate: { numerator: 25, denominator: 1 } }, - { value: 30_000 / 1_001, rate: { numerator: 30_000, denominator: 1_001 } }, - { value: 30, rate: { numerator: 30, denominator: 1 } }, - { value: 48, rate: { numerator: 48, denominator: 1 } }, - { value: 50, rate: { numerator: 50, denominator: 1 } }, - { value: 60_000 / 1_001, rate: { numerator: 60_000, denominator: 1_001 } }, - { value: 60, rate: { numerator: 60, denominator: 1 } }, - { value: 120, rate: { numerator: 120, denominator: 1 } }, -]; - -const STANDARD_FRAME_RATE_TOLERANCE = 0.01; - -export function frameRateToFloat(rate: FrameRate): number { - return rate.numerator / rate.denominator; -} - -export function frameRatesEqual(a: FrameRate, b: FrameRate): boolean { - return a.numerator === b.numerator && a.denominator === b.denominator; -} - -export function floatToFrameRate(fps: number): FrameRate { - const standard = STANDARD_FRAME_RATES.find( - (candidate) => Math.abs(fps - candidate.value) <= STANDARD_FRAME_RATE_TOLERANCE, - ); - if (standard) return standard.rate; - - if (Number.isInteger(fps)) { - return { numerator: fps, denominator: 1 }; - } - - const ARBITRARY_DENOMINATOR = 1_000_000; - const scaledNumerator = Math.round(fps * ARBITRARY_DENOMINATOR); - const divisor = gcd(scaledNumerator, ARBITRARY_DENOMINATOR); - return { - numerator: scaledNumerator / divisor, - denominator: ARBITRARY_DENOMINATOR / divisor, - }; -} - -function gcd(left: number, right: number): number { - let a = Math.abs(left); - let b = Math.abs(right); - while (b !== 0) { - const remainder = a % b; - a = b; - b = remainder; - } - return a || 1; -} - -export function getHighestImportedVideoFps({ - mediaAssets, -}: { - mediaAssets: MediaAssetFpsInput[]; -}): number | null { - let highestFps: number | null = null; - - for (const asset of mediaAssets) { - const fps = asset.fps ?? Number.NaN; - if (asset.type !== "video") continue; - if (!Number.isFinite(fps) || fps <= 0) continue; - - highestFps = highestFps === null ? fps : Math.max(highestFps, fps); - } - - return highestFps; -} - -export function getRaisedProjectFpsForImportedMedia({ - currentFps, - importedAssets, -}: { - currentFps: FrameRate; - importedAssets: MediaAssetFpsInput[]; -}): FrameRate | null { - const highestImportedVideoFps = getHighestImportedVideoFps({ - mediaAssets: importedAssets, - }); - - const currentFpsFloat = frameRateToFloat(currentFps); - - if (highestImportedVideoFps === null || highestImportedVideoFps <= currentFpsFloat) { - return null; - } - - return floatToFrameRate(highestImportedVideoFps); -} |
