Бонусы за приглашения

Как работают бонусы за приглашения

Поделитесь ссылкой. Когда друг зарегистрируется по ней и пополнит баланс, вы получите указанный бонус за его последующие пополнения.

Как проверить видео после повышения частоты кадров в Runway

Полный путь от подготовки и загрузки локального видео до отправки enhance_frame_rate, проверки задачи, сохранения результата и финальной приёмки.

Содержание
Как проверить видео после повышения частоты кадров в Runway

У вас может быть готовый локальный ролик, но ещё не быть результата Runway с повышенной частотой кадров. До приёмки нужно подготовить и загрузить файл, передать targetFramerate, дождаться задачи и сохранить выходной файл. Ниже дан полный REST-процесс, а затем проверка точного FPS, артефактов движения, склеек и синхронизации звука.

17 сентября 2026 года Runway добавила enhance_frame_rate в Runway Dev. Операция вызывается через video upscale endpoint и принимает 24, 25, 30, 48, 50, 60, 120, 23_98 (23,98 fps), 29_97 (29,97 fps) и 59_94 (59,94 fps); один входной файл ограничен 300 секундами, а в сообщении о запуске указано 1 credit за 2 секунды.

Не принимайте результат только потому, что движение стало плавнее. Сначала выберите точную частоту по требованиям приёмки, затем проверьте метаданные, рискованные движения, склейки и синхронизацию в начале, середине и конце, а после этого испытайте файл на реальной таймлинии и конечной платформе.

Сначала выберите частоту сдачи; без точной спецификации остановитесь

Сначала возьмите точное значение из требований монтажной таймлинии, вещателя, рекламной платформы или клиента. 29_97 и 30, как и 59_94 и 60, выглядят почти одинаково, но неверная подмена в длинной программе, вещании или проекте со смешанными источниками может привести к повторному транскодированию или обработке.

ЦельТипичное основание выбораЧто подтвердить перед сдачей
23_98 / 24Таймлиния или заказчик явно требует кинематографическую частотуНужны именно 23,98, а не целые 24
25 / 50Производственная цепочка 25/50 fps или региональная спецификацияТаймлиния, титры, звук и остальные материалы используют ту же частоту
29_97 / 30В требованиях прямо указано одно из значенийНе подменять одно другим без согласования
59_94 / 60Динамичный материал или платформа прямо требует high frame rateБолее плавное движение не означает восстановление утраченных деталей
48 / 120Специальная таймлиния, замедление или высокочастотная выдачаИспользовать только при явной необходимости; больше не всегда лучше

Если в задаче сказано только «сделать плавнее», запросите точную спецификацию. Иначе можно получить корректный файл 60 fps, который всё равно нельзя безоговорочно положить на таймлинию 59,94 fps.

Зафиксируйте исходник, чтобы потом найти причину ошибки

До обработки сохраните частоту, длительность, кодек и параметры аудиодорожек исходника. Без этой базы трудно понять, откуда взялись пропавшая дорожка, изменившаяся длительность или замороженный хвост: из исходника, результата Runway или последующего транскода.

  1. Имя исходного файла, длительность, разрешение, кодек и исходную частоту кадров.
  2. Постоянная ли это частота (CFR) или переменная (VFR).
  3. Количество аудиодорожек, sample rate, число каналов и примерную длительность.
  4. Целевую частоту и источник требования, например: «клиент требует 59_94».
  5. Три–пять рискованных таймкодов: быстрые панорамы, руки, тонкие линии, края перекрытий, вспышки, переходы, субтитры или UI.
  6. Не менее трёх точек синхронизации звука и изображения — в начале, середине и конце.

Такая база не позволит свести проверку к фразе «стало плавнее», пропустив изменение длительности, исчезнувшую дорожку или несовместимость с форматом сдачи.

Сначала убедитесь, что локальное видео подходит для обработки

До вызова API проверьте формат, длительность и размер. Один вход enhance_frame_rate не может быть длиннее 300 секунд, а файл для ephemeral upload должен занимать от 512 байт до 200 МБ. Предпочтительны поддерживаемые контейнеры и кодеки, например MP4 с H.264, H.265 или AV1; более длинную программу разделите по естественным склейкам.

