Resolve Scripting Essentials

User avatar
Midgardsormr
Fusionista
Posts: 706
Joined: Wed Nov 26, 2014 8:04 pm
Location: Los Angeles, CA, USA
Been thanked: 64 times
Contact:

Re: Resolve Scripting Essentials

#31

Post by Midgardsormr » Wed Apr 18, 2018 7:23 am

Wow, hacktastic! :shock:

User avatar
Greg Bovine
Double M
Posts: 113
Joined: Fri Feb 02, 2018 6:07 am
Location: Oslo, Norway
Been thanked: 29 times
Contact:

Resolve vs Fusion Standalone Host Check

#32

Post by Greg Bovine » Wed Apr 18, 2018 4:47 pm

This short Lua script snippet can be used to check if Resolve or Fusion Standalone is being used to run your script:
Code: [Select all] [Expand/Collapse] [Download] (FusionHost.lua)
  1. -- Check if Fusion Standalone or the Resolve Fusion page is active
  2. host = fusion:MapPath('Fusion:/')
  3. if string.lower(host):match('resolve') then
  4.     print('[Host] Resolve')
  5. else
  6.     print('[Host] Fusion')
  7. end

User avatar
Greg Bovine
Double M
Posts: 113
Joined: Fri Feb 02, 2018 6:07 am
Location: Oslo, Norway
Been thanked: 29 times
Contact:

Re: Resolve Scripting Essentials

#33

Post by Greg Bovine » Mon Apr 23, 2018 9:25 am

If you are looking for more documentation on Resolve's scripting API don't forget to check out the official readme file and two example python scripts that are included with Resolve Studio v15. As a reminder, you need to be running Resolve Studio to access the new Resolve API functions. The scripting features used to interface with the Resolve NLE and the Media Pool are not available in the free version of Resolve.

macOS Resolve Scripting Docs:

Code: Select all

/Library/Application Support/Blackmagic Design/DaVinci Resolve/Developer/Scripting/
Windows Resolve Scripting Docs:

Code: Select all

C:\ProgramData\Blackmagic Design\DaVinci Resolve\Support\Developer\Scripting\
Linux Resolve Scripting Docs:

Code: Select all

/opt/resolve/Developer/Scripting/

User avatar
AndrewHazelden
Fusionator
Posts: 1001
Joined: Fri Apr 03, 2015 3:20 pm
Location: West Dover, Nova Scotia, Canada
Been thanked: 92 times
Contact:

FBX Export in Resolve

#34

Post by AndrewHazelden » Sun Apr 29, 2018 9:51 am

I noticed a conversation on the BMD Fusion forums that was inferring the FBX Exporter node might not work in Resolve 15.

Here is a short Lua code snippet that renders the output of the node tree up to a specific node in your Fusion page composite. If you type in the name of your FBX Exporter node in the script then that mesh data will be written to disk by Resolve/Fusion:
Code: [Select all] [Expand/Collapse] [Download] (Export FBX Simple.lua)
  1. -- Render up to the FBXExporter1 tool, but nothing further downstream.
  2. comp:Render({Tool = comp.FBXExporter1})

FBXExporterUltra

The new FBXExporterUltra macro makes it easier to save out FBX meshes from Resolve.

User Controls

The "Render to Disk" button will save out an FBX file by rendering out the flow up to the FBXExporterUltra node.
The "Open Containing Folder" button makes it easy to access the folder where the FBX file was saved to disk.

