feat: analysis providers, settings UI, song search, WAV duration fix
- Multi-provider AI analysis (Anthropic, OpenAI, Ollama, Algorithmic) - server-only guards on all provider files; client bundle fix - /settings page with provider status, Ollama model picker, preferences - Song search box on /analyze replacing raw MBID input (debounced, keyboard nav) - Auto-register song via MusicBrainz on POST /api/tracks (no more 404) - Fix WAV duration bug: last section songEnd was double-counting elapsed time - Registry sync comment updated for self-hosted HTTPS git servers Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { z } from "zod";
|
||||
import { getTempoMapsForSong, insertTempoMap, query } from "@/lib/db/client";
|
||||
import { getTempoMapsForSong, getSongByMbid, insertTempoMap, upsertSong } from "@/lib/db/client";
|
||||
import { validateCTP } from "@/lib/ctp/validate";
|
||||
import { lookupRecording, formatArtistCredit, mbDurationToSeconds } from "@/lib/musicbrainz/client";
|
||||
|
||||
// ─── GET /api/tracks?mbid=<uuid> ─────────────────────────────────────────────
|
||||
|
||||
@@ -55,19 +56,33 @@ export async function POST(req: NextRequest) {
|
||||
);
|
||||
}
|
||||
|
||||
// Ensure the song exists
|
||||
const { rowCount } = await query("SELECT 1 FROM songs WHERE mbid = $1", [
|
||||
doc.metadata.mbid,
|
||||
]);
|
||||
// Ensure the song exists — auto-register it if not
|
||||
const existing = await getSongByMbid(doc.metadata.mbid);
|
||||
|
||||
if (!rowCount || rowCount === 0) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: "Song not found. Search for the song first to register it.",
|
||||
if (!existing) {
|
||||
try {
|
||||
const rec = await lookupRecording(doc.metadata.mbid);
|
||||
await upsertSong({
|
||||
mbid: doc.metadata.mbid,
|
||||
},
|
||||
{ status: 404 }
|
||||
);
|
||||
title: rec.title,
|
||||
artist: formatArtistCredit(rec["artist-credit"]),
|
||||
duration_seconds: mbDurationToSeconds(rec.length),
|
||||
acousticbrainz_bpm: null,
|
||||
acousticbrainz_time_sig_num: null,
|
||||
source: "musicbrainz",
|
||||
});
|
||||
} catch {
|
||||
// MusicBrainz unreachable — fall back to CTP metadata
|
||||
await upsertSong({
|
||||
mbid: doc.metadata.mbid,
|
||||
title: doc.metadata.title,
|
||||
artist: doc.metadata.artist,
|
||||
duration_seconds: doc.metadata.duration_seconds,
|
||||
acousticbrainz_bpm: null,
|
||||
acousticbrainz_time_sig_num: null,
|
||||
source: "manual",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const map = await insertTempoMap({
|
||||
|
||||
Reference in New Issue
Block a user