자막에 생명을! Python과 ASS로 '말씀'만 색상 바꾸는 자동화 비법

2026. 1. 15.

 

영상 제작자 여러분! 혹시 여러분의 오디오북이나 인터뷰 영상 자막이 너무 단조롭게 느껴지신 적 없으신가요? 나레이션과 인물의 대사가 모두 같은 색으로 표시되어, 중요한 '말씀'이 묻히는 것 같아 아쉬웠던 경험은 없으신가요?

 

오늘은 단순한 텍스트의 나열을 넘어, 자막에 생명력과 깊이를 불어넣는 전문가 수준의 기법을 소개해 드리고자 합니다. 바로 ASS(Advanced SubStation Alpha) 자막의 강력한 '부분 스타일링(Inline Styling)' 기능을 활용하여, "큰따옴표 안의 텍스트만" 자동으로 다른 색상으로 변경하는 방법입니다.

 

이 모든 과정을 Python으로 자동화하여, SRT 파일만 있으면 누구나 손쉽게 전문가 수준의 자막을 완성할 수 있도록 도와드리겠습니다.


1. 왜 '설명'과 '말씀'을 구분해야 할까?

단순히 모든 텍스트를 보여주는 것을 넘어, 색상의 변화를 통해 우리는 시청자에게 더 많은 정보를 전달하고 더 깊은 몰입감을 선사할 수 있습니다.

  • 직관적인 정보 전달: 시청자는 색상의 차이만으로 지금이 상황 설명(나레이션)인지, 인물의 중요한 대사(말씀)인지 즉시 구분할 수 있습니다.
  • '말씀'의 권위 강조: 중요한 대사에만 특별한 색을 부여함으로써, 그 텍스트에 시각적인 무게감을 더하고 시청자의 집중을 유도합니다.
  • 세련된 미학적 완성도: 의도된 색상 팔레트를 사용하는 것은, 여러분의 영상이 매우 세심하게 디자인되었다는 인상을 주어 전체적인 품격을 높입니다.
역할 색상 이름 16진수 코드 RGB 값 디자인 의도 및 사용자 경험
대사
(모든 인물)
소프트 아이보리
(Soft Ivory)
#F5F5DC (245, 245, 220) 따뜻함, 부드러움, 집중. 순백색의 눈부심과 노란색의 자극성을 모두 배제한, 베이지색이 아주 미세하게 가미된 따뜻한 흰색입니다. 어두운 배경 위에서 텍스트를 선명하게 보여주면서도, 빛이 번지지 않아 눈의 피로도가 현저히 낮습니다. '은은한 호박색'보다 채도가 낮아 훨씬 더 차분하고 고급스러운 느낌을 줍니다.
나레이션
(설명)
웜 그레이
(Warm Gray)
#D3D3D3 (211, 211, 211) 차분함, 배경, 명료함. 기존의 라이트 그레이(E0E0E0)보다 아주 약간 더 어둡습니다. 이 미세한 차이를 통해, '대사'가 나올 때 시각적으로 더 중요한 정보라는 것을 부드럽게 암시합니다. 차가운 회색이 아닌 따뜻한 톤의 회색으로, 아이보리 색상과 완벽한 색상 조화를 이룹니다.

2. 핵심 원리: ASS 자막의 "오버라이드 태그(Override Tags)"

이 마법의 핵심은 ASS 포맷의 강력한 기능인 '오버라이드 태그'에 있습니다. SRT와 달리, ASS는 자막 줄 안의 특정 부분에만 다른 스타일을 강제로 적용할 수 있습니다.

  • 색상 변경 태그 (\c 또는 \1c): 이 태그가 나온 시점부터 텍스트의 색상을 변경합니다.
    • 문법: \c&H<BBGGRR>& (주의: 색상 순서가 Blue-Green-Red 입니다!)
    • 예시: #FFB300 (은은한 호박색) -> &H00B3FF&
  • 스타일 초기화 태그 (\r): 변경된 스타일을 다시 원래의 기본 스타일로 되돌립니다.

이 두 가지를 조합하면, 다음과 같은 코드를 만들 수 있습니다.

 

예수께서 대답하셨습니다. "{\c&H00B3FF&}지금은 허락해 주십시오.{\r}"

 

이 한 줄의 코드는 플레이어에게 이렇게 명령합니다:

"기본색으로 '예수께서 대답하셨습니다. "' 까지 보여줘. 그 다음부터는 '호박색'으로 바꿔서 '지금은 허락해 주십시오.'를 보여준 뒤, 다시 원래 색으로 돌아와."


3. Python으로 모든 것을 자동화하기

이제 이 원리를 Python 스크립트에 적용하여, 수백 개의 자막 라인도 단 몇 초 만에 처리하는 자동화 시스템을 만들어 보겠습니다.