Screenshot
FBXExporterUltra.png
Download the Macro
Code: [Select all] [Expand/Collapse] [Download] (FBXExporterUltra.setting)
  1. {
  2.     Tools = ordered() {
  3.         FBXExporterUltra = ExporterFBX {
  4.             CustomData = {
  5.                     HelpPage = "https://www.steakunderwater.com/wesuckless/viewtopic.php?p=16429#p16429",
  6.                 },
  7.             CtrlWZoom = false,
  8.             Inputs = {
  9.                 Filename = Input { Value = "", },
  10.                 ExportRenderRange = Input { Value = 0, },
  11.                 FilePerFrame = Input { Value = 0, },
  12.                 FrameRenderScriptNest = Input { Value = 1, },
  13.             },
  14.             ViewInfo = OperatorInfo { Pos = { 490, 119.485 } },
  15.             UserControls = ordered() {
  16.                 RenderButton = {
  17.                     LINKID_DataType = "Number",
  18.                     BTNCS_Execute = [[
  19. ------------------------------------------------------------------------
  20. -- Add the platform specific folder slash character
  21. osSeparator = package.config:sub(1,1)
  22.  
  23. -- Find out the current directory from a file path
  24. -- Example: print(Dirname('/Users/Shared/file.txt'))
  25. function Dirname(mediaDirName)
  26.     return mediaDirName:match('(.*' .. osSeparator .. ')')
  27. end
  28.  
  29. -- Check if the output folder exists
  30. filename = comp:MapPath(tool:GetInput('Filename'))
  31. if filename ~= '' then
  32.     dir = Dirname(filename)
  33.     if not bmd.fileexists(dir) then
  34.         print('[Create Directory] ', dir)
  35.         bmd.createdir(dir)
  36.     end
  37.  
  38.     -- Print the status info
  39.     -- Timeline frame range
  40.     startFrame = comp:GetAttrs().COMPN_RenderStart
  41.     endFrame = comp:GetAttrs().COMPN_RenderEnd
  42.     print('[FBX Render Range] ' .. startFrame .. '-' .. endFrame .. ' [Node] ' .. tostring(tool.Name))
  43.  
  44.     -- Render the FBX Exporter node to disk
  45.     comp:Render({Tool = tool})
  46. else
  47.     print('[FBX Render] Empty Filename. Please type in a filename and then click the "Render to Disk" button again.')
  48. end
  49. ]],
  50.                     ICS_ControlPage = "Controls",
  51.                     INPID_InputControl = "ButtonControl",
  52.                     LINKS_Name = "Render to Disk"
  53.                 },
  54.                     OpenContainingButton = {
  55.                     LINKID_DataType = "Number",
  56.                     BTNCS_Execute = [[
  57. ------------------------------------------------------------------------
  58. -- Add the platform specific folder slash character
  59. osSeparator = package.config:sub(1,1)
  60.  
  61. -- Find out the current directory from a file path
  62. -- Example: print(Dirname('/Users/Shared/file.txt'))
  63. function Dirname(mediaDirName)
  64.     return mediaDirName:match('(.*' .. osSeparator ..')')
  65. end
  66.  
  67. -- Open a folder window up using your desktop file browser
  68. function OpenDirectory(mediaDirName)
  69.     dir = Dirname(mediaDirName)
  70.  
  71.     if not bmd.fileexists(dir) then
  72.         print('[Create Directory] ', dir)
  73.         bmd.createdir(dir)
  74.     end
  75.    
  76.     if bmd.fileexists(dir) then
  77.         print('[Open Directory] ', dir)
  78.         bmd.openfileexternal('Open', dir)
  79.     end
  80. end
  81.  
  82. filename = comp:MapPath(tool:GetInput('Filename'))
  83. OpenDirectory(filename)
  84. ]],
  85.                     ICS_ControlPage = "Controls",
  86.                     INPID_InputControl = "ButtonControl",
  87.                     LINKS_Name = "Open Containing Folder "
  88.                 }
  89.             },
  90.         },
  91.     },
  92.     ActiveTool = "FBXExporterUltra"
  93. }
  94.  
You do not have the required permissions to view the files attached to this post.
Last edited by AndrewHazelden on Sun Apr 29, 2018 11:19 am, edited 3 times in total.

User avatar
Midgardsormr
Fusionista
Posts: 706
Joined: Wed Nov 26, 2014 8:04 pm
Location: Los Angeles, CA, USA
Been thanked: 64 times
Contact:

Re: Resolve Scripting Essentials

#35

Post by Midgardsormr » Sun Apr 29, 2018 10:58 am

Thanks, Andrew! You're a rock star!

