Spaces:
Running
Running
| import { Transcript } from "common-utils"; | |
| import _ from "lodash"; | |
| import { random, staticFile, useCurrentFrame } from "remotion"; | |
| import { DisplayMedia } from "./ig-reel/IGSimpleScene"; | |
| function levenshteinDistance(str1: string, str2: string) { | |
| const dp = Array.from({ length: str1.length + 1 }, (_, i) => [i]); | |
| for (let j = 1; j <= str2.length; j++) { | |
| dp[0][j] = j; | |
| } | |
| for (let i = 1; i <= str1.length; i++) { | |
| for (let j = 1; j <= str2.length; j++) { | |
| const cost = str1[i - 1] === str2[j - 1] ? 0 : 1; | |
| dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost); | |
| } | |
| } | |
| return dp[str1.length][str2.length]; | |
| } | |
| export class RenderUtils { | |
| public static calculateDisplayMedia( | |
| item: Transcript, | |
| durationInSeconds: number, | |
| frame: number, | |
| fps: number) { | |
| let currentDisplayMedia: DisplayMedia = (item?.mediaAbsPaths as any || [])[0] | |
| if (!_.isEmpty(item?.mediaAbsPaths)) { | |
| let frameOffest = 0 | |
| for (let i = 0; i < item?.mediaAbsPaths.length; i++) { | |
| const media: DisplayMedia = item.mediaAbsPaths[i] as any; | |
| if (!media) { | |
| return undefined | |
| } | |
| media.idx = i | |
| media.startFrame = frameOffest | |
| if (media.durationSec == undefined) { | |
| media.durationSec = durationInSeconds / (item?.mediaAbsPaths.length) | |
| if (i == item.mediaAbsPaths.length - 1) { | |
| media.durationSec = durationInSeconds | |
| } | |
| } | |
| media.durationFrames = media.durationSec * fps | |
| media.endFrame = frameOffest + media.durationFrames | |
| frameOffest = frameOffest + media.durationFrames | |
| if (frame > media.startFrame && frame < media.endFrame) { | |
| currentDisplayMedia = media | |
| } | |
| } | |
| } | |
| return currentDisplayMedia | |
| } | |
| public static tryStaticFile(file: string) { | |
| try { | |
| return staticFile(file); | |
| } catch (e) { | |
| let fileName = RenderUtils.getFileName(file) | |
| return staticFile(fileName!!); | |
| } | |
| } | |
| public static convertVHToPixels(vh: string) { | |
| return Math.round(window.innerHeight * (parseInt(vh.replace("vh", "")) / 100)); | |
| } | |
| public static convertVWToPixels(vw: string) { | |
| return Math.round(window.innerWidth * (parseInt(vw.replace("vw", "")) / 100)); | |
| } | |
| public static splitWordsIntoGroups(words: any) { | |
| const groups = []; | |
| let currentGroup = []; | |
| for (const word of words) { | |
| if (currentGroup.length === 0) { | |
| currentGroup.push(word); | |
| } else if (word.sentence_end) { | |
| currentGroup.push(word); | |
| groups.push(currentGroup); | |
| currentGroup = []; | |
| } else if (currentGroup.length < 5) { | |
| currentGroup.push(word); | |
| } else { | |
| groups.push(currentGroup); | |
| currentGroup = [word]; | |
| } | |
| } | |
| if (currentGroup.length > 0) { | |
| groups.push(currentGroup); | |
| } | |
| // Ensure each group has a maximum of 5 words | |
| const finalGroups = []; | |
| for (const group of groups) { | |
| while (group.length > 5) { | |
| finalGroups.push(group.slice(0, 5)); | |
| group.splice(0, 5); | |
| } | |
| finalGroups.push(group); | |
| } | |
| return finalGroups?.map(group => { | |
| return { | |
| words: group, | |
| start: undefined, | |
| end: undefined | |
| } | |
| }); | |
| } | |
| public static findCurrentGroupByTime(timeSec: Number, groups: any[]) { | |
| var t = timeSec; | |
| let wds = groups | |
| for (let i = 0; i < wds.length; i++) { | |
| const x: any = wds[i]; | |
| if (x.start != undefined && x.end != undefined && (t >= x.start && t < x.end)) { | |
| return x | |
| } | |
| } | |
| } | |
| public static findCurrentWord(timeSec: Number, frames: any[]) { | |
| var t = timeSec; | |
| let wds = frames | |
| for (let i = 0; i < wds.length; i++) { | |
| const x = wds[i]; | |
| if (x.start && x.end && (t >= x.start && t < x.end)) { | |
| return x | |
| } | |
| } | |
| } | |
| public static randomElement<T>(arr: T[], seed: string): T { | |
| return arr[Math.floor(random(seed || 1) * arr.length)]; | |
| } | |
| public static hashCode(s: string) { | |
| return s.split("").reduce(function (a: number, b: string) { | |
| a = ((a << 5) - a) + b.charCodeAt(0); | |
| return a & a; | |
| }, 0); | |
| } | |
| public static splitArrayIntoChunks(arr: string | any[], chunkSize: number) { | |
| const chunkedArr = []; | |
| for (let i = 0; i < arr.length; i += chunkSize) { | |
| chunkedArr.push(arr.slice(i, i + chunkSize)); | |
| } | |
| return chunkedArr; | |
| } | |
| public static splitArray(arr: string | any[], pieces: number) { | |
| let result = []; | |
| let chunkSize = Math.ceil(arr.length / pieces); | |
| for (let i = 0, j = arr.length; i < j; i += chunkSize) { | |
| result.push(arr.slice(i, i + chunkSize)); | |
| } | |
| return result; | |
| } | |
| public static getFileName(filePath: string, subdirpath?: string): string | undefined { | |
| if (!filePath) | |
| return undefined; | |
| if (filePath.startsWith("http")) | |
| return filePath; | |
| // Always extract just the filename from any path | |
| const match = filePath.match(/([^\/\\]+)$/); | |
| let filename = match ? match[1] : ''; | |
| if (subdirpath) { | |
| return subdirpath + "/" + filename; | |
| } else { | |
| return filename; | |
| } | |
| } | |
| public static findMostSimilarString(inputString: string, stringArray: string[]) { | |
| let minDistance = Number.MAX_SAFE_INTEGER; | |
| let mostSimilarString = ''; | |
| stringArray.forEach((str) => { | |
| const distance = levenshteinDistance(inputString, str); | |
| if (distance < minDistance) { | |
| minDistance = distance; | |
| mostSimilarString = str; | |
| } | |
| }); | |
| return mostSimilarString; | |
| } | |
| } |