KT AIVLE School AI 트랙 미니프로젝트 2차
PPT 파일 한 장이면 강의 스크립트 작성부터 음성 합성, 영상 제작, 자막 합성까지 자동으로 끝내는 LangGraph 기반 에이전트입니다.
발표자가 PPTX 슬라이드만 준비하면, 에이전트가 아래 과정을 자동으로 수행하여 PPT를 실제 강의 영상으로 바꿔주는 것이 목표입니다.
- 슬라이드에 담긴 텍스트/표/이미지를 읽어내고
- 슬라이드 제목으로 웹 검색을 보강해 설명을 풍부하게 만들고
- 전체 강의 흐름을 고려해 슬라이드별 발표 스크립트를 작성하고
- 스크립트를 지정한 톤에 맞는 목소리로 음성 합성(TTS)하고
- 슬라이드 이미지 + 음성을 합쳐 슬라이드별 영상을 만든 뒤 전체 강의 영상으로 이어붙이고
- 마지막으로 음성 인식(Whisper)을 통해 자막까지 입혀줍니다.
src/agent.py의 build_graph()가 실제로 조립하는 StateGraph 구조는 다음과 같습니다 (원본 노트북 AI_15조.ipynb의 그래프 정의 셀 그대로).
| 노드 | 역할 |
|---|---|
parse_all |
PPTX의 모든 슬라이드에서 텍스트/표/이미지 추출 + 슬라이드 배경 스냅샷(PNG) 생성 |
gen_overall_script |
전체 슬라이드 내용을 바탕으로 강의 전체 흐름(개요) 생성 |
gen_comic |
전체 흐름을 요약한 4컷 만화 이미지 생성 (gpt-image-1.5) |
gen_outro |
만화 이미지 + 마무리 멘트 음성으로 아웃트로 영상 생성 |
search_index |
현재 슬라이드 제목으로 Tavily 웹 검색 수행 |
gen_content |
슬라이드 원본 정보 + 검색 결과를 종합해 페이지 설명문 생성 (이미지 최대 2장 함께 전달) |
gen_script |
페이지 설명문 기반으로 60~90초 분량 발표 스크립트 생성 (오프닝/중반/클로징 분기 로직 포함) |
gen_quiz |
방금 만든 스크립트를 바탕으로 짧은 복습 퀴즈 생성, 마지막 슬라이드에서는 전체 퀴즈를 스크립트 끝에 병합 |
tts |
스크립트를 OpenAI TTS로 음성(mp3) 변환 (톤에 맞는 보이스를 LLM이 자동 선택) |
gen_video |
슬라이드 스냅샷 + 음성을 합쳐 슬라이드별 mp4 생성 (ffmpeg) |
update_index |
다음 슬라이드로 인덱스 증가 |
concat_videos |
모든 슬라이드 영상 + 아웃트로 영상을 하나의 최종 영상으로 병합 |
gen_subtitles_video |
Whisper로 음성 인식 후 최종 영상에 자막 합성(burn-in) |
flowchart TD
START([시작]) --> parse_all[parse_all]
parse_all --> gen_overall_script[gen_overall_script]
gen_overall_script --> gen_comic[gen_comic]
gen_overall_script --> search_index[search_index]
gen_comic --> gen_outro[gen_outro]
gen_outro --> concat_videos[concat_videos]
search_index --> gen_content[gen_content]
gen_content --> gen_script[gen_script]
gen_script --> tts[tts]
gen_script --> gen_quiz[gen_quiz]
gen_quiz --> gen_script
tts --> gen_video[gen_video]
gen_video --> update_index[update_index]
update_index -->|continue| search_index
update_index -->|end| concat_videos
concat_videos --> gen_subtitles_video[gen_subtitles_video]
gen_subtitles_video --> END([종료])
슬라이드가 여러 장일 경우 search_index → gen_content → gen_script → tts → gen_video → update_index 구간이 슬라이드 수만큼 반복되고, 마지막 슬라이드까지 처리되면 concat_videos로 빠져나가 전체 영상을 합치는 구조입니다. 슬라이드별 스크립트를 그때그때 순차 생성하는 대신 gen_overall_script로 전체 강의 흐름을 먼저 잡아둔 뒤 슬라이드별로 나눠 쓰는 방식을 택해, 슬라이드 간 맥락이 이어지도록 했습니다.
gen_script → gen_quiz → gen_script로 되돌아가는 순환 엣지에는 별도의 종료 조건이 없어, src/main.py에서는 무한 반복을 막기 위해 recursion_limit을 지정해 실행합니다.
- 오케스트레이션: LangGraph (
StateGraph, 조건부 엣지) - LLM:
langchain-openai(ChatOpenAI), OpenAIgpt-image-1.5(이미지 생성),gpt-4o-mini-tts(TTS) - 웹 검색:
langchain-tavily(Tavily Search API) - 슬라이드 파싱:
python-pptx,Pillow - 슬라이드 → 이미지 변환: LibreOffice(
soffice) headless 변환 +pdftoppm(poppler),xvfb - 음성/자막: OpenAI TTS,
openai-whisper(음성 인식 → SRT 자막 생성) - 영상 합성:
ffmpeg(이미지+오디오 → mp4, 여러 mp4 병합, 자막 burn-in) - 웹 데모:
gradio
파이프라인을 끝까지 실행하면 다음 산출물이 생성됩니다.
- 슬라이드별 발표 스크립트(txt), 복습 퀴즈 텍스트
- 슬라이드별 음성 파일(mp3)과 슬라이드별 강의 영상(mp4)
- 전체 강의를 이어붙인 최종 영상(
final_lecture_full.mp4)과 자막이 합성된 최종본(result_with_subtitles.mp4) - 강의 내용을 요약한 4컷 만화 이미지 및 이를 이용한 아웃트로 영상
용량이 큰 실제 생성물(mp4/mp3/슬라이드 이미지 등)은 재실행하면 다시 만들어낼 수 있는 산출물이라 저장소에는 포함하지 않았습니다. src/main.py로 직접 실행하면 로컬 work-dir에 위와 동일한 결과물이 생성됩니다.
02-Miniproject/
├── README.md
├── requirements.txt
├── notebooks/
│ └── ai_instructor_agent.ipynb # 원본 Colab 노트북(백업/참고용, 팀 최종 제출본)
├── src/
│ ├── agent.py # LangGraph 그래프 정의 + 노드 함수 (노트북 로직을 재구성한 실행 가능 모듈)
│ └── main.py # CLI 진입점 (python src/main.py --pptx ... 로 실행)
└── docs/
└── AI_강사_Agent_보고서.pptx # 팀 최종 발표/보고서 자료
pip install -r requirements.txt
# ffmpeg, libreoffice, poppler-utils, xvfb 등 OS 패키지는 별도 설치 필요
export OPENAI_API_KEY=sk-...
export TAVILY_API_KEY=tvly-...
python src/main.py --pptx path/to/slides.pptx --work-dir ./output