User avatar
AndrewHazelden
Fusionator
Posts: 1001
Joined: Fri Apr 03, 2015 3:20 pm
Location: West Dover, Nova Scotia, Canada
Been thanked: 92 times
Contact:

Resolve Fusion Page - Hotkey Manager

#36

Post by AndrewHazelden » Mon May 14, 2018 10:05 am

Hotkey Manager.png
If you want to view the active hotkeys in the Resolve Fusion page you can open the Hotkey Manager window using the following Lua script:
Code: [Select all] [Expand/Collapse] [Download] (Hotkey Manager.lua)
  1. -- Hotkey Manager
  2. app:DoAction("App_CustomizeHotkeys", {})
You can save this Lua script to your Resolve Fusion user prefs "Scripts:/Comp/Hotkey Manager.lua" PathMap location. Restart Resolve so this script shows up in a Fusion > Script > Hotkey Manager menu entry.
You do not have the required permissions to view the files attached to this post.
Last edited by AndrewHazelden on Mon May 14, 2018 11:55 am, edited 2 times in total.

User avatar
AndrewHazelden
Fusionator
Posts: 1001
Joined: Fri Apr 03, 2015 3:20 pm
Location: West Dover, Nova Scotia, Canada
Been thanked: 92 times
Contact:

Resolve Fusion Page - New Image View

#37

Post by AndrewHazelden » Mon May 14, 2018 10:12 am

In the Resolve Fusion page you can create a new floating image viewer window. This allows you to move a viewer onto an external monitor.

When the new viewer window is open you can click the extra third "circle" shape icon on a node to send media to the floating window. Alternatively you can press the "3" key on your keyboard when a node is selected in the "Nodes" work area to push media into the floating window.

New Image View Screenshot
New Image View.png
New Image View Script

Save this Lua script text to the Resolve Fusion user preferences "Scripts:/Comp/New Image View.lua" PathMap location. Then restart Resolve for the script to show up as a Fusion > Script > New Image View menu entry.
Code: [Select all] [Expand/Collapse] [Download] (New Image View.lua)
  1. -- Display a New Image View
  2. fu:CreateFloatingView()
You do not have the required permissions to view the files attached to this post.

User avatar
Adelson
Posts: 44
Joined: Mon Feb 01, 2016 7:25 am
Been thanked: 3 times

Re: Resolve Scripting Essentials

#38

Post by Adelson » Tue May 15, 2018 10:17 am

Thanks Andrew! Very useful.

It's a shame that this is not persistent. When you switch to the Edit tab and go back to Fusion tab, the view is gone.

Is there any chance that we can have a similar code to generate a "Floating Flow" ?

User avatar
SirEdric
Fusionista
Posts: 962
Joined: Tue Aug 05, 2014 10:04 am
Been thanked: 70 times
Contact:

Re: Resolve Scripting Essentials

#39

Post by SirEdric » Tue May 15, 2018 10:51 am

Of course there is!
It's called "Fusion Standalone"...:-)

User avatar
Adelson
Posts: 44
Joined: Mon Feb 01, 2016 7:25 am
Been thanked: 3 times

Re: Resolve Scripting Essentials

#40

Post by Adelson » Thu May 17, 2018 3:06 pm

SirEdric wrote:
Tue May 15, 2018 10:51 am
It's called "Fusion Standalone"...:-)

Oh I see.
Something like:

Code: Select all

fu:OpenFusionStandalone()
fu:ExitDaVinciResolve()
:lol:

Just an update: in DaVinci 15 Beta 3 the Viewer is now persistent. It will reopen every time you go to the Fusion Page

Cheers

User avatar
AndrewHazelden
Fusionator
Posts: 1001
Joined: Fri Apr 03, 2015 3:20 pm
Location: West Dover, Nova Scotia, Canada
Been thanked: 92 times
Contact:

Accesing the MediaIn Node MediaProps Table

#41

Post by AndrewHazelden » Mon May 21, 2018 9:19 am

The Resolve 15 Fusion page uses a new analogy of a "MediaIn" node to load footage from the Media Pool and Edit page timeline into your Fusion composite. This is a big change for Fusion Standalone users who were comfortable with the typical "Loader" node based approach to work with footage in a composite.

