← Все статьи DaVinci Resolve API
DaVinci Resolve APIПродвинутыйRender

Как запустить рендер всего Timeline через Python API

SetRenderRange Entire Timeline, SetRenderSettings, AddRenderJob и StartRendering

Рабочий пример полного рендера активного Timeline: очистить очередь, выбрать Entire Timeline, задать папку вывода, создать render job и запустить только новую задачу.

API

Resolve Scripting API

Язык

Python

Resolve

19–20+

Требуется

Запущенный Resolve

Синтаксис

result = api_method()

Параметры

  • Параметры зависят от конкретного метода Resolve Scripting API и показаны в рабочем примере.

Возвращает

Возвращаемое значение нужно проверять перед следующим шагом автоматизации.

Полный рабочий пример Pythonкод можно использовать как основу скрипта
import os
import sys
from pathlib import Path


def import_resolve_module():
    try:
        import DaVinciResolveScript as dvr
        return dvr
    except ImportError:
        search_paths = [
            os.environ.get("RESOLVE_SCRIPT_API", ""),
            os.environ.get("RESOLVE_MODULES", ""),
            r"C:\\ProgramData\\Blackmagic Design\\DaVinci Resolve\\Support\\Developer\\Scripting\\Modules",
            "/opt/resolve/Developer/Scripting/Modules",
            "/opt/BlackmagicDesign/DaVinciResolve/Developer/Scripting/Modules",
            "/Library/Application Support/Blackmagic Design/DaVinci Resolve/Developer/Scripting/Modules",
            str(Path.home() / "Library/Application Support/Blackmagic Design/DaVinci Resolve/Developer/Scripting/Modules"),
        ]
        for path in search_paths:
            if path and os.path.isdir(path) and path not in sys.path:
                sys.path.append(path)
        import DaVinciResolveScript as dvr
        return dvr


def safe_call(obj, name, *args, **kwargs):
    try:
        fn = getattr(obj, name, None)
        if callable(fn):
            return fn(*args, **kwargs)
    except Exception:
        return None
    return None


def get_project_and_timeline():
    dvr = import_resolve_module()
    resolve = dvr.scriptapp("Resolve")
    if not resolve:
        raise RuntimeError("DaVinci Resolve API недоступен")

    project_manager = resolve.GetProjectManager()
    project = project_manager.GetCurrentProject() if project_manager else None
    if not project:
        raise RuntimeError("Нет открытого проекта DaVinci Resolve")

    timeline = project.GetCurrentTimeline()
    if not timeline:
        raise RuntimeError("Нет активного Timeline")

    return resolve, project, timeline

import time
from datetime import datetime


def frames_to_tc(frame: int, fps: float) -> str:
    fps_i = max(1, int(round(fps)))
    total = int(round(frame))
    ff = total % fps_i
    seconds = total // fps_i
    hh = seconds // 3600
    mm = (seconds % 3600) // 60
    ss = seconds % 60
    return f"{hh:02d}:{mm:02d}:{ss:02d}:{ff:02d}"


def clear_render_queue(project) -> None:
    safe_call(project, "StopRendering")
    jobs = safe_call(project, "GetRenderJobs") or safe_call(project, "GetRenderJobList") or []
    for job in jobs:
        job_id = job.get("JobId") if isinstance(job, dict) else job
        if job_id is not None:
            safe_call(project, "DeleteRenderJob", job_id)


def render_entire_timeline(output_dir: str) -> str:
    resolve, project, timeline = get_project_and_timeline()
    target_dir = Path(output_dir).expanduser()
    target_dir.mkdir(parents=True, exist_ok=True)

    clear_render_queue(project)
    safe_call(project, "SetRenderRange", "Entire Timeline")
    safe_call(timeline, "ClearInOutPoints")

    base_name = f"{safe_call(project, 'GetName') or 'Project'}_{datetime.now():%Y%m%d_%H%M%S}"
    project.SetRenderSettings({
        "TargetDir": str(target_dir),
        "CustomName": base_name,
        "ExportVideo": True,
        "ExportAudio": True,
        "IndividualClips": False,
        "UniqueFilenames": True,
    })

    job_id = project.AddRenderJob()
    if not job_id:
        raise RuntimeError("AddRenderJob вернул пустой результат")

    if not safe_call(project, "StartRendering", [job_id]):
        if not safe_call(project, "StartRendering", job_id):
            raise RuntimeError("StartRendering не запустился")

    while safe_call(project, "IsRenderingInProgress"):
        time.sleep(0.8)

    status = safe_call(project, "GetRenderJobStatus", job_id) or {}
    print("Render status:", status)
    return str(job_id)


print("Render job:", render_entire_timeline(r"D:\\renders"))

Документация

Что делает пример

Код очищает очередь рендера, выбирает диапазон Entire Timeline, передает базовые Render Settings, создает новую задачу и запускает только ее. После старта скрипт ждет окончания рендера через IsRenderingInProgress.

Почему очередь нужно контролировать

Если в Render Queue остались старые задачи, безадресный StartRendering может запустить не то, что нужно. Поэтому пример сначала удаляет старые jobs и затем пробует стартовать свежий job по id.

Что остается настроить

Формат и кодек можно задать отдельным блоком через SetRenderSettings или заранее загруженным render preset. В этой статье показан основной каркас запуска рендера.

Разбор примера

1

Подключение к Resolve

Пример начинает работу с подключения к запущенному DaVinci Resolve через официальный Python-модуль.

2

Проверка проекта

Перед вызовами Media Pool, Timeline или Render Queue код проверяет наличие открытого проекта.

3

Вызов метода API

Основной блок выполняет задачу статьи: как запустить рендер всего timeline через python api.

4

Проверка результата

После вызова API результат проверяется, чтобы скрипт не продолжал работу с пустым объектом или не созданной задачей.

Особенности Resolve API

  • Папка вывода должна существовать или успешно создаваться скриптом.
  • Для стабильного production-рендера лучше явно задать формат и кодек.
  • Некоторые версии Resolve по-разному принимают job_id в StartRendering.
  • Всегда проверяйте AddRenderJob перед запуском.

Частые ошибки

Resolve API недоступен

Причина: Приложение не запущено или Python не видит DaVinciResolveScript.

Решение: Запустите Resolve и проверьте путь к Developer/Scripting/Modules.

Метод вернул None или False

Причина: В Resolve нет нужного проекта, Timeline, клипов, preset или доступа к папке.

Решение: Проверьте входные данные и добавьте явную проверку результата после каждого важного вызова API.

Скрипт работает только на одной машине

Причина: Пути к файлам или папкам Resolve зашиты под конкретную систему.

Решение: Вынесите пути в переменные и добавьте стандартные пути Windows, Linux и macOS.

Следующий шаг

Следующий шаг зависит от задачи: импорт медиа, создание Timeline или запуск рендера.

Связанные статьи API