슬라이드 강의·해설 영상에서 Python으로 장면 전환 자동 추출하기

2026. 2. 4.

 

안녕하세요! 오늘은 영상 편집자나 콘텐츠 제작자에게 꼭 필요한 영상 처리 자동화 기술을 공유하려고 합니다.

 

노트북LM이나 PPT로 만든 슬라이드 영상을 블로그 포스팅용 이미지로 변환하거나, 유튜브의 '챕터(타임라인)' 기능을 만들 때 아주 유용한 도구입니다.


1. 왜 이 기술이 필요한가요?

  • 시간 절약: 10분짜리 영상에서 슬라이드 20장을 수동으로 캡처하려면 꽤 많은 시간이 걸리지만, 이 코드는 단 몇 초 만에 해결합니다.
  • 정확도: 눈으로 확인하기 힘든 미세한 화면 전환 시점도 프레임 단위로 계산해냅니다.
  • 콘텐츠 재활용: 해설 영상을 토대로 블로그 글을 쓰거나 교육 자료를 만들 때, 핵심 슬라이드 이미지를 즉시 확보할 수 있습니다.

2. 준비물

이 코드를 실행하려면 아래 두 가지가 필요합니다.

  1. Python: 파이썬 공식 홈페이지에서 설치 가능합니다.
  2. FFmpeg: 영상 처리의 '맥가이버 칼'이라 불리는 도구입니다. 설치 후 '환경 변수'에 등록되어 있어야 합니다.

3. 전체 파이썬 코드 (완성본)

이 코드는 크게 두 가지 일을 합니다.

  1. ffprobe를 사용해 장면이 바뀌는 정확한 타임라인을 텍스트 파일로 저장합니다.
  2. ffmpeg를 사용해 화면이 변하는 순간의 이미지를 PNG 파일로 추출합니다.
import subprocess
import os
import datetime