MediaIn Node.png

When a MediaIn node is active you will see a small amount of information about the footage in the Fusion page Inspector view.

MediaIn Inspector View.png

If you select a MediaIn node in the Nodes view and copy that node into your system's copy/paste clipboard it will be saved as plain text in a Lua table format.

If you pasted that text output into a text editor like BBEdit or Notepad++ it would look something like this:

Code: Select all

{
	Tools = ordered() {
		MediaIn1 = MediaIn {
			ExtentSet = true,
			CtrlWZoom = false,
			CustomData = { MediaProps = {
					MEDIA_HEIGHT = 800,
					MEDIA_MARK_IN = 22,
					MEDIA_MARK_OUT = 143,
					MEDIA_NAME = "mantra.b0.[0001-0144].exr",
					MEDIA_NUM_FRAMES = 144,
					MEDIA_NUM_LAYERS = 6,
					MEDIA_PAR = 1,
					MEDIA_PATH = "/Houdini/render/mantra.b0.[0001-0144].exr",
					MEDIA_SRC_FRAME_RATE = 24,
					MEDIA_START_FRAME = 0,
					MEDIA_WIDTH = 1920
				}, },
			Inputs = {
				GlobalIn = Input { Disabled = true, },
				GlobalOut = Input {
					Value = 143,
					Disabled = true,
				},
				Layer = Input { Value = "0", },
				ClipTimeStart = Input { Disabled = true, },
				ClipTimeEnd = Input {
					Value = 143,
					Disabled = true,
				},
				HoldFirstFrame = Input { Disabled = true, },
				HoldLastFrame = Input { Disabled = true, },
				Reverse = Input { Disabled = true, },
				Loop = Input { Disabled = true, },
			},
			ViewInfo = OperatorInfo { Pos = { 55, 49.6061 } },
		}
	},
	ActiveTool = "MediaIn1"
}

From looking at this output we can see that a MediaIn node stores information about the footage in a "CustomData = { MediaProps = {}, }" Lua table entry.

This information was originally pulled by Resolve from the Media Pool database where the internal record of the media in the Resolve project actually lives.

By comparison to a Mediain node in Resolve, a Fusion Standalone based Loader node is a much simpler and easier to understand node as it simply reads the footage you want to access in the composite directly using the Filename attribute on the node with no extra media management system overhead.

Lets start exploring the MediaProps attributes on a MediaIn node.

Open the Console view using the Fusion > Console menu.

Fusion Console Menu Item.png

To access the CustomData 'MediaProps' settings on the currently selected MediaIn node, paste the following code into the Console window:

Code: Select all

==comp.ActiveTool:GetData('MediaProps')

The double equals sign "==" placed at the start of the line is the Lua shorthand notation for the "dump()" command that is able to print a Lua table out to the Console view. If you are coming to Lua from another programming language a Lua table is Lua's equivalent to an array or struct. The reason we use the dump command for this task is because it is more powerful then print() function because it allows you to see and browse the full Lua table structure in the Console output.

Dumping the MediaIn Node Attributes.png

You could also access the CustomData 'MediaProps' settings by searching for a specific MediaIn node in the composite using its node name with the help of the FindTool command. FindTool works by returning a pointer variable for the MediaIn node. The interesting thing about the FindTool command is the pointer you get back for the node will continue to refer to the same footage in your comp even if another part of your scripted workflow renames the node later on.

Code: Select all

==comp:FindTool('MediaIn1'):GetData('MediaProps')

The GetData function allows us to access the CustomData information that is stored in the MediaIn node.

There are three different ways to use the built-in GetData functions in the Fusion page. The correct GetData function is chosen based upon if you want to read information from the Fusion page environment itself with "fusion:GetData" / "app:GetData()", or from the active composite with "comp:GetData()", or finally at the node level like we just did in the above code snippet if you want to access persistent data stored on an individual node.

More details about the GetData function's available parameters are described in the Fusion 8 Scripting Manual.pdf guide on pages 171/172.

