Python Scripting with DaVinci Resolve Studio 16 on a Mac

Although DaVinci Resolve scripting capabilities are extremely limited, I found it promising to see that this sort of capability was being developed at BlackMagicDesign.

Learn about Python scripting with DaVinci Resolve Studio 16 in order to automate the repetitive process of reusing your YouTube videos for IGTV.

DaVinci Resolve Python Scripting

Why I Want to Script DaVinci Resolve

My goal was to write a Python script that would repurpose a video for YouTube as an Instagram TV video. If you’re not familiar, IGTV is a vertical video platform, so by placing my horizontal YouTube video on a vertical IGTV background template, I can publish the same video to my Instagram audience.

With full DaVinci Resolve Python scripting capabilities, here is ideally what my video scrip would do.

  1. Create a DaVinci Resolve project
  2. Set project settings such as width, height, and frame rate
  3. Import a rendered video file and IGTV background template (another video file) to the media pool
  4. Add the video file to the timeline on a track above the IGTV background template
  5. Dynamically add a text tile to the timeline on the above track
  6. Load render presets and render the video

While my script can accomplish most of these steps, DaVinci Resolve scripting capabilities are limited. So I had to improvise.

  • DaVinci Resolve scripting does not support dynamic text, so I had to add a track with static text. No getting around this.
  • Additionally, Python scripting only allows you to append clips to a single track (Track 1), so my template had to exist on Track 2 or above.

DaVinci Resolve timeline with multiple tracks

Below find out my scripting setup on my Mac as well as the full text of my Python script.

DaVinci Resolve Python Scripting Setup on a Mac

This tutorial assumes that you have Python 3 installed on your Mac with a virtual environment.

The location of DaVinci Resolve developer stuff is located at /Library/Application Support/Blackmagic Design/DaVinci Resolve/Developer. You can also access this by clicking on Help -> Developer Documentation within DaVinci Resolve.

Either change directory to this path in a terminal, or set the following environment variables according to the README.

RESOLVE_SCRIPT_API="/Library/Application Support/Blackmagic Design/DaVinci Resolve/Developer/Scripting/"
RESOLVE_SCRIPT_LIB="/Applications/DaVinci Resolve/DaVinci Resolve.app/Contents/Libraries/Fusion/fusionscript.so"
PYTHONPATH="$PYTHONPATH:$RESOLVE_SCRIPT_API/Modules/"

The provided examples in the Scripting/Examples directory are quite helpful, especially the ones highlighted below:

  • 1_sorted_timeline_from_folder.py
  • 2_compositions_from_timeline_clips.py
  • 3_grade_and_render_all_timelines.py
  • 4_display_project_and_folder_tree.py
  • 5_get_project_information.py
  • 6_get_current_media_thumbnail.py
  • python_get_resolve.py

Lastly, I do suggest you read the README.txt as it’s the only official DaVinci Resolve scripting documentation available at this point.

DaVinci Resolve Python Script

This first Python script creates a DaVinci Resolve project, sets settings, and imports the Instagram TV template video file which I designed previously into the media pool. The script also adds the IGTV template clip to the timeline.

from python_get_resolve import GetResolve
import sys

framerate = 30
width = 1080
height = 1920

project_name = 'igtv-template'
igtv_template_path = '/Users/tonyflorida/Movies/igtv/igtv-template.mov'

# Create project and set parameters
resolve = GetResolve()
project_manager = resolve.GetProjectManager()
project = project_manager.CreateProject(project_name)

if not project:
    print("Unable to create a project")
    sys.exit()

project.SetSetting("timelineFrameRate", str(framerate))
project.SetSetting("timelineResolutionWidth", str(width))
project.SetSetting("timelineResolutionHeight", str(height))

# Create mediapool and storage objects
mediapool = project.GetMediaPool()
storage = resolve.GetMediaStorage()

# Add video file to media pool
clips = storage.AddItemsToMediaPool(igtv_template_path)
# Create timeline:
timeline_name = "Timeline 1"
timeline = mediapool.CreateEmptyTimeline(timeline_name)
if not timeline:
    print("Unable to create timeline '" + timeline_name + "'")
    sys.exit()

# Add video file to timeline
mediapool.AppendToTimeline(clips[1])

While this entire script needs only to be executed once and can easily be configured manually through the DaVinci Resolve interface, this is just for demonstration purposes.

After the addition of a title and a performing manual render through the UI, this is essentially why my template IGTV template looks like.

IGTV template
A basic Instagram TV video template

I made this template project 10 minutes long since that’s the IGTV time limit for small creators at this time.

In order to reuse this template, you must export it via File -> Export Project. I saved my igtv-template.drp file to the igtv subdirectory in my Movies folder.

With the template saved, I wrote the following Python script which copies the template and works out of that project instead.

Essentially, this script goes on to:

  • Load the copied template project
  • Add the video file to the timeline
  • Determine the first and last frame of the video file (MarkIn and MarkOut)
  • Set and load render setting
  • Render out the new video file
from python_get_resolve import GetResolve
import sys
import os
import shutil

if len(sys.argv) < 2:
    print("input parameters for scripts are video_path")
    sys.exit()