Если видео уже находится в объектном хранилище, его HTTPS-адрес можно передать прямо в videoUri. Адрес должен использовать домен, а не IP, поддерживать HEAD, возвращать корректные Content-Type и Content-Length и не зависеть от редиректов; лимит видео по URL — 32 МБ. Для обычного локального мастера ephemeral upload проще, потому что не требует такой настройки хостинга.

Убедитесь также, что на аккаунте есть купленные credits. В сообщении о запуске указано 1 credit за 2 секунды, но правило округления неполных интервалов не описано, поэтому сохраняйте estimatedCost из ответа на отправку и итоговый cost из записи задачи.

Этот скрипт загружает файл, отправляет задачу, ждёт и скачивает результат

Пример использует REST API и не прячет ключевые действия внутри SDK. Он безопасно запрашивает API Key, проверяет длительность и размер локального файла, создаёт ephemeral upload, передаёт видео, запускает повышение частоты, опрашивает задачу раз в пять секунд и скачивает успешный результат.

Установите зависимость Python и убедитесь, что доступен ffprobe:

python3 -m pip install requests

Сохраните код как runway_fps.py:

from __future__ import annotations

import getpass, json, os, random, subprocess, sys, time
from pathlib import Path
import requests

API = "https://api.dev.runwayml.com"
FPS = {"24", "25", "30", "48", "50", "60", "120", "23_98", "29_97", "59_94"}
RETRYABLE = {429, 502, 503, 504}


def api(session, method, path, body=None):
    for attempt in range(6):
        response = session.request(method, API + path, json=body, timeout=60)
        if response.status_code < 400:
            return response
        if response.status_code in RETRYABLE and attempt < 5:
            time.sleep((2**attempt) * (1 + random.random() * 0.5))
            continue
        raise RuntimeError(f"HTTP {response.status_code}: {response.text}")
    raise RuntimeError("RETRY_LIMIT_REACHED")


def main():
    if len(sys.argv) not in {3, 4}:
        raise SystemExit("python runway_fps.py INPUT_VIDEO TARGET_FPS [OUTPUT_VIDEO]")

    source = Path(sys.argv[1])
    target = sys.argv[2]
    output = Path(sys.argv[3]) if len(sys.argv) == 4 else Path(f"runway-{target}fps.mp4")

    if target not in FPS:
        raise SystemExit(f"UNSUPPORTED_TARGET_FRAMERATE: {target}")
    if not source.is_file():
        raise SystemExit(f"INPUT_NOT_FOUND: {source}")
    if not 512 <= source.stat().st_size <= 200 * 1024 * 1024:
        raise SystemExit(f"INVALID_UPLOAD_SIZE_BYTES: {source.stat().st_size}")

    duration = float(subprocess.run(
        ["ffprobe", "-v", "error", "-show_entries", "format=duration",
         "-of", "default=noprint_wrappers=1:nokey=1", str(source)],
        check=True, capture_output=True, text=True,
    ).stdout.strip())
    if not 0 < duration <= 300:
        raise SystemExit(f"INVALID_DURATION_SECONDS: {duration}")

    key = os.getenv("RUNWAYML_API_SECRET") or getpass.getpass("RUNWAYML_API_SECRET: ")
    session = requests.Session()
    session.headers.update({
        "Authorization": f"Bearer {key}",
        "X-Runway-Version": "2024-11-06",
        "Content-Type": "application/json",
    })

    upload_init = api(session, "POST", "/v1/uploads", {
        "filename": source.name,
        "type": "ephemeral",
    }).json()
    with source.open("rb") as handle:
        upload = requests.post(
            upload_init["uploadUrl"],
            data=upload_init["fields"],
            files={"file": (source.name, handle)},
            timeout=300,
        )
    if upload.status_code >= 400:
        raise RuntimeError(
            f"UPLOAD_FAILED_REQUEST_NEW_UPLOAD: HTTP {upload.status_code}: {upload.text}"
        )

    created = api(session, "POST", "/v1/video_upscale", {
        "model": "enhance_frame_rate",
        "videoUri": upload_init["runwayUri"],
        "targetFramerate": target,
    }).json()
    task_id = created["id"]
    print(json.dumps({"id": task_id, "estimatedCost": created.get("estimatedCost")}, indent=2))

    while True:
        task = api(session, "GET", f"/v1/tasks/{task_id}").json()
        status = task["status"]
        if status in {"PENDING", "THROTTLED", "RUNNING"}:
            time.sleep(5)
            continue
        if status == "SUCCEEDED":
            urls = task.get("output") or []
            if not urls:
                raise RuntimeError("SUCCEEDED_WITHOUT_OUTPUT")
            with requests.get(urls[0], stream=True, timeout=300) as download:
                download.raise_for_status()
                with output.open("wb") as saved:
                    for chunk in download.iter_content(1024 * 1024):
                        if chunk:
                            saved.write(chunk)
            break
        if status == "FAILED":
            raise RuntimeError(json.dumps({
                "status": status,
                "failure": task.get("failure"),
                "failureCode": task.get("failureCode"),
                "cost": task.get("cost"),
            }, ensure_ascii=False))
        if status == "CANCELLED":
            raise RuntimeError(json.dumps({"status": status, "cost": task.get("cost")}))
        raise RuntimeError(f"UNKNOWN_TASK_STATUS: {status}")

    subprocess.run([
        "ffprobe", "-v", "error", "-show_entries",
        "stream=codec_name,width,height,r_frame_rate,avg_frame_rate,time_base,duration:format=duration",
        "-of", "json", str(output),
    ], check=True)
    print(output.resolve())


