feat: add audios table and ElevenLabs TTS endpoint
- New audios table with voice params, S3 link, alignment JSON - POST /api/audios/generate calls ElevenLabs with-timestamps, uploads to S3 - GET/PATCH/DELETE /api/audios endpoints - Requires ELEVENLABS_API_KEY env var Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -494,6 +494,62 @@ async function migrate() {
|
||||
AND bbox_x IS NULL
|
||||
`).catch(() => {});
|
||||
|
||||
// user_pair_progress
|
||||
await query(`
|
||||
CREATE TABLE IF NOT EXISTS user_pair_progress (
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
pair_id UUID NOT NULL REFERENCES pairs(id) ON DELETE CASCADE,
|
||||
seen_count INTEGER NOT NULL DEFAULT 1,
|
||||
correct_count INTEGER NOT NULL DEFAULT 0,
|
||||
wrong_count INTEGER NOT NULL DEFAULT 0,
|
||||
last_seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
PRIMARY KEY (user_id, pair_id)
|
||||
)
|
||||
`);
|
||||
|
||||
await query(`
|
||||
CREATE OR REPLACE FUNCTION update_last_seen_at()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN NEW.last_seen_at = NOW(); RETURN NEW; END;
|
||||
$$ LANGUAGE plpgsql
|
||||
`);
|
||||
|
||||
await query(`
|
||||
DROP TRIGGER IF EXISTS user_pair_progress_last_seen_at ON user_pair_progress;
|
||||
CREATE TRIGGER user_pair_progress_last_seen_at
|
||||
BEFORE UPDATE ON user_pair_progress
|
||||
FOR EACH ROW EXECUTE FUNCTION update_last_seen_at()
|
||||
`);
|
||||
|
||||
// audios
|
||||
await query(`
|
||||
CREATE TABLE IF NOT EXISTS audios (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'generated'
|
||||
CHECK (status IN ('generated', 'published', 'blocked')),
|
||||
text TEXT,
|
||||
audio_link TEXT,
|
||||
alignment JSONB,
|
||||
voice_id TEXT,
|
||||
model_id TEXT,
|
||||
speed NUMERIC(4,2),
|
||||
stability NUMERIC(4,2),
|
||||
similarity_boost NUMERIC(4,2),
|
||||
style NUMERIC(4,2),
|
||||
published_at TIMESTAMPTZ,
|
||||
blocked_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
)
|
||||
`);
|
||||
|
||||
await query(`
|
||||
DROP TRIGGER IF EXISTS audios_updated_at ON audios;
|
||||
CREATE TRIGGER audios_updated_at
|
||||
BEFORE UPDATE ON audios
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at()
|
||||
`);
|
||||
|
||||
// ── Migrate old {{uuid}} placeholders → new {{label.w:uuid}} / {{label.o:uuid}} ──
|
||||
await migratePlaceholders();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user