ВИДЕОМОНТАЖЁРDAVINCI RESOLVE · ВИДЕО · AI

RESOLVE API / FIELD GUIDE / 03

Как получить текущий проект DaVinci Resolve через Python

Приложение, проект и активный таймлайн — три разных уровня состояния.

Получаем Project Manager, проверяем текущий проект по имени и ID, читаем число таймлайнов и активный Timeline. Пустой таймлайн допускается; автоматическая загрузка и создание проекта исключены.

НА ВЫХОДЕ

Снять ограниченный отчёт о текущем проекте и активном таймлайне, не выбирая за пользователя другой объект.

PYTHON / RESOLVEУЧЕБНАЯ МОДЕЛЬ
01manager = resolve.GetProjectManager()

Менеджер относится к подключённой библиотеке проектов, а не к папке с видео на диске.

ПРОВЕРКА

Объект менеджера получен до следующих вызовов.

Переключатели меняют объяснение. Ничего не подключается к Resolve и не запускается на вашем компьютере.

01 / BEFORE THE CODE

До кода — условия запуска.

01

Запущенный Resolve Studio

Основной маршрут — внешний локальный Python и настольная Studio. В релизе 21.1 Blackmagic относит Python scripting к Studio; прежний опыт с Free не подтверждает текущую совместимость. Не используйте Fusion-подключение как обход ограничения редакции.

02

Python и библиотека одной установки

Для синтаксиса этих примеров нужен Python 3.8 или новее. Отдельно нужны совместимые 64-битные Python и native-библиотека Resolve. Номер Python, архитектуру и ограничения сверяйте с README своей установки. Наличие Python 3 само по себе не гарантирует загрузку бинарного модуля.

03

Локальный доступ, без сети

Для внешнего скрипта проверьте Preferences → System → General → External scripting using → Local, если этот пункт есть в вашей версии. Network не нужен для примеров на этом компьютере. Не повышайте права процесса до администратора как универсальное исправление.

04

Открытый тестовый проект

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

Ориентируйтесь на актуальные требования Studio и документацию установленной версии, а не на старые инструкции для консоли или Free.[1][4][3]

02 / API CONTRACT

Какой объект. Какой метод. Какой результат.

ResolveGetProjectManager()
Вход
Без аргументов.
Возвращает
ProjectManager текущей библиотеки.
Проверить
Проверить непустой объект.
ProjectManagerGetCurrentProject()
Вход
Без аргументов.
Возвращает
Текущий открытый Project.
Проверить
Если отсутствует — остановиться, а не открывать похожий проект.
ProjectGetName() / GetUniqueId()
Вход
Без аргументов.
Возвращает
Читаемое имя и идентификатор.
Проверить
Имя не является уникальным адресом во всех библиотеках.
ProjectGetTimelineCount()
Вход
Без аргументов.
Возвращает
Количество таймлайнов.
Проверить
0 допустим; None и некорректный тип не превращать в 0.
ProjectGetCurrentTimeline()
Вход
Без аргументов.
Возвращает
Активный Timeline; может отсутствовать.
Проверить
Не вызывать методы Timeline у пустого результата.

Контракты методов Resolve описаны Blackmagic; Python и авторские helper обозначены отдельно. Дополнительные проверки — устройство наших примеров. Непустой объект не доказывает совместимость всего API.[3]

03 / UNDERSTAND

Менеджер не является проектом

GetProjectManager возвращает объект для операций с библиотекой и проектами. GetCurrentProject вызывается уже у этого менеджера. Имя проекта читает project.GetName(), а не print(project): строковое представление native-объекта не заменяет его свойства.

Запрос не ищет проект по имени и не открывает его. Это полезное ограничение перед автоматизацией: пользователь явно выбирает рабочую цель в Resolve, а скрипт проверяет выбранное состояние.[3]

04 / UNDERSTAND

Почему одного имени недостаточно

В разных Project Library и папках могут встречаться одинаковые названия. В примере --expect-project — дополнительная проверка точного имени, а не универсальный адрес и не разрешение на правки. Отчёт также содержит GetUniqueId; сравнивать идентичность сессии надёжнее, чем полагаться на одно название.

Для устойчивого workflow сохраняйте контекст выбранной библиотеки отдельно. Не считайте, что экспорт/импорт проекта или его копирование обязаны сохранять прежний ID. В этой статье идентификатор используется для сверки текущего объекта в рамках одного короткого чтения.

Имена и ID в выводе реальны, если скрипт запущен у вас. Прежде чем переслать JSON заказчику или в поддержку, проверьте, нет ли в названии проекта персональных данных.[3]