if __name__ == "__main__":
    main()

Пример запуска для преобразования input.mp4 в 60 fps с сохранением в output-60fps.mp4:

python3 runway_fps.py input.mp4 60 output-60fps.mp4

Введите ключ только после приглашения RUNWAYML_API_SECRET:. Значение не отображается и не попадает в историю shell; скрипт не записывает его в файл. Если одноимённая переменная окружения уже настроена безопасно, скрипт использует её.

Разберите три этапа API, которые выполняет скрипт

Генерация завершена только после успеха всех трёх этапов. Имена полей чувствительны к регистру: в REST JSON нужны именно videoUri и targetFramerate.

ЭтапЗапросОбязательные данныеПризнак успеха
Инициализация загрузкиPOST https://api.dev.runwayml.com/v1/uploadsfilename, type: "ephemeral"Возвращены uploadUrl, fields, runwayUri
Отправка обработкиPOST https://api.dev.runwayml.com/v1/video_upscalemodel: "enhance_frame_rate", videoUri, targetFramerateВозвращены id задачи и estimatedCost
Получение задачиGET https://api.dev.runwayml.com/v1/tasks/{id}ID задачи в путиstatus: "SUCCEEDED" и непустой output

После инициализации отправьте multipart POST на uploadUrl, передав без изменений все значения из fields и файл в поле file. Только после успешной передачи runwayUri можно использовать в запросе повышения частоты. URI действует 24 часа.

После успеха сразу скачайте и сохраните файл

Пока статус равен PENDING, THROTTLED или RUNNING, продолжайте ждать; Runway не рекомендует ожидать обновления одной задачи чаще одного раза в пять секунд. Читайте output[0] только при SUCCEEDED. FAILED и CANCELLED являются терминальными неуспешными состояниями.

Ссылки результата обычно истекают через 24–48 часов, поэтому сразу скачайте файл в собственное постоянное хранилище и не используйте временный URL как ссылку для заказчика. Если ссылка истекла, сначала снова запросите ту же задачу и получите свежий URL, а не запускайте платную обработку заново. Скачивание подтверждает завершение API-задачи, но не заменяет проверки ниже.

Обрабатывайте ошибки по типу, а не повторяйте всё подряд

Если multipart POST на uploadUrl не удался, не используйте тот же presigned URL повторно: снова вызовите /v1/uploads и начните загрузку заново. При 400, 401, 404 или 405 сначала исправьте вход, ключ, ресурс или метод. Пример автоматически повторяет только 429, 502, 503 и 504 с экспоненциальной задержкой и jitter.

При FAILED сохраните failure, failureCode и cost: SAFETY.* не повторяйте; для ASSET.INVALID сначала исправьте длительность, размер или кодек; перед повтором INTERNAL.BAD_OUTPUT.* проверьте входные данные; после задержки можно повторить INPUT_PREPROCESSING.INTERNAL, INTERNAL, отсутствие кода или THIRD_PARTY.UNAVAILABLE. Не запускайте бесконечный цикл одинаковых запросов.