def process_video_slides(video_path, output_dir='output_slides', threshold=0.02):
    """
    영상에서 장면 전환을 감지하여 이미지 추출 및 타임라인을 기록합니다.

    :param video_path: 분석할 영상 파일 경로
    :param output_dir: 결과물이 저장될 폴더
    :param threshold: 장면 전환 감도 (0.01 ~ 0.1) - 낮을수록 미세한 변화도 감지
    """

    # 1. 저장 폴더 생성
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    timeline_file = os.path.join(output_dir, 'timeline.txt')
    image_pattern = os.path.join(output_dir, 'slide_%03d.png')

    print(f"\n[작업 시작] 분석 파일: {video_path}")
    print("-" * 50)

    # 2. ffprobe를 이용한 장면 전환 타임라인 추출
    # scene 필터가 설정한 threshold 이상일 때의 시간값(pkt_pts_time)만 가져옵니다.
    print("> 1단계: 장면 전환 타임라인 분석 중...")
    probe_cmd = [
        'ffprobe', '-v', 'error',
        '-show_entries', 'frame=pkt_pts_time',
        '-of', 'default=noprint_wrappers=1:nokey=1',
        '-f', 'lavfi',
        f"movie={video_path},select='gt(scene,{threshold})'"
    ]

    try:
        raw_output = subprocess.check_output(probe_cmd, universal_newlines=True).strip()
        timestamps = [ts for ts in raw_output.split('\n') if ts]
    except subprocess.CalledProcessError as e:
        print(f"타임라인 분석 실패: {e}")
        return

    # 3. ffmpeg를 이용한 슬라이드 이미지 추출
    # 가변 프레임 레이트(-vsync vfr)를 적용하여 조건에 맞는 프레임만 저장합니다.
    print("> 2단계: 슬라이드 이미지 추출 중...")
    extract_cmd = [
        'ffmpeg', '-y', '-i', video_path,
        '-vf', f"select='gt(scene,{threshold})',setpts=N/FRAME_RATE/TB",
        '-vsync', 'vfr',
        image_pattern
    ]

    try:
        # 진행 상황은 생략하고 백그라운드에서 실행
        subprocess.run(extract_cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    except subprocess.CalledProcessError as e:
        print(f"이미지 추출 실패: {e}")
        return

    # 4. 결과 리포트 작성 (timeline.txt)
    print("> 3단계: 타임라인 파일 생성 중...")
    with open(timeline_file, 'w', encoding='utf-8') as f:
        f.write(f"=== 영상 슬라이드 추출 리포트 ===\n")
        f.write(f"대상 파일: {video_path}\n")
        f.write(f"추출 일시: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
        f.write("-" * 40 + "\n")

        for i, ts in enumerate(timestamps):
            seconds = float(ts)
            # 초 단위를 사람이 보기 편한 HH:MM:SS 포맷으로 변환
            time_fmt = str(datetime.timedelta(seconds=round(seconds, 2))).split('.')[0]
            f.write(f"슬라이드 {i+1:03d} | 위치: {ts.ljust(8)}초 | 타임코드: [{time_fmt}]\n")

    print("-" * 50)
    print(f"[완료] 총 {len(timestamps)}개의 장면이 추출되었습니다.")
    print(f"[결과 저장] {os.path.abspath(output_dir)}")

# 사용 예시
if __name__ == "__main__":
    # 분석하고 싶은 영상 파일명을 적어주세요 (확장자 포함)
    MY_VIDEO = 'bible_commentary_01.mp4' 

    if os.path.exists(MY_VIDEO):
        # threshold 값을 조정하여 감도를 조절할 수 있습니다 (기본 0.02)
        process_video_slides(MY_VIDEO, threshold=0.02)
    else:
        print(f"파일을 찾을 수 없습니다: {MY_VIDEO}")

4. 핵심 기술 포인트 설명 (알고리즘)

① 장면 전환 감지 필터 (select='gt(scene,0.02)')

FFmpeg의 가장 강력한 기능 중 하나입니다. 이전 프레임과 현재 프레임을 비교하여 변화량(0.0~1.0)을 수치화합니다.

  • 0.02는 화면의 약 2%가 변했을 때를 뜻합니다.
  • 슬라이드가 바뀔 때는 화면 전체가 변하므로 보통 0.01~0.03 사이의 값을 쓰면 아주 정확하게 잡아냅니다.

ffprobe vs ffmpeg

  • ffprobe: 영상을 실제로 건드리지 않고 '데이터'만 읽어옵니다. 여기서는 슬라이드가 바뀌는 정확한 시간(초) 정보를 얻기 위해 사용했습니다.
  • ffmpeg: 실제 영상 데이터를 가공합니다. 여기서는 바뀐 장면을 이미지 파일(.png)로 저장하는 역할을 합니다.

③ 사람이 읽기 편한 타임코드 변환

파이썬의 datetime.timedelta 모듈을 사용해 84.23초 같은 데이터를 00:01:24와 같은 형식으로 변환했습니다. 이 정보는 유튜브 설명란의 타임스탬프로 바로 활용할 수 있습니다.


5. 결과 확인하기

스크립트를 실행하면 output_slides 폴더에 다음과 같이 깔끔하게 정리된 결과물이 나타납니다.

  1. slide_001.png, slide_002.png...: 캡처된 고화질 이미지
  2. timeline.txt: 각 슬라이드의 위치 정보

슬라이드 001 | 위치: 0.000000초 | 타임코드: [0:00:00]
슬라이드 002 | 위치: 125.4500초 | 타임코드: [0:02:05]
...


마치며

이제 수동 캡처의 고통에서 벗어나세요!

 

이 파이썬 스크립트만 있으면 아무리 긴 강의 영상도 슬라이드별로 깔끔하게 정리할 수 있습니다.

특히 해설 영상을 만드시는 분들이나 온라인 강사분들에게 이 코드가 큰 도움이 되길 바랍니다.


 

댓글