05 / UNDERSTAND

Проект без таймлайна — нормальный случай

GetTimelineCount сообщает количество таймлайнов, а GetCurrentTimeline возвращает активный объект. Пример допускает count=0 и current_timeline=null. Если ваша следующая задача — импорт в Media Pool, активный таймлайн может вообще не требоваться.

Если следующая операция относится к конкретному Timeline, задайте отдельное требование: получить нужный объект, проверить его имя/ID и лишь затем продолжать. Не используйте автоматически GetTimelineByIndex(1) как «тот самый» таймлайн: порядок списка не выражает намерение пользователя.[3]

06 / UNDERSTAND

Повторное чтение — проверка, но не транзакция

В конце пример повторно получает текущий проект и сравнивает ID. Если пользователь переключил проект во время чтения, отчёт отбрасывается с ошибкой. Это защищает от части изменений состояния между вызовами.

Последовательность API-вызовов не становится атомарной: таймлайн может смениться внутри того же проекта, проект может поменяться и вернуться, а содержимое — измениться другим участником. Поэтому здесь нет формулировки «полностью согласованный снимок». Для будущих правок нужны отдельные предусловия и исключение параллельных действий.[3]

07 / UNDERSTAND

Как использовать результат дальше

Держите зависимости явными: приложение → менеджер → проект → опциональный таймлайн. Не прячьте получение проекта внутрь функции, которая при неудаче молча создаёт новый. Это особенно важно, когда тот же код затем используется для удаления клипов или рендера.

После успешного чтения можно перейти к отдельной статье по Media Pool или таймлайнам. Сам этот отчёт не подтверждает, что выбран правильный диапазон, материал находится онлайн или настройки экспорта соответствуют заданию.[3]

PYTHON / COMPLETE EXAMPLE

Прочитайте код. Затем запускайте осознанно.

Два файла в одной папке

Скачайте current_project.py и resolve_api_connection.py либо возьмите комплект из пяти скриптов. Helper написан нами; официальный модуль DaVinciResolveScript и нативная библиотека должны браться из вашей установки Resolve.

Скачать все примеры с инструкцией (.zip) ↓
current_project.py
Скачать .py
"""Read the current project and optional timeline. No project is opened or created."""
import argparse
import json

from resolve_api_connection import connect, project_manager


def read_current(manager, expected_name=None):
    project = manager.GetCurrentProject()
    if not project:
        raise RuntimeError("No current project. Open the intended project manually.")
    name, project_id = project.GetName(), project.GetUniqueId()
    if not isinstance(name, str) or not isinstance(project_id, str) or not project_id:
        raise RuntimeError("Project identity is incomplete")
    if expected_name is not None and name != expected_name:
        raise RuntimeError("Current project name does not match --expect-project")
    timeline = project.GetCurrentTimeline()
    count = project.GetTimelineCount()
    if not isinstance(count, int) or isinstance(count, bool) or count < 0:
        raise RuntimeError("Timeline count could not be read")
    result = {
        "project": {"name": name, "id": project_id},
        "timeline_count": count,
        "current_timeline": None,
    }
    if timeline:
        timeline_name = timeline.GetName()
        timeline_id = timeline.GetUniqueId()
        if not timeline_name or not timeline_id:
            raise RuntimeError("Timeline identity is incomplete")
        result["current_timeline"] = {"name": timeline_name, "id": timeline_id}
    current = manager.GetCurrentProject()
    if not current or current.GetUniqueId() != project_id:
        raise RuntimeError("Active project changed during reading. Discard this report and inspect Resolve.")
    # Two identity reads detect some changes; they do not make the snapshot atomic.
    return result