Шаг 1. Через ffprobe подтвердите, что файл действительно соответствует цели

Сначала через ffprobe проверьте среднюю частоту, time base, фактическое число кадров, длительность и аудиопотоки. Одного поля FPS в Finder, Проводнике или плеере для приёмки недостаточно.

ffprobe -v error -select_streams v:0 \
  -show_entries stream=codec_name,width,height,r_frame_rate,avg_frame_rate,time_base,duration \
  -of json output.mp4
ffprobe -v error -select_streams v:0 -count_frames \
  -show_entries stream=nb_read_frames,avg_frame_rate,r_frame_rate,duration \
  -of json output.mp4
ffprobe -v error \
  -show_entries format=duration:stream=index,codec_type,codec_name,sample_rate,channels,duration \
  -of json output.mp4

Проверьте:

  • avg_frame_rate соответствует цели или её равнозначной дробной записи.
  • Между r_frame_rate и avg_frame_rate нет необъяснимого конфликта; большая разница требует проверки на VFR.
  • Для файла, близкого к CFR, nb_read_frames примерно соответствует длительности, умноженной на целевой fps.
  • Длительность результата совпадает с исходником, в конце нет обрезанных или добавленных замороженных кадров.
  • Разрешение, кодек и аудиопотоки соответствуют спецификации сдачи.
  • Длительность аудиопотока не отличается от видеопотока неожиданно сильно.

Для 29,97 и 59,94 инструменты часто показывают 30000/1001 и 60000/1001. Дробная запись сама по себе не является ошибкой.

Шаг 2. Сначала проверьте кадры, где дефекты заметнее всего

Начните с быстрых движений, краёв перекрытий, мелкого текста и склеек: там ошибки интерполяции проявляются быстрее всего. Смотрите следующие участки при масштабе 100%, покадрово или на сниженной скорости:

  • быстрые панорамы, трекинг и быстро движущиеся объекты;
  • кисти, пальцы, волосы, оправы очков и губы;
  • заборы, жалюзи, сетки, мелкий текст и тонкие линии интерфейса;
  • края объектов, которые перекрывают или открывают фон;
  • воду, дым, частицы, листья и высокочастотные текстуры;
  • вспышки, жёсткие склейки, наплывы и кадры рядом со сменой плана.

Ищите воспроизводимые дефекты, а не абстрактную «резкость»: двойные контуры, ghosting, изгибающиеся края, исчезновение мелких объектов на один кадр, пульсацию текстуры, деформацию конечностей, смешанные кадры на склейке или дрожание статичного текста.

Для каждого дефекта сохраните точный таймкод, целевую частоту, фрагмент источника и результата. Так можно отличить проблему исходника от нового дефекта или особенностей декодера плеера.

Шаг 3. Проверьте синхронизацию в начале, середине и конце

Нормальная синхронизация в начале не означает, что она сохранится до конца; проверьте начало, середину и конец, чтобы отличить постоянное смещение от нарастающего drift. Действуйте так:

  1. Найдите заметный якорь в начале: хлопок, взрывной согласный, удар, приземление или визуальную склейку.
  2. Повторите проверку в середине и конце.
  3. Одинаковое смещение в трёх точках больше похоже на постоянную задержку.
  4. Ошибка, растущая к концу, указывает на возможную проблему длительности, time base или интерпретации frame rate.
  5. Для lip sync проверьте начало, середину и конец непрерывной реплики, а не один слог.

В записи о запуске не описано поведение аудио. Поэтому нельзя заранее считать, что дорожка всегда остаётся неизменной или автоматически синхронизируется. Решение принимается по выходному файлу.

Шаг 4. Повторите проверку на реальной таймлинии и платформе

Обязательно проверьте файл на реальной монтажной таймлинии и конечной платформе: NLE или повторный transcode могут переопределить частоту, изменить скорость или потерять аудиодорожку. Выполните как минимум две проверки:

  • Поместите файл на целевую монтажную таймлинию и убедитесь, что программа не переопределяет частоту, не меняет скорость и не теряет аудиодорожку.
  • Проверьте файл на конечной платформе или устройстве и убедитесь, что повторное кодирование не изменило частоту, субтитры и синхронизацию.

