added share function

This commit is contained in:
2026-08-26 09:47:52 +08:00
parent ccd8ec16bb
commit f80da8a5f6
5 changed files with 435 additions and 18 deletions

View File

@@ -3,6 +3,7 @@ import sqlite3
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Dict, List, Optional
import uuid
from .models import SentenceBoundary, SentenceBoundaryDocument
from .store import normalize_video_hash
@@ -67,6 +68,27 @@ class VideoRepository:
created_at TEXT NOT NULL,
FOREIGN KEY (video_hash) REFERENCES videos(video_hash) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS dub_shares (
share_id TEXT PRIMARY KEY,
video_hash TEXT NOT NULL,
title TEXT NOT NULL,
created_at TEXT NOT NULL,
FOREIGN KEY (video_hash) REFERENCES videos(video_hash) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS dub_share_segments (
id INTEGER PRIMARY KEY AUTOINCREMENT,
share_id TEXT NOT NULL,
sentence_index INTEGER NOT NULL,
start_ms INTEGER NOT NULL,
end_ms INTEGER NOT NULL,
text TEXT,
audio_filename TEXT NOT NULL,
audio_size_bytes INTEGER NOT NULL,
FOREIGN KEY (share_id) REFERENCES dub_shares(share_id) ON DELETE CASCADE,
UNIQUE (share_id, sentence_index)
);
"""
)
@@ -266,6 +288,72 @@ class VideoRepository:
reference_speech_duration_ms=row["reference_speech_duration_ms"],
)
def create_dub_share(
self,
*,
video_hash: str,
title: str,
segments: List[Dict[str, Any]],
) -> Optional[Dict[str, Any]]:
normalized_hash = normalize_video_hash(video_hash)
if self.get_video(normalized_hash) is None:
return None
share_id = uuid.uuid4().hex
now = utc_now()
with self._connect() as connection:
connection.execute(
"""
INSERT INTO dub_shares (share_id, video_hash, title, created_at)
VALUES (?, ?, ?, ?)
""",
(share_id, normalized_hash, title[:200], now),
)
connection.executemany(
"""
INSERT INTO dub_share_segments (
share_id, sentence_index, start_ms, end_ms, text,
audio_filename, audio_size_bytes
) VALUES (?, ?, ?, ?, ?, ?, ?)
""",
[
(
share_id,
segment["sentence_index"],
segment["start_ms"],
segment["end_ms"],
segment["text"],
segment["audio_filename"],
segment["audio_size_bytes"],
)
for segment in segments
],
)
return {
"share_id": share_id,
"video_hash": normalized_hash,
"title": title[:200],
"created_at": now,
}
def get_dub_share(self, share_id: str) -> Optional[Dict[str, Any]]:
with self._connect() as connection:
share = connection.execute(
"SELECT * FROM dub_shares WHERE share_id = ?", (share_id,)
).fetchone()
if share is None:
return None
rows = connection.execute(
"""
SELECT * FROM dub_share_segments
WHERE share_id = ?
ORDER BY sentence_index
""",
(share_id,),
).fetchall()
result = dict(share)
result["segments"] = [dict(row) for row in rows]
return result
def record_attempt(
self,
*,