68 lines
2.0 KiB
Python
68 lines
2.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""generator/output 스캔 → content 테이블 upsert.
|
|
|
|
디스크의 완성 mp4 와 DB 를 잇는다. 시작 시 + 잡 완료 시 호출.
|
|
"""
|
|
import re
|
|
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from .config import OUTPUT_DIR, ENGINE_SCENARIO
|
|
from .database import SessionLocal
|
|
from .models import Content
|
|
|
|
_TITLE_RE = re.compile(r"\[제목\]\s*(.+)")
|
|
|
|
|
|
def _title(job_dir) -> str:
|
|
txt = job_dir / "narration.txt"
|
|
if txt.exists():
|
|
for line in txt.read_text(encoding="utf-8", errors="ignore").splitlines():
|
|
m = _TITLE_RE.match(line.strip())
|
|
if m:
|
|
return m.group(1).strip()
|
|
return job_dir.name
|
|
|
|
|
|
def _scan() -> list[dict]:
|
|
rows = []
|
|
if not OUTPUT_DIR.is_dir():
|
|
return rows
|
|
for engine, sc in ENGINE_SCENARIO.items():
|
|
d = OUTPUT_DIR / engine
|
|
if not d.is_dir():
|
|
continue
|
|
for job in d.iterdir():
|
|
if not job.is_dir():
|
|
continue
|
|
mp4s = sorted(job.glob("*.mp4"))
|
|
if not mp4s:
|
|
continue
|
|
rel = mp4s[0].relative_to(OUTPUT_DIR).as_posix()
|
|
rows.append({"id": job.name, "sc": sc, "title": _title(job), "video": f"/videos/{rel}"})
|
|
return rows
|
|
|
|
|
|
async def sync_output(session: AsyncSession | None = None, owner_uuid: str | None = None) -> int:
|
|
"""새 output 폴더를 content 로 삽입. 삽입 개수 반환."""
|
|
own = session is None
|
|
session = session or SessionLocal()
|
|
try:
|
|
existing = set((await session.execute(select(Content.id))).scalars().all())
|
|
added = 0
|
|
for r in _scan():
|
|
if r["id"] in existing:
|
|
continue
|
|
session.add(Content(
|
|
id=r["id"], scenario=r["sc"], title=r["title"], video=r["video"],
|
|
owner_uuid=owner_uuid,
|
|
))
|
|
added += 1
|
|
if added:
|
|
await session.commit()
|
|
return added
|
|
finally:
|
|
if own:
|
|
await session.close()
|