def main(argv=None):
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--expect-project", help="Optional exact name check, not a globally unique identity")
    args = parser.parse_args(argv)
    result = read_current(project_manager(connect()), args.expect_project)
    print(json.dumps(result, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()

Общий helper подключения — посмотреть и скачать

Этот файл находит и загружает установленный мост. При импорте Python может записывать кэш байткода, а нативный вызов — зависнуть; это не песочница и не механизм тайм-аута. Используйте доверенную локальную установку.

resolve_api_connection.py
Скачать .py
"""Load the installed Blackmagic module; do not install a similarly named package.

This helper uses standard desktop installation paths or RESOLVE_SCRIPT_API.
It does not enable scripting, start Resolve, open projects or retry API calls.
Validate Python/native-library compatibility against your installed README.txt.
"""
from __future__ import annotations

import importlib.util
import os
from pathlib import Path
import struct
import sys


class ResolveConnectionError(RuntimeError):
    """An explicit environment, module, or application-connection failure."""


def scripting_root() -> Path:
    configured = os.environ.get("RESOLVE_SCRIPT_API")
    if configured is not None:
        if not configured.strip() or configured != configured.strip():
            raise ResolveConnectionError("RESOLVE_SCRIPT_API is empty or has outer whitespace")
        if configured.startswith(('"', "'")) or configured.endswith(('"', "'")):
            raise ResolveConnectionError("Do not store literal outer quotes in RESOLVE_SCRIPT_API")
        root = Path(os.path.expandvars(configured)).expanduser()
    elif sys.platform == "win32":
        root = Path(os.environ.get("PROGRAMDATA", r"C:\ProgramData")) / "Blackmagic Design/DaVinci Resolve/Support/Developer/Scripting"
    elif sys.platform == "darwin":
        root = Path("/Library/Application Support/Blackmagic Design/DaVinci Resolve/Developer/Scripting")
    elif sys.platform.startswith("linux"):
        root = Path("/opt/resolve/Developer/Scripting")
    else:
        raise ResolveConnectionError("Set RESOLVE_SCRIPT_API for this platform/installation")
    if not root.is_absolute():
        raise ResolveConnectionError("RESOLVE_SCRIPT_API must be an absolute Scripting directory")
    return root


def module_file() -> Path:
    # RESOLVE_SCRIPT_API points to Scripting, not its Modules subdirectory.
    return scripting_root() / "Modules" / "DaVinciResolveScript.py"


def load_resolve_module():
    if struct.calcsize("P") * 8 != 64:
        raise ResolveConnectionError("Use a compatible 64-bit Python interpreter")
    source = module_file()
    if not source.is_file():
        raise ResolveConnectionError("Official DaVinciResolveScript.py not found at: " + str(source))
    configured_lib = os.environ.get("RESOLVE_SCRIPT_LIB")
    if configured_lib is not None:
        lib = Path(os.path.expandvars(configured_lib)).expanduser()
        if not lib.is_absolute() or not lib.is_file():
            raise ResolveConnectionError("RESOLVE_SCRIPT_LIB must name the installed native library file")
    name = "DaVinciResolveScript"
    spec = importlib.util.spec_from_file_location(name, source)
    if spec is None or spec.loader is None:
        raise ResolveConnectionError("Cannot create a loader for the official module")
    previous = sys.modules.get(name)
    module = importlib.util.module_from_spec(spec)
    sys.modules[name] = module
    try:
        spec.loader.exec_module(module)
        # Blackmagic's wrapper can replace its sys.modules entry with a native module.
        loaded = sys.modules[name]
        if not callable(getattr(loaded, "scriptapp", None)):
            raise ResolveConnectionError("Loaded module does not expose scriptapp")
        return loaded
    except Exception as exc:
        if previous is None:
            sys.modules.pop(name, None)
        else:
            sys.modules[name] = previous
        raise ResolveConnectionError("Official module was found, but loading it failed") from exc


def connect():
    module = load_resolve_module()
    try:
        resolve = module.scriptapp("Resolve")
    except Exception as exc:
        raise ResolveConnectionError("scriptapp failed; inspect the original exception") from exc
    if not resolve:
        raise ResolveConnectionError("No Resolve object: check running Studio, Local access and Python environment")
    return resolve


def project_manager(resolve):
    manager = resolve.GetProjectManager()
    if not manager:
        raise ResolveConnectionError("Resolve connected, but Project Manager is unavailable")
    return manager

Команды запуска

Прочитать текущий проект

Прочитать текущий проект
python current_project.py

Нужны запущенный Resolve и открытый тестовый проект; helper лежит рядом.

С дополнительной проверкой имени

С дополнительной проверкой имени
python current_project.py --expect-project "API_Demo_Project"

Это точное сравнение имени, не поиск и не открытие проекта.

Что делает код

  1. Получить текущий объект

    Project Manager запрашивает уже открытый проект, без поиска или загрузки.

  2. Прочитать идентичность

    Проверяются имя и ID; необязательный --expect-project ограничивает ожидаемое имя.

  3. Разрешить пустой Timeline

    В JSON передаётся null, когда активного таймлайна нет; число таймлайнов читается отдельно.

  4. Перечитать проект

    Перед возвратом результата сравнивается ID текущего проекта с первоначальным.

Границы, которые важно сохранить

Нулевое число таймлайнов не является ошибкой подключения.

Project Library — не директория импортируемых видеоматериалов.

Отчёт содержит имена и ID, поэтому его нужно проверить перед публикацией.

DEBUG / OBSERVATION FIRST

Ошибка — отправная точка, не готовый диагноз.

No current project

Возможная причинаНет открытого проекта, хотя приложение может быть доступно.

Следующая проверкаОткройте нужный тестовый проект вручную. Не добавляйте автоматическую загрузку по похожему имени.

Current project name does not match

Возможная причинаАргумент --expect-project не совпал с фактическим названием.

Следующая проверкаПроверьте выбранный проект и точное имя. Удалять проверку ради продолжения работы не нужно.

current_timeline=null

Возможная причинаНет активного таймлайна.

Следующая проверкаДля чтения проекта это допустимо. Для действий с Timeline выберите целевой объект отдельно.

Active project changed during reading

Возможная причинаНачальное и конечное чтение дали разные ID.

Следующая проверкаНе используйте частичный отчёт. Прекратите параллельные переключения и повторите только чтение.

PRACTICE / YOUR OWN EVIDENCE

Три состояния одного рабочего места

  1. Откройте пустой тестовый проект и получите отчёт: count и активный Timeline проверяются независимо.
  2. Создайте таймлайн вручную и повторите чтение. Сверьте его имя и ID с ожидаемым объектом.
  3. Запустите с заведомо другим --expect-project и убедитесь, что скрипт останавливается, ничего не открывая.
КРИТЕРИЙ ПРИЁМКИ

Отсутствие проекта, пустой Timeline и несовпадение имени различаются; ни один сценарий не вызывает LoadProject, CreateProject или SetCurrentTimeline.

Это условия вашей проверки, а не отчёт об испытании, уже выполненном на сайте.

FAQ

Вопросы, которые возникают на практике.

GetCurrentProject возвращает строку?

Нет: API возвращает объект проекта. Для имени вызывайте GetName(), для идентификатора — GetUniqueId().[3]

Почему проект есть, а Timeline нет?

Это разные объекты. Открытый проект может не содержать таймлайнов или не иметь активного Timeline в наблюдаемом состоянии. Проверяйте результат отдельно.[3]

Можно ли узнать путь к .drp?

Текущий проект хранится в Project Library, а .drp — отдельный экспорт. Имя проекта не является путём к файлу .drp и GetCurrentProject не создаёт такой экспорт.[3]

Повторное чтение защищает от любой гонки?

Нет. Оно обнаруживает часть смен проекта, но не делает всю последовательность атомарной и не блокирует действия другого пользователя или агента.

SOURCES / VERSION BOUNDARIES

Источники, а не подразумеваемая сертификация.

Сверка источников, офлайн-тесты Python и проверка интерфейса — разные виды подтверждения. Ни один из них не означает, что каждый пример проверен со всеми сборками Studio, ОС и версиями Python. Указанная дата — дата редакционной проверки, не сертификат живого прогона.

  1. Blackmagic Design — DaVinci Resolve Studio 21.1 release notes

    8 сентября 2026. В объявлении выпуска Python scripting отнесён к Studio. Это источник требований редакции, а не протокол испытания наших примеров.

  2. Blackmagic Design — Support Center

    Каталог обновлений проверен 5 октября 2026: опубликована ветка 21.1.1. Последний выпуск не равен минимальной версии каждого метода.

  3. Blackmagic Scripting README — snapshot 24 July 2026 (Resolve 21.0.4)

    Публичная копия первичного README Blackmagic, поддерживаемая X-Raym. По ней сверены базовые сигнатуры; это не официальный хостинг и не README 21.1.1. Оригинал своей установки: Help → Documentation → Developer → Scripting → README.txt; расположение пункта зависит от версии.

  4. Blackmagic Design — Scripting and Automation

    Официальное описание Python/Lua scripting и интеграций Studio. Нельзя переносить обещания Studio на Free без проверки конкретного выпуска.

KEEP BUILDING

Продолжайте с конкретной задачей.

API / Старт

Как подключиться к DaVinci Resolve через Python API

Настройка внешнего Python для Resolve Studio: официальный модуль, пути Windows/macOS/Linux, проверка продукта и версии. Без открытия проекта, скрытых повторов и установки случайного пакета из pip.

API / Проекты

Как создать проект DaVinci Resolve через Python API

Контролируемый CreateProject в локальной Project Library: проверка имени, библиотеки и папки, отдельный --apply, остановка при открытом проекте и проверка сохранения. Без скрытого LoadProject и автоматического удаления.

API / Timeline

Как прочитать FPS таймлайна через API

Читаем timelineFrameRate у Timeline и Project раздельно, сохраняем исходную строку, разбираем дробные значения и пометку DF. Не подставляем частоту при ошибке и не угадываем временную базу.

Вернуться в библиотеку API →MCP и AI-ассистенты →