반응형

영상 프레임 보간 AI인 RIFE를 파이썬에서 사용하는 방법입니다.

프레임 사이사이에 AI가 중간 프레임을 생성해주기 때문에 슬로우 모션을 걸어도 끊기지 않습니다.

RIFE 다운로드

두 가지 방식이 있습니다.

1. CUDA/PyTorch (NVIDIA GPU)

pip install torch torchvision pillow

모델 파일은 RIFE GitHub에서 받을 수 있습니다.

train_log 폴더에 RIFE_HDv3.py와 체크포인트 파일이 필요합니다.

2. ncnn-vulkan (AMD 등 모든 GPU)

rife-ncnn-vulkan releases에서 exe 파일을 받으면 됩니다.

별도 파이썬 패키지 설치 없이 subprocess로 호출하는 방식입니다.

1단계: FFmpeg로 프레임 추출

먼저 영상을 JPG 프레임으로 쪼갭니다.

import subprocess

FFMPEG = 'ffmpeg.exe 경로'

subprocess.run([
    FFMPEG, '-y',
    '-hwaccel', 'cuda',
    '-i', '입력영상.mp4',
    '-qscale:v', '2',
    'temp/in/%08d.jpg'
])

-hwaccel cuda는 GPU 디코딩 가속 옵션입니다. 없어도 동작하지만 속도 차이가 꽤 납니다.

-qscale:v 2는 JPG 품질 설정으로 낮을수록 고품질입니다.

2단계: RIFE 프레임 보간

CUDA 방식

import torch
from torchvision import transforms
from PIL import Image
from train_log.RIFE_HDv3 import Model

# 모델 로드 (최초 1회)
model = Model()
model.load_model('rife_model/train_log', -1)
model.eval()
model.device()
torch.set_grad_enabled(False)

# 프레임 보간
frames = sorted(Path('temp/in').glob('*.jpg'))
multiply = 8  # 프레임 8배
idx = 0

for i in range(len(frames) - 1):
    img0 = transforms.ToTensor()(Image.open(frames[i])).unsqueeze(0).cuda().half()
    img1 = transforms.ToTensor()(Image.open(frames[i+1])).unsqueeze(0).cuda().half()

    # 원본 프레임 저장
    Image.open(frames[i]).save(f'temp/out/{idx:08d}.jpg', quality=95)
    idx += 1

    # 중간 프레임 생성
    for ti in range(1, multiply):
        t = ti / multiply
        mid = model.inference(img0, img1, t)
        transforms.ToPILImage()(mid.squeeze(0).float().clamp(0,1).cpu()) \
            .save(f'temp/out/{idx:08d}.jpg', quality=95)
        idx += 1

핵심은 model.inference(img0, img1, t) 한 줄입니다. t값(0~1)에 따라 두 프레임 사이 원하는 위치의 중간 프레임을 생성해줍니다.

ncnn-vulkan 방식

RIFE_NCNN = 'rife-ncnn-vulkan.exe 경로'
MODEL_PATH = 'rife-v4.6 모델 폴더'

frame_count = len(list(Path('temp/in').glob('*.jpg')))
target = frame_count * 8  # 8배 보간

subprocess.run([
    RIFE_NCNN,
    '-i', 'temp/in',
    '-o', 'temp/out',
    '-n', str(target),
    '-m', MODEL_PATH,
    '-g', '0',           # GPU 번호
    '-j', '8:8:8',       # 스레드 수
    '-f', '%08d.jpg'
])

exe 파일 하나로 끝나서 환경 세팅이 훨씬 간단합니다.

3단계: FFmpeg로 슬로우 모션 인코딩

original_fps = 30
multiply = 8
slow_factor = 2
output_fps = original_fps * multiply / slow_factor  # 120fps

subprocess.run([
    FFMPEG, '-y',
    '-framerate', str(output_fps),
    '-start_number', '0',
    '-i', 'temp/out/%08d.jpg',
    '-an',
    '-c:v', 'libx264',
    '-crf', '23',
    '-preset', 'veryslow',
    '-pix_fmt', 'yuv420p',
    '-movflags', '+faststart',
    'output/result_rife8x_slow2x.mp4'
])

출력 FPS 계산이 포인트입니다. 30fps 원본을 8배 보간하면 240fps 분량의 프레임이 생기는데, 이걸 120fps로 재생하면 2배 슬로우가 됩니다.

주의사항

  • 장면 전환(컷)이 있는 구간은 프레임이 깨집니다
  • 원본 FPS가 높을수록 결과가 좋습니다
  • 배수가 높을수록 처리 시간이 비례해서 늘어납니다
반응형

+ Recent posts