MediaProps.lua Script

Here is an example script named MediaProps.lua that extracts several useful attributes from the MediaProps table and then prints the results to the Console window. Minimal error handling was added to the script so the node's "RegID" attribute is checked to verify the selected node is actually a MediaIn node type before any other action is carried out.

You can drag and drop this script into the Nodes view or the Fusion console view to run it. Alternatively you could copy the MediaProps.lua script into the Resolve Fusion user prefs "Scripts:/Tools/" folder and run it from the Nodes view by you right clicking on a node then selecting the Script > MediaProps contextual menu.

MediaProps Script in Tools Menu.png

or you could place the script in the Fusion user prefs "Scripts:/Comp/" folder and access it from the Fusion > Script > MediaProps menu after you restart Resolve once to refresh the menu entries.

MediaProps Script in Comp Menu.png

A tip about writing Fusion page "Tool" scripts is that they automatically have the variable "tool" pre-filled with the currently selected node when they are launched in the Nodes view. Also, if you select multiple nodes in the Nodes view at the same time and run a tool script you will actually see in the Console window output that the same script was run multiple times in a row where Fusion looped through and processed each node individually with the script so they were supplied with a unique "tool" value for the each node in the selection list.

By comparison a "Comp" menu script that is installed to the Fusion user prefs "Scripts:/Comp/" folder is only run once when you select it in the Fusion > Script menu so no matter how many nodes are active in your selection. This means you have to get a selection list back using another approach if you want to process multiple nodes at the same time in a script.

With all of those details explained, lets try this MediaProps.lua script out in Resolve:
Code: [Select all] [Expand/Collapse] [Download] (MediaProps.lua)
  1. --[[--
  2. MediaProps.lua - 2018-05-21
  3. By Andrew Hazelden <andrew@andrewhazelden.com>
  4.  
  5. This Resolve 15 example script will read the MediaIn node CustomData 'MediaProps' settings to find out the filename and image resolution information for your footage.
  6. --]]--
  7.  
  8. print('\n------------------------------------------')
  9. print('[MediaProps Script] by Andrew Hazelden\n\n')
  10.  
  11. -- Check the active node selection
  12. if not tool then
  13.     tool = comp.ActiveTool
  14. end
  15.  
  16. -- Make sure a MediaIn node is active and ignore all other node types
  17. if tool and tool:GetAttrs().TOOLS_RegID == 'MediaIn' then
  18.     -- Extract the needed Media Props Lua table data
  19.     mediaprops = tool:GetData('MediaProps')
  20.     path = tostring(mediaprops.MEDIA_PATH)
  21.     width = tonumber(mediaprops.MEDIA_WIDTH)
  22.     height = tonumber(mediaprops.MEDIA_HEIGHT)
  23.     fps = tonumber(mediaprops.MEDIA_SRC_FRAME_RATE)
  24.     startFrame = tonumber(mediaprops.MEDIA_START_FRAME) + tonumber(mediaprops.MEDIA_MARK_IN)
  25.     endFrame = tonumber(mediaprops.MEDIA_MARK_OUT)
  26.     durationFrames = endFrame - startFrame
  27.     durationSec = durationFrames / fps
  28.    
  29.     -- Display the results in the Console window
  30.     print('[MediaIn File] ' .. tostring(path))
  31.     print('[Media Info] ' .. tostring(width) .. 'x' .. tostring(height) .. 'px @ ' .. tostring(fps) .. 'FPS [' .. startFrame .. '-' .. endFrame .. '] Active Frame Range [' .. tostring(durationFrames) .. '] Frames Total / [' .. tostring(durationSec) .. '] Seconds Duration')
  32.     print('\n\n[MediaProps Table Info]')
  33.     dump(mediaprops)
  34. else
  35.     print('[Selection Error] Please select a MediaIn node and run this script again.')
  36. end
  37.  
  38. print('\n------------------------------------------')
  39.  

This is an copy of the textual output I get back in the Console view after I run the MediaProps script:

Code: Select all