video_path = sys.argv[1]

template_root = '/Users/tonyflorida/Movies/igtv/'
template_file = os.path.join(template_root, 'igtv-template.drp')

video_name = os.path.basename(video_path)
project_name = 'igtv-' +  os.path.splitext(video_name)[0]
project_file = os.path.join(template_root, project_name + '.drp')

# Make a copy of the project template
shutil.copy2(template_file, project_file)

# Load project
resolve = GetResolve()
project_manager = resolve.GetProjectManager()
project_manager.ImportProject(project_file)
project = project_manager.LoadProject(project_name)
if not project:
    print("Unable to load project")
    sys.exit()

# Add video file to Media Pool
mediapool = project.GetMediaPool()
storage = resolve.GetMediaStorage()
clips = storage.AddItemsToMediaPool(video_path)
mediapool.AppendToTimeline(clips[1])

# Get MarkIn and MarkOut
timeline = project.GetTimelineByIndex(1)
mark_out = timeline.GetItemsInTrack('video', 1)[1].GetEnd()
mark_in = timeline.GetStartFrame()

# Render
target_directory = os.path.dirname(video_path)
render_settings = {"MarkIn":mark_in, "MarkOut":mark_out, "TargetDir":target_directory, "CustomName":project_name}
project.LoadRenderPreset('igtv-preset')
project.SetRenderSettings(render_settings)
project.DeleteAllRenderJobs()
project.AddRenderJob()
project.StartRendering()

Please note that I manually created the render preset called igtv-preset by calling the SaveAsNewRenderPreset(presetName)after manually setting the following in the Deliver tab according to the IGTV Help Center:

  • Format: MP4
  • Resolution: Custom
  • Dimensions: 1080 x 1920
  • Frame rate: 30

I saved my Python script as generate-igtv-video.py and it can be executed similar to below:

python generate-igtv-video.py /Users/tonyflorida/Movies/video.mp4

Don’t Be a Stranger ?

If you have any questions about scripting with DaVinci Resolve, please let me know in the comments below. I’m looking forward to future releases of the DaVinci Resolve scripting API, and would love to talk to others in the community who share a similar interest.

Also, you can check out my IGTV videos here, follow me on YouTube, and check out some of my other Python blog posts.

About The Author

With a strong software engineering background, Tony is determined to leverage the internet to positively impact as many people as possible. Discover why Tony quit his dream job to pursue this mission. You can send Tony a message here.

2 thoughts on “Python Scripting with DaVinci Resolve Studio 16 on a Mac”

  1. Good day Tony,
    I’m new on Resolve 16 and had some issues with the Media Manager trim function. I would like to move the project trimmed with an offset of 50 frames for future editing. Resolve crash always when the left or right offset is smaller then 50 frames. I have started to write a small script in LUA to test the current clip but I would like to write my one export/trim script in Python. Unfortunately the documentation of the usable Resolve functions is not complete. Per example I need to scan all the clips in the timeline and to copy the trimmed clip including 50 frames (if available). Is this possible with scripting?

    Best regards from Namibia

    –[[
    DaVinci Resolve script:
    copy and trim current timeline.
    –]]

    resolve = Resolve()
    projectManager = resolve:GetProjectManager()
    project = projectManager:GetCurrentProject()
    timeline = project:GetCurrentTimeline()
    timecode = timeline:GetCurrentTimecode()
    clip = timeline:GetCurrentVideoItem()
    clipname = clip:GetName()
    duration = clip:GetDuration()
    clipstart = clip:GetStart()
    clipend = clip:GetEnd()
    clipleftoffset = clip:GetLeftOffset()
    cliprightoffset = clip:GetRightOffset()

    print(“Project Manager: “,projectManager)
    print(“Project: “,project)
    print(“Timeline: “,timeline)
    print(“Timecode “,timecode)
    print(“Clip: “,clip)
    print(“Clipname: “,clipname)
    print(“Clip Duration: “,duration)
    print(“Clip Start: “,clipstart)
    print(“Clip End: “,clipend)
    print(“Clip Left Offset: “,clipleftoffset)
    print(“Clip Right Offset: “,cliprightoffset)

    if (clipleftoffset < 50) then
    print("ATTENTION Left Offset To Small","\n")
    end
    if (cliprightoffset < 50) then
    print("ATTENTION Right Offset To Small","\n")
    end

    Reply
    • The Python scripting capabilities are very limited in DaVinci Resolve 16. I’m not sure if you want to trim individual clips, or you entire timeline. Trimming individual clips isn’t possible as far as I know. In order to trim the beginning or end of your timeline, you can set the render settings for MarkIn and MarkOut like this:
      render_settings = {"MarkIn":mark_in, "MarkOut":mark_out}
      project.SetRenderSettings(render_settings)

      This will select everything in your timeline between mark_in and mark_out.

      In order to set mark_in and mark_out with an offset of 50 frames on either side, you can do something like:

      mark_in = timeline.GetStartFrame() + 50
      mark_out = timeline.GetItemsInTrack('video', 1)[-1].GetEnd() - 50

      Is this kind of along the lines of what you want to accomplish?

      Reply

Leave a Comment

shares