AI-интерполяция кадров видео (Frame Interpolation)
Конвертация 24fps → 60fps или 30fps → 120fps через дублирование кадров даёт рывки на быстрых движениях. AI frame interpolation синтезирует промежуточные кадры с помощью optical flow — результат плавнее, чем любой механический метод.
RIFE — практический инструмент
RIFE (Real-Time Intermediate Flow Estimation) — самый быстрый open-source метод. RTX 3080, 1080p: ~30 кадров/секунду при 2x интерполяции.
import torch
import numpy as np
import cv2
from pathlib import Path
# Загрузка RIFE модели (IFNet)
from model.RIFE_HDv3 import Model
def interpolate_video_rife(
input_path: str,
output_path: str,
multiplier: int = 2, # 2x, 4x, 8x — только степени двойки в RIFE
scale: float = 1.0, # масштаб для optical flow (0.5 при слабом GPU)
fp16: bool = True
) -> None:
device = torch.device('cuda')
model = Model()
model.load_model('train_log', -1)
model.eval().device(device)
cap = cv2.VideoCapture(input_path)
fps = cap.get(cv2.CAP_PROP_FPS)
w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
out_fps = fps * multiplier
writer = cv2.VideoWriter(
output_path,
cv2.VideoWriter_fourcc(*'mp4v'),
out_fps, (w, h)
)
ret, prev_frame = cap.read()
while ret:
ret, curr_frame = cap.read()
if not ret:
break
# Преобразование в тензоры
I0 = torch.from_numpy(prev_frame).permute(2,0,1).float() / 255.0
I1 = torch.from_numpy(curr_frame).permute(2,0,1).float() / 255.0
if fp16:
I0 = I0.half()
I1 = I1.half()
I0 = I0.unsqueeze(0).to(device)
I1 = I1.unsqueeze(0).to(device)
# Padding до кратного 32
pad_h = (32 - h % 32) % 32
pad_w = (32 - w % 32) % 32
I0 = torch.nn.functional.pad(I0, [0, pad_w, 0, pad_h])
I1 = torch.nn.functional.pad(I1, [0, pad_w, 0, pad_h])
writer.write(prev_frame)
# Синтезируем (multiplier-1) промежуточных кадров
for i in range(1, multiplier):
t = i / multiplier
with torch.no_grad():
middle = model.inference(I0, I1, scale=scale)
mid_np = (middle[0].float().cpu().permute(1,2,0).numpy()
* 255).astype(np.uint8)
writer.write(mid_np[:h, :w])
prev_frame = curr_frame
writer.write(prev_frame)
cap.release()
writer.release()
EMA-VFI для сложных сцен
RIFE теряет качество на сценах с окклюзиями и нелинейными движениями. EMA-VFI (Event-based Motion-Aware VFI) — точнее, но медленнее в 3–4 раза.
Типичные артефакты и решения
Ghosting — полупрозрачный двойник объекта. Возникает при быстрых движениях, где optical flow даёт ошибку. Решение: уменьшить scale или переключиться на EMA-VFI.
Warping artifacts — деформация текста и резких краёв. RIFE плохо работает с текстом на экранах. Решение: маскировать статичные регионы и не интерполировать их.
Мерцание на shot cuts — RIFE не детектирует смену сцены и синтезирует кадр между двумя разными сценами. Необходима предобработка: определение shot boundaries через PySceneDetect.
from scenedetect import detect, ContentDetector, AdaptiveDetector
def find_scene_cuts(video_path: str, threshold: float = 27.0) -> list[int]:
"""
Возвращает номера кадров, где происходит смена сцены.
threshold=27: стандартный для ContentDetector.
"""
scene_list = detect(
video_path,
ContentDetector(threshold=threshold)
)
cut_frames = []
for scene in scene_list:
cut_frames.append(scene[0].get_frames())
return cut_frames
Сравнение методов
| Метод | Скорость 1080p 2x | SSIM | Артефакты | Применение |
|---|---|---|---|---|
| Дублирование кадров | Мгновенно | — | Рывки | Не использовать |
| DAIN | ~5fps | 0.942 | Средние | Архивное видео |
| RIFE v4.6 | ~30fps | 0.961 | Ghosting на быстрых | 24→48fps |
| EMA-VFI | ~8fps | 0.971 | Минимальные | Киновидео |
| Film (Google) | ~3fps | 0.978 | Минимальные | Максимум качества |
Сроки
| Задача | Срок |
|---|---|
| API-сервис frame interpolation (RIFE) | 1–2 недели |
| Pipeline с детекцией shot cuts + интерполяция | 2–4 недели |
| Fine-tuning под специфический тип видео | 6–10 недель |