Если платформа делает ещё один transcode, сохраните и результат Runway, и версию платформы. Исследуйте их отдельно, прежде чем обвинять исходный выходной файл.

По этой таблице решите: принять, переделать или оставить исходный фрагмент

Файл можно сдавать только после прохождения всех критичных пунктов. Если не прошёл один план, сначала переделайте этот фрагмент или оставьте исходный, а не запускайте заново всю программу.

ПроверкаУсловие прохожденияЧто делать при ошибке
Целевая частотаТочное соответствие спецификации; 29,97/59,94 не подменены 30/60Исправить target или интерпретацию таймлинии
Длительность и кадрыДлительность совпадает; для CFR число кадров близко к расчётуПроверить VFR, обрезку, замороженный хвост и time base
Разрешение и кодекСоответствуют требованиям редактора или каналаПерепаковать или перекодировать по спецификации
Быстрое движениеНет неприемлемого двоения, изгибов и исчезновения объектовОтметить таймкоды; выбрать другую цель или оставить исходный фрагмент
Склейки и вспышкиНет смешанных, повторных кадров и аномального мерцанияРазделить по естественной склейке, обработать снова и проверить стык
Текст и UIСимволы, тонкие линии и статичные элементы стабильныНаложить графику заново на посте, а не обрабатывать вместе с видео
СинхронизацияНет заметного смещения или drift в начале, середине и концеСравнить длительности/time base, затем выровнять или перекодировать
Целостность файлаФайл декодируется целиком, конец и аудиодорожки на местеСкачать заново, перепаковать или повторить задачу

В этих случаях не повышайте частоту с 60 до 120 fps

Остановитесь на минимальной частоте, которая выполняет спецификацию, если 120 fps лишь увеличивают размер и последующую нагрузку. Не повышайте частоту в следующих случаях:

  • спецификация требует только 24, 25, 29,97 или 30 fps;
  • в исходнике уже есть сильный ghosting, блоки сжатия или motion blur;
  • субтитры, UI или тонкие линии стали менее стабильными;
  • причина рассинхронизации ещё не найдена;
  • платформа всё равно перекодирует видео в меньшую частоту;
  • видимой пользы нет, а нагрузка на хранение, декодирование и последующий transcode растёт.

Frame rate — параметр доставки, а не отдельный балл качества. Критерий прохождения: файл соответствует требуемой частоте и не получил неприемлемых новых дефектов.

Выполните весь путь за десять шагов

Чтобы сократить переделки, сначала зафиксируйте спецификацию и исходник, затем загрузите, отправьте, дождитесь и сохраните результат, после чего выполните техническую и визуальную приёмку.

  1. Выберите точный targetFramerate по требованиям downstream-системы.
  2. Через ffprobe сохраните частоту, длительность, аудио и рискованные таймкоды; подтвердите длительность не более 300 секунд.
  3. Для локального файла вызовите POST /v1/uploads и сохраните uploadUrl, fields, runwayUri.
  4. Отправьте multipart-форму на uploadUrl; при сбое запросите новую загрузку.
  5. Вызовите POST /v1/video_upscale с model, videoUri, targetFramerate.
  6. Сохраните id задачи и estimatedCost.
  7. Раз в пять секунд вызывайте GET /v1/tasks/{id} до терминального статуса.
  8. При SUCCEEDED скачайте и сохраните output; FAILED и CANCELLED обрабатывайте по типу ошибки.
  9. Проверьте фактическую частоту, длительность, артефакты, склейки и синхронизацию через ffprobe и покадровый просмотр.
  10. Испытайте файл на реальной таймлинии и конечной платформе, затем передавайте заказчику.

Официальные материалы: Models, Inputs, Uploads, Video upscale API Reference, Task API Reference, Outputs, HTTP errors, Task failures и API Changelog. Поля интерфейса и шаги проверены 26 сентября 2026 года.

Готовы оптимизировать LLM workflow?

Подключите единый API, управляйте ключами и контролируйте расходы на AI-модели в BetterToken.

Начать бесплатно