www_site/services/api/migrations/002_tts.sql

57 lines
2.5 KiB
SQL

CREATE TABLE IF NOT EXISTS tts_voices (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
provider_voice_id TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
language TEXT,
description TEXT,
enabled BOOLEAN NOT NULL DEFAULT true,
supported_parameters JSONB NOT NULL DEFAULT '{}'::jsonb,
allowed_plans JSONB NOT NULL DEFAULT '["free", "vip"]'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS tts_tasks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
text TEXT NOT NULL,
text_length INTEGER NOT NULL CHECK (text_length > 0),
voice_id UUID REFERENCES tts_voices(id),
provider_voice_id TEXT NOT NULL,
parameters JSONB NOT NULL DEFAULT '{}'::jsonb,
status TEXT NOT NULL DEFAULT 'queued' CHECK (status IN ('queued', 'running', 'succeeded', 'failed')),
provider_task_id TEXT,
idempotency_key TEXT NOT NULL,
request_hash TEXT NOT NULL,
policy_version INTEGER NOT NULL,
quota_account_id UUID NOT NULL REFERENCES quota_accounts(id),
reserved_amount BIGINT NOT NULL CHECK (reserved_amount >= 0),
error_code TEXT,
attempt_count INTEGER NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
started_at TIMESTAMPTZ,
finished_at TIMESTAMPTZ,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
UNIQUE(user_id, idempotency_key)
);
CREATE INDEX IF NOT EXISTS tts_tasks_user_created_idx ON tts_tasks(user_id, created_at DESC);
CREATE INDEX IF NOT EXISTS tts_tasks_queue_idx ON tts_tasks(status, updated_at);
CREATE TABLE IF NOT EXISTS audio_files (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
task_id UUID NOT NULL UNIQUE REFERENCES tts_tasks(id) ON DELETE CASCADE,
owner_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
storage_key TEXT NOT NULL UNIQUE,
mime_type TEXT NOT NULL,
size_bytes BIGINT NOT NULL CHECK (size_bytes >= 0),
checksum TEXT NOT NULL,
duration_ms INTEGER,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
expires_at TIMESTAMPTZ,
status TEXT NOT NULL DEFAULT 'available' CHECK (status IN ('available', 'expired', 'deleted'))
);
INSERT INTO tts_voices(provider_voice_id, name, description, supported_parameters, allowed_plans)
VALUES ('default', 'default', '旧 TTS 工程代码中的默认音色标识', '{"format":["wav","mp3"],"speed":{"min":0.5,"max":2}}'::jsonb, '["free","vip"]'::jsonb)
ON CONFLICT (provider_voice_id) DO NOTHING;