프로토타입에서 프로덕션까지: 멀티모달 비디오 검색 엔진 구축
Source: Dev.to
개요
이전 글에서는 CLIP, Whisper, ArcFace 를 결합해 시각적 설명, 대화, 얼굴을 통해 비디오 콘텐츠를 찾는 모델 스태킹의 힘을 탐구했습니다. 연휴 동안 그 오후 해킹을 보다 프로덕션에 가까운 시스템으로 다듬었습니다.
실시간 데모
- 데모 사이트: (데스크톱 브라우저)
- 시작 코드:
예시 워크플로우
- Visual Content 탭에 “전화통화 중인 노인, 항구 배경” 을 입력 → + 클릭.
- 항구에 기대어 앉아 있는 안경 쓴 노인의 얼굴을 클릭.
- Dialog (Semantic mode) 탭에 “미국인들이 미사일을 발사했다” 를 입력 → + 클릭.
- 결과 클립을 재생.
메타데이터, 타임코드, 정확한 문구에 의존하지 않고 정확한 샷까지 파고들 수 있습니다. 의미 기반 검색은 퍼지하게 동작합니다—예를 들어, 트랜스크립트에 “What it was telling him was that the US had launched their ICBMs.” 라고 적혀 있어도 쿼리와 매치됩니다.
아키텍처
- 프론트엔드: Nginx 로 서빙되는 Vue.js
- 백엔드: FastAPI
- 인제스트 워커: 새로운 미디어를 폴링하고 드라이브 마운트/언마운트를 우아하게 처리하는 독립 프로세스 (Watchdog 은 NFS/네트워크 공유에서 신뢰성이 낮음)
- 데이터베이스: 벡터 유사도 검색을 위한 pgvector 확장 기능이 포함된 PostgreSQL
모든 구성 요소는 docker‑compose 로 오케스트레이션됩니다.
기능
- 백그라운드 강화 – 워커가 새 파일을 지속적으로 처리하고 시각, 오디오, 얼굴 임베딩을 추출합니다.
- 의미 기반 대화 검색 – sentence‑transformer 임베딩을 사용; “미국인들이 미사일을 발사했다” 와 같은 쿼리가 “US fired rockets.” 를 포함한 클립을 찾아냅니다.
- 프레임 정확도 재생 –
requestVideoFrameCallback()를 통해 HTML5 비디오를 캔버스로 디코딩합니다. - EDL 내보내기 – 선택한 씬을 큐에 넣고 NLE 라운드‑트리핑을 위한 CMX 3600 편집 결정 리스트를 내보냅니다.
- 통합 쿼리 – PostgreSQL + pgvector 로 메타데이터 필터링과 벡터 유사도 검색을 하나의 쿼리로 수행합니다.
코드
전체 소스 코드와 Docker 설정은 다음에서 확인할 수 있습니다:
감사
- 데모 영상은 Pioneer One(Creative Commons 라이선스가 적용된 캐나다 드라마)에서 가져왔습니다.
- Claude Code 에게 큰 도움을 받았습니다.