[MediaIn File] /Houdini/render/mantra.b0.[0001-0144].exr
[Media Info] 1920x800px @ 24FPS [22-143] Active Frame Range [121] Frames Total / [5.0416666666667] Seconds Duration


[MediaProps Table Info]
table: 0x0155c0b8
	MEDIA_HEIGHT = 800
	MEDIA_SRC_FRAME_RATE = 24
	MEDIA_NUM_FRAMES = 144
	MEDIA_NUM_LAYERS = 6
	MEDIA_NAME = mantra.b0.[0001-0144].exr
	MEDIA_WIDTH = 1920
	MEDIA_START_FRAME = 0
	MEDIA_PATH = /Houdini/render/mantra.b0.[0001-0144].exr
	MEDIA_MARK_IN = 22
	MEDIA_MARK_OUT = 143
	MEDIA_PAR = 1

------------------------------------------
You do not have the required permissions to view the files attached to this post.

halucjan
Posts: 14
Joined: Mon Jul 11, 2016 6:46 am

Re: Resolve Scripting Essentials

#42

Post by halucjan » Tue Aug 14, 2018 4:20 am

Does fu:CreateFloatingView() still work for Resolve 15 Studio non beta?

bns
Posts: 1
Joined: Sat Jun 09, 2018 5:29 am
Been thanked: 1 time

Re: Resolve Scripting Essentials

#43

Post by bns » Tue Aug 28, 2018 1:32 pm

post beta, fu:CreateFloatingView() fails silently

NewImageView is the way to go (with persistence after page switch !)
  1. fu:NewImageView()

MLanghausen
Posts: 1
Joined: Wed Aug 29, 2018 12:44 pm

Re: Resolve Scripting Essentials

#44

Post by MLanghausen » Mon Sep 03, 2018 9:46 pm

***Update***

I tried on my Mac Laptop - OS Sierra - and get the same behavior:
The other testing was done on Windows 10 OS

Tried removing the following line as well and still doesn't accept the new 'Resolution" settings

proj:SetSetting("timelineOutputResMismatchUseCustomPreset", tostring(0))
proj:SetSetting("timelineOutputResMismatchCustomPreset", "None")

***EndUpdate***


Hello!
Thank you for this forum!
I've been teaching myself lua and digging into Resolve scripting for the last 3 days.
Just trying out different scripts and seeing how Resolve reacts.

After looking around for a bit, I seem to have run into an issue. Could be user error but thought I would post for feedback.

The following script works perfectly every time.

Change Project Resolution:

Code: Select all

 
local resolve = Resolve()
local pm = resolve:GetProjectManager()
local proj = pm:GetCurrentProject()

proj:SetSetting('timelineResolutionHeight', "720")
proj:SetSetting('timelineResolutionWidth', "2000")
proj:SetSetting("timelineOutputResMismatchBehavior", "stretch")    

 
With that in mind, I wrote the following script trying to change the Output Sizing

Output Sizing

Code: Select all

local resolve = Resolve()
local pm = resolve:GetProjectManager()
local proj = pm:GetCurrentProject()



proj:SetSetting("timelineOutputResMatchTimelineRes", tostring(0))
proj:SetSetting("timelineOutputResMismatchUseCustomPreset", tostring(0))
proj:SetSetting("timelineOutputResMismatchCustomPreset", "None")
proj:SetSetting("timelineOutputResolutionWidth", "720")
proj:SetSetting("timelineOutputResolutionHeight", "2000")
proj:SetSetting("timelineOutputPixelAspectRatio", "square")
proj:SetSetting("timelineOutputResMismatchBehavior", "scaleToCrop")
Everything in the above works except for changing the resolution & custom drop-down setting to "custom"

In script 01, the "custom" resolution drop-down in project settings automatically switches to "custom" and there is no attribute I could find for this when dumping the project settings.

No matter how many different ways I set the "custom" drop-down in Output Scaling the following dump attribute always stayed the same:

timelineOutputResMismatchCustomPreset = None

Could not being able to change this setting be what is not allowing me to change the Output Resolution in Output Scaling?