09_DB 스키마 공개
들어가며
SceneMaker가 방송 영상을 분석해 저장하는 데이터 구조를 공개한다.
-github DB 스키마 링크 포함 필수-
저장 형식은 정형 데이터, 비정형 데이터가 있다 . 프로젝트에서 사용한 DB는 아래와 같다.
| MariaDB (관계형) | Milvus (VectorDB) | |
|---|---|---|
| 담는 것 | 정형 데이터. AI 결과를 읽히는 형태 로 (자막·요약·인물·감정) | 비정형 데이터. 텍스트의 임베딩 벡터 + 검색용 메타 |
| 역할 | 원본 진실 (Single Source of Truth) | 검색용 파생본 |
전체 데이터 저장 흐름
데이터 저장소는 Mysql 과 Milvus 를 사용하고 있으며 아래의 흐름으로 데이터가 저장된다.

관계형 테이블은 t_video 를 중심으로 v_id 로 연결된다.
t_video ─┬─ t_dialogue / t_dialogue_refine (대사)
├─ t_segment / t_segment_refine (6초 화면분석)
├─ t_chapter (씬/서브)
├─ t_scene (사건 단위 장면)
├─ t_category (분류, 자기참조 계층)
└─ t_code (상태 코드)
각 데이터베이스들의 구성을 확인해보자.
1. MariaDB 테이블

t_video — 영상 (중심 테이블)
영상 한 편의 메타와 최종 요약을 담는다.
| 컬럼 | 타입 | 설명 |
|---|---|---|
v_id | mediumint | PK , 영상 ID |
p_v_id | mediumint | 시리즈 연결(예: 시즌2→시즌1 참조) |
cate_id | smallint | FK → t_category |
name | varchar(45) | 영상명 |
dir | varchar(200) | 영상 저장 위치 |
summary / summary_stt | text | 전체 줄거리 / STT 단계 요약 |
cast | text | STT가 남긴 등장인물 |
status_code | smallint | FK → t_code , 처리 상태 |
reg/upd_datetime | datetime | 입력·변경 시각 |
t_category — 카테고리 (자기참조 계층)
p_cate_id 로 상위 카테고리를 가리켜 "스포츠 → 야구" 같은 계층을 만듭니다.
| 컬럼 | 설명 |
|---|---|
cate_id (PK) / cate_name | 카테고리 ID / 이름 |
p_cate_id | 상위 카테고리 |
t_dialogue — 대사 (자막)
STT 결과. (v_id, idx) 가 PK인 시간순 대사입니다.
| 컬럼 | 타입 | 설명 |
|---|---|---|
v_id, idx | PK , 영상·대사순서 | |
start_time / end_time | time(1) | 발화 구간 |
speaker / speaker_name | char(4) / varchar | 발화자 라벨 / 교정된 실명 |
lang | char | 발화 언어 |
dialogue | varchar(500) | 대사 본문 |
t_dialogue_refine은 인물명 보정을 거친 2차본으로, 스키마는 거의 동일합니다.
t_segment — 6초 화면분석 (검색 원자)
영상을 6초 단위로 자른 화면 분석 결과. 검색의 최소 단위입니다.
| 컬럼 | 타입 | 설명 |
|---|---|---|
v_id, seg_id | PK | |
start_time / end_time | time | 6초 구간 |
summary | varchar(1024) | 화면 내용 요약 |
adv | tinyint | 광고 포함 여부 |
meta | JSON | 카테고리별 구조 속성(스포츠=스코어/이닝…) |
status_code / status_reason | 처리 상태 |
t_segment_refine은 보정본으로cast · ocr · sound · action(JSON) 필드가 추가됨. (agent-vision 산출물)
t_chapter — 씬 / 서브 (계층 요약)
level 로 씬(2)과 서브·막(1)을 구분하고, parent_chap_id 로 씬→서브를 연결합니다.
| 컬럼 | 설명 |
|---|---|
v_id, chap_id (PK) | |
level | 1=서브(막) / 2=씬 |
parent_chap_id | 씬이 속한 서브 |
start/end_time , start/end_seg | 시간·세그먼트 범위 |
title / summary | 라벨 / 줄거리(임베딩 대상) |
cast / keywords / emotion | 등장인물 / 키워드 / 감정 |
meta | 확장 JSON |
t_scene — 사건 단위 장면
장르별 사건 단위(스포츠=홈런/삼진 등). 검색 필터용 구조 속성을 JSON으로 가집니다.
| 컬럼 | 설명 |
|---|---|
v_id, scene_id (PK) | |
scene_type / description | 사건 유형 / 서술(임베딩 대상) |
is_replay / is_ad | 리플레이·광고 배제 플래그 |
attributes | JSON (스포츠=투수/타자/이닝/스코어…) |
이 밖에
t_play(야구 특화,t_scene으로 대체됨)·t_segment_2(실험용) 레거시 테이블이 있다.
2. Milvus 컬렉션 — sm_1024
관계형 데이터 중 검색 대상(자막·화면·씬·서브)을 임베딩해 담는 벡터 컬렉션 의미 기반 검색이기에, 비정형 데이터를 사용하였다.
한 행 = 벡터 + 검색용 메타 복사본 .
| 필드 | 타입 | 설명 |
|---|---|---|
pk | VARCHAR(64) | PK , "v_id:ref_type:ref_id" |
vector | FLOAT_VECTOR(1024) | 임베딩 벡터 (유일한 벡터 값) |
v_id | INT32 | 영상 ID (→ RDB) |
ref_type | VARCHAR(16) | segment / scene / chapter / dialogue |
ref_id | INT16 | RDB의 seg_id / chap_id / idx |
p_ref_id | INT16 | 소속 씬(부모 맥락) |
start/end_sec , start/end_time | INT16 / VARCHAR | 시간 범위 |
cast | VARCHAR(500) | 등장인물 |
text | VARCHAR(2048) | 임베딩 원문 |
dialogue / segment / scene | JSON | 원본 스냅샷 |
- 인덱스 :
vector→ HNSW / 유사도 : COSINE - 동적 필드 (
enable_dynamic_field=True):cate_id, emotion, highlight, events, is_ad
3. 두 저장소의 연결
Milvus의 각 벡터는 pk = v_id : ref_type : ref_id 로 관계형 원본 행과 1:1로 이어집니다.
Milvus "42:segment:120" ←→ RDB t_segment (v_id=42, seg_id=120)
ref_type 이 어느 테이블인지를, ref_id 가 그 테이블의 PK 일부(seg_id /chap_id /idx )를 가리킵니다.
4. 저장 순서
데이터는 파이프라인을 따라 아래 순서로 쌓입니다. (작은 원자 → 파생 → 벡터 색인)
| 순서 | 저장 | 담당 |
|---|---|---|
| 1 | t_video (껍데기) | 등록 |
| 2 | t_dialogue · t_segment | agent-stt · agent-vision |
| 3 | t_chapter · t_scene | agent-scenario |
| 4 | t_video.summary | agent-scenario |
| 5 | Milvus sm_1024 (벡터 색인) | agent-scenario |
관계형 저장이 모두 끝난 뒤, 마지막에 벡터 색인이 이뤄집니다.
마무리
전체 DDL과 컬렉션 정의는 저장소에 공개돼 있습니다. SceneMaker는 Apache 2.0으로 배포됩니다.
본 글은 과학기술정보통신부·정보통신산업진흥원 「2026년 오픈소스 AI·SW 개발·활용 지원사업」의 지원으로 수행된 연구 결과입니다.