자동화의 핵심: 정규 표현식 (Regular Expression)

정규 표현식은 복잡한 문자열 속에서 특정 패턴을 찾아내는 강력한 도구입니다. 우리는 이 도구를 사용해 자막 텍스트에서 "큰따옴표로 둘러싸인 모든 부분"을 정확하게 찾아낼 것입니다.

  • 우리가 사용할 패턴: "(.*?)"
    • 이 패턴은 "로 시작하고 " 로 끝나는 모든 문자열(.*?)을 찾아줍니다.

최종 자동화 코드

이 코드는 SRT 파일을 직접 읽어, 긴 자막은 디졸브로 부드럽게 연결하고, 큰따옴표 안의 '말씀'만 자동으로 다른 색으로 변경한 뒤, 최종적으로 완벽한 ASS 파일을 생성합니다.

import pysubs2
import os
import re

# --- (설정값들은 이전과 동일) ---
# ...

def create_styled_ass_from_srt_quotes_advanced(srt_path, ass_path):
    """
    SRT 파일을 불러와, 한 줄 또는 여러 줄에 걸친 인용구("...")를
    자동으로 인식하여 다른 색으로 변경하는 최종 버전입니다.
    """
    try:
        subs = pysubs2.load(srt_path, encoding="utf-8")
        
        # (디졸브를 위한 시간 사전 조정 로직은 이전과 동일)
        # ...

        # (스타일 설정은 이전과 동일)
        # ...
        
        # --- [핵심] 상태 관리 로직을 사용한 효과 적용 ---
        
        in_quote_block = False # 현재 인용구 블록 안에 있는지 상태를 기억하는 변수

        for line in subs:
            line.style = 'Default'
            
            clean_text = line.plaintext
            styled_text = ""

            # 1. 시작 따옴표와 끝 따옴표가 모두 한 줄에 있는 경우 (가장 흔함)
            if '"' in clean_text and clean_text.count('"') % 2 == 0:
                def replace_quotes(match):
                    quoted_text = match.group(1)
                    return f'"{DIALOGUE_COLOR_TAG}{quoted_text}{RESET_TAG}"'
                styled_text = re.sub(r'"(.*?)"', replace_quotes, clean_text)
                in_quote_block = False # 혹시 모르니 상태 초기화
            
            # 2. 시작 따옴표만 있는 경우 (인용구 시작)
            elif '"' in clean_text and not in_quote_block:
                parts = clean_text.split('"', 1)
                styled_text = f'{parts[0]}"{DIALOGUE_COLOR_TAG}{parts[1]}'
                in_quote_block = True
            
            # 3. 끝 따옴표만 있는 경우 (인용구 끝)
            elif '"' in clean_text and in_quote_block:
                parts = clean_text.split('"', 1)
                styled_text = f'{DIALOGUE_COLOR_TAG}{parts[0]}{RESET_TAG}"{parts[1]}'
                in_quote_block = False

            # 4. 따옴표가 하나도 없지만, 인용구의 중간 부분인 경우
            elif in_quote_block:
                styled_text = f'{DIALOGUE_COLOR_TAG}{clean_text}' # 전체 라인에 색상 적용
            
            # 5. 인용구와 관련 없는 일반 라인
            else:
                styled_text = clean_text

            # (시간 계산 및 전체 페이드 효과 적용 로직은 이전과 동일)
            original_duration = line.end - line.start
            line.end = line.start + original_duration + LINGER_MS + EXIT_EFFECT_DURATION
            fade_tag = f"\\fad({EFFECT_IN_DURATION},{EXIT_EFFECT_DURATION})"
            
            line.text = f"{{{fade_tag}}}{styled_text.replace(chr(10), r'\\N')}"

        subs.save(ass_path)
        print(f"성공: SRT -> ASS 변환 및 다중 라인 인용구 처리 완료! '{srt_path}' -> '{ass_path}'")
        return True
    
    except Exception as e:
        print(f"   [경고] ASS 파일 생성 실패: {e}")
        return False

# (메인 실행 코드)
# ...

마치며

이제 여러분은 더 이상 수동으로 자막 색상을 바꾸는 고된 작업을 할 필요가 없습니다. 이 Python 스크립트 하나면, 원본 SRT 파일의 따옴표만 잘 유지하는 것만으로도 자동으로 설명과 말씀을 구분하는 전문가 수준의 자막을 순식간에 만들어낼 수 있습니다.

 

단순한 정보 전달을 넘어, 시청자에게 더 깊은 감성적 경험을 선사하고 싶으시다면, 오늘 소개해 드린 '부분 스타일링' 자동화 기법을 꼭 한번 활용해 보시길 바랍니다! 여러분의 영상이 한 단계 더 프로페셔널해질 것입니다.

댓글