/** * Auto-import test samples on startup * * Checks for test continuation samples in data/test_ai_continuations/ * and imports any that aren't already in the database. * Also imports pre-analyzed results if available. */ import fs from "fs/promises"; import path from "path"; import * as db from "./db"; import { saveTrackFile } from "./localStorage"; const TEST_SAMPLES_DIR = path.join(process.cwd(), "data/test_ai_continuations"); const MANIFEST_FILE = path.join(TEST_SAMPLES_DIR, "manifest.json"); const RESULTS_FILE = path.join(TEST_SAMPLES_DIR, "preanalyzed_results.json"); // Demo user ID (used when no real users exist) const DEMO_USER_ID = 1; interface ManifestSample { continuation_file: string; source_title: string; source_artist: string; source_track_id: string; total_duration_sec?: number; } interface Manifest { samples: ManifestSample[]; } interface ChunkMatch { trackId: string; title: string; artist: string; similarity: number; matchType: "exact" | "style"; } interface ChunkResult { chunkIndex: number; startTime: number; endTime: number; matches: ChunkMatch[]; } interface PreanalyzedResult { filename: string; sourceTrackId: string; sourceTitle: string; sourceArtist: string; duration: number; chunks: ChunkResult[]; } interface PreanalyzedResults { results: PreanalyzedResult[]; } export async function importTestSamples(): Promise { try { // Check if test samples directory exists try { await fs.access(TEST_SAMPLES_DIR); } catch { console.log("[ImportTestSamples] No test samples directory found, skipping"); return; } // Check if manifest exists try { await fs.access(MANIFEST_FILE); } catch { console.log("[ImportTestSamples] No manifest.json found, skipping"); return; } // Load manifest const manifestData = await fs.readFile(MANIFEST_FILE, "utf-8"); const manifest: Manifest = JSON.parse(manifestData); if (!manifest.samples || manifest.samples.length === 0) { console.log("[ImportTestSamples] No samples in manifest"); return; } // Load pre-analyzed results if available let preanalyzed: PreanalyzedResults | null = null; try { const resultsData = await fs.readFile(RESULTS_FILE, "utf-8"); preanalyzed = JSON.parse(resultsData); console.log(`[ImportTestSamples] Found ${preanalyzed?.results?.length || 0} pre-analyzed results`); } catch { console.log("[ImportTestSamples] No pre-analyzed results found"); } // Create lookup map for pre-analyzed results const resultsMap = new Map(); if (preanalyzed?.results) { for (const result of preanalyzed.results) { resultsMap.set(result.filename, result); } } console.log(`[ImportTestSamples] Found ${manifest.samples.length} test samples`); // Get existing tracks to avoid duplicates const existingTracks = await db.getUserTracks(DEMO_USER_ID); const existingTitles = new Set(existingTracks.map(t => t.title)); let imported = 0; let resultsImported = 0; for (const sample of manifest.samples) { const title = `[TEST] ${sample.source_title}`; // Skip if already imported if (existingTitles.has(title)) { continue; } const filePath = path.join(TEST_SAMPLES_DIR, sample.continuation_file); // Check if file exists try { await fs.access(filePath); } catch { console.log(`[ImportTestSamples] File not found: ${sample.continuation_file}`); continue; } // Check if we have pre-analyzed results for this sample const preResult = resultsMap.get(sample.continuation_file); const hasResults = !!preResult; // Read file const fileData = await fs.readFile(filePath); // Save to uploads const { fileKey, fileUrl } = await saveTrackFile( DEMO_USER_ID, sample.continuation_file, fileData ); // Create track record // Set to "completed" if we have pre-analyzed results, otherwise "pending" const trackId = await db.createTrack({ userId: DEMO_USER_ID, title, artist: sample.source_artist, trackType: "ai_generated", fileKey, fileUrl, fileSize: fileData.length, mimeType: "audio/wav", duration: preResult?.duration || sample.total_duration_sec || null, status: hasResults ? "completed" : "pending", }); // Import pre-analyzed attribution results if (preResult && trackId) { for (const chunk of preResult.chunks) { for (const match of chunk.matches) { // Use method based on matchType for consistency with live analysis const isExact = match.matchType === "exact"; await db.createAttributionResult({ aiTrackId: trackId, aiStemId: null, trainingTrackId: 0, // Not linked to DB track, just for display trainingStemId: null, method: isExact ? "mert_exact" : "style", score: match.similarity, confidence: match.similarity, metadata: { chunkIndex: chunk.chunkIndex, startTime: chunk.startTime, endTime: chunk.endTime, matchedTrackId: match.trackId, matchedTitle: match.title, matchedArtist: match.artist, method: "mert", matchType: match.matchType, }, }); } } resultsImported++; } imported++; console.log(`[ImportTestSamples] Imported: ${title}${hasResults ? " (with results)" : ""}`); } if (imported > 0) { console.log(`[ImportTestSamples] Imported ${imported} test samples (${resultsImported} with pre-analyzed results)`); } else { console.log("[ImportTestSamples] All test samples already imported"); } } catch (error) { console.error("[ImportTestSamples] Error:", error); // Don't throw - this is non-critical startup task } }