bundle pytorch model
Some checks failed
ci / build (push) Failing after 0s
ci / Tests & Checks (push) Failing after 1s

This commit is contained in:
CJ_Clippy 2025-07-19 08:13:54 -08:00
parent fad0d49776
commit 381daeeac9
4 changed files with 8 additions and 239 deletions

View File

@ -1,3 +1,5 @@
!dist/vibeui.pt
runs
requirements.txt
venv

View File

@ -19,6 +19,9 @@ RUN apt-get update -y && \
# Install IPFS Kubo
COPY --from=ipfs/kubo:v0.36.0 /usr/local/bin/ipfs /usr/local/bin/ipfs
# Include the vibeui pytorch model
COPY ./dist/vibeui.pt /app/dist/vibeui.pt
# Copy and install dependencies
COPY package.json package-lock.json ./
RUN npm install --ignore-scripts=false --foreground-scripts --verbose

View File

@ -8,7 +8,7 @@ dotenvx.config({ path: ['../../.env.development'] })
const EnvSchema = z.object({
NODE_ENV: z.enum(['development', 'production', 'test']),
VENV: z.string(),
VENV: z.string().default('/app/venv'),
PORT: z.coerce.number().default(3000),
DATABASE_URL: z.string().url(),
ORIGIN: z.string(),

View File

@ -4,51 +4,15 @@ import { withAccelerate } from "@prisma/extension-accelerate";
import { getOrDownloadAsset } from "../utils/cache";
import { env } from "../config/env";
import { getS3Client, uploadFile } from "../utils/s3";
import { nanoid } from "nanoid";
import { existsSync, rmSync } from "node:fs";
import { join, basename, extname } from "node:path";
import { readFile, writeFile, readdir } from 'node:fs/promises';
import yaml from 'js-yaml';
import { getNanoSpawn } from "../utils/nanoSpawn";
import which from "which";
import * as ort from 'onnxruntime-node';
import { inference, loadDataYaml } from "../utils/vibeui";
import { ffprobe } from "../utils/vibeui";
import { inference } from "../utils/vibeui";
import { preparePython } from "../utils/python";
import { generateActions2, buildFunscript } from "../utils/funscripts";
import { buildFunscript } from "../utils/funscripts";
interface Payload {
vodId: string;
}
// interface Detection {
// startFrame: number;
// endFrame: number;
// className: string;
// }
// interface DataYaml {
// path: string;
// train: string;
// val: string;
// names: Record<string, string>;
// }
// interface FunscriptAction {
// at: number;
// pos: number;
// }
// interface Funscript {
// version: string;
// actions: FunscriptAction[];
// }
// interface ClassPositionMap {
// [className: string]: number | 'pattern';
// }
const prisma = new PrismaClient().$extends(withAccelerate());
@ -63,206 +27,6 @@ function assertPayload(payload: any): asserts payload is Payload {
// export async function buildFunscript(
// helpers: Helpers,
// predictionOutput: string,
// videoPath: string
// ): Promise<string> {
// const labelDir = join(predictionOutput, 'labels');
// const yamlPath = join(predictionOutput, 'data.yaml');
// const outputPath = join(process.env.CACHE_ROOT ?? '/tmp', `${nanoid()}.funscript`);
// helpers.logger.info('Starting Funscript generation');
// try {
// const data = await loadDataYaml(join(env.VIBEUI_DIR, 'data.yaml'))
// const classPositionMap = await loadClassPositionMap(data, helpers);
// const { fps, totalFrames } = await loadVideoMetadata(videoPath, helpers);
// const detectionSegments = await processLabelFiles(labelDir, helpers, data);
// const totalDurationMs = Math.floor((totalFrames / fps) * 1000);
// const actions = generateActions2(totalDurationMs, fps, detectionSegments, classPositionMap);
// await writeFunscript(outputPath, actions, helpers);
// return outputPath;
// } catch (error) {
// helpers.logger.error(`Error generating Funscript: ${error instanceof Error ? error.message : 'Unknown error'}`);
// throw error;
// }
// }
// async function loadClassPositionMap(data: DataYaml, helpers: Helpers): Promise<ClassPositionMap> {
// try {
// if (
// !data ||
// typeof data !== 'object' ||
// !('names' in data) ||
// typeof data.names !== 'object' ||
// data.names === null ||
// Object.keys(data.names).length === 0
// ) {
// throw new Error('Invalid data.yaml: "names" field is missing, not an object, or empty');
// }
// const positionMap: ClassPositionMap = {
// ControlledByTipper: 50,
// ControlledByTipperHigh: 80,
// ControlledByTipperLow: 20,
// ControlledByTipperMedium: 50,
// ControlledByTipperUltrahigh: 95,
// Ring1: 30,
// Ring2: 40,
// Ring3: 50,
// Ring4: 60,
// Earthquake: 'pattern',
// Fireworks: 'pattern',
// Pulse: 'pattern',
// Wave: 'pattern',
// Pause: 0,
// RandomTime: 70,
// HighLevel: 80,
// LowLevel: 20,
// MediumLevel: 50,
// UltraHighLevel: 95
// };
// const names = Object.values(data.names);
// for (const name of names) {
// if (typeof name !== 'string' || name.trim() === '') {
// helpers.logger.info(`Skipping invalid class name: ${name}`);
// continue;
// }
// if (!(name in positionMap)) {
// helpers.logger.info(`No position mapping for class "${name}", defaulting to 0`);
// positionMap[name] = 0;
// }
// }
// helpers.logger.info(`Loaded class position map: ${JSON.stringify(positionMap)}`);
// return positionMap;
// } catch (error) {
// helpers.logger.error(`Error loading data.yaml: ${error instanceof Error ? error.message : 'Unknown error'}`);
// throw error;
// }
// }
// function generatePatternPositions(startMs: number, durationMs: number, className: string, fps: number): FunscriptAction[] {
// const actions: FunscriptAction[] = [];
// const frameDurationMs = 1000 / fps;
// const totalFrames = Math.floor(durationMs / frameDurationMs);
// const intervalMs = 100;
// for (let timeMs = 0; timeMs < durationMs; timeMs += intervalMs) {
// const progress = timeMs / durationMs;
// let pos = 0;
// switch (className) {
// case 'Pulse':
// pos = Math.round(50 * Math.sin(progress * 2 * Math.PI));
// break;
// case 'Wave':
// pos = Math.round(50 + 50 * Math.sin(progress * 2 * Math.PI));
// break;
// case 'Fireworks':
// pos = Math.random() > 0.5 ? 80 : 0;
// break;
// case 'Earthquake':
// pos = Math.round(90 * Math.sin(progress * 4 * Math.PI) + (Math.random() - 0.5) * 10);
// pos = Math.max(0, Math.min(90, pos));
// break;
// }
// actions.push({ at: startMs + timeMs, pos });
// }
// return actions;
// }
// async function loadVideoMetadata(videoPath: string, helpers: Helpers) {
// const { fps, frames: totalFrames } = await ffprobe(videoPath);
// helpers.logger.info(`Video metadata: fps=${fps}, frames=${totalFrames}`);
// return { fps, totalFrames };
// }
// async function processLabelFiles(labelDir: string, helpers: Helpers, data: DataYaml): Promise<Detection[]> {
// const labelFiles = (await readdir(labelDir)).filter(file => file.endsWith('.txt'));
// const detections: Map<number, Detection[]> = new Map();
// const names = data.names;
// for (const file of labelFiles) {
// const match = file.match(/(\d+)\.txt$/);
// if (!match) {
// helpers.logger.info(`Skipping invalid filename: ${file}`);
// continue;
// }
// const frameIndex = parseInt(match[1], 10);
// if (isNaN(frameIndex)) {
// helpers.logger.info(`Skipping invalid frame index from filename: ${file}`);
// continue;
// }
// const content = await readFile(join(labelDir, file), 'utf8');
// const lines = content.trim().split('\n');
// const frameDetections: Detection[] = [];
// let maxConfidence = 0;
// let selectedClassIndex = -1;
// for (const line of lines) {
// const parts = line.trim().split(/\s+/);
// if (parts.length < 6) continue;
// const classIndex = parseInt(parts[0], 10);
// const confidence = parseFloat(parts[5]);
// if (isNaN(classIndex) || isNaN(confidence)) continue;
// if (confidence >= 0.7 && confidence > maxConfidence) {
// maxConfidence = confidence;
// selectedClassIndex = classIndex;
// }
// }
// if (maxConfidence > 0) {
// const className = (data.names as Record<string, string>)[selectedClassIndex.toString()];
// if (className) {
// frameDetections.push({ startFrame: frameIndex, endFrame: frameIndex, className });
// }
// }
// if (frameDetections.length > 0) {
// detections.set(frameIndex, frameDetections);
// }
// }
// // Merge overlapping detections into continuous segments
// const detectionSegments: Detection[] = [];
// let currentDetection: Detection | null = null;
// for (const [frameIndex, frameDetections] of detections.entries()) {
// for (const detection of frameDetections) {
// if (!currentDetection || currentDetection.className !== detection.className) {
// if (currentDetection) detectionSegments.push(currentDetection);
// currentDetection = { ...detection, endFrame: frameIndex };
// } else {
// currentDetection.endFrame = frameIndex;
// }
// }
// }
// if (currentDetection) detectionSegments.push(currentDetection);
// return detectionSegments;
// }
// async function writeFunscript(outputPath: string, actions: FunscriptAction[], helpers: Helpers) {
// const funscript: Funscript = { version: '1.0', actions };
// await writeFile(outputPath, JSON.stringify(funscript, null, 2));
// helpers.logger.info(`Funscript generated: ${outputPath} (${actions.length} actions)`);
// }
const createFunscript: Task = async (payload: any, helpers: Helpers) => {
assertPayload(payload);
const { vodId } = payload;