I found it frequently time intensive to figure out how to do things with RV… And what I wish I had was a cookbook that I could just look up snippets in…
So let’s start one together as a community.
Add snippets that work and are helpful. Please
If there is a post already use Copy Quote to link to original post (for further reference)
Mention the version of RV that the snippet works with
Preferably make it executable in the Python Console for RV (if possible)
Let’s make it fun and helpful
And if you are looking for basic getting started guidance instead of snippets:
12 Likes
Adding multiple media representations.
Works in RV 2024.1.0, link to docs
import rv
src1 = "https://assets.mixkit.co/videos/preview/mixkit-very-close-shot-of-the-leaves-of-a-tree-wet-18310-small.mp4"
src2 = "https://assets.mixkit.co/videos/preview/mixkit-very-close-shot-of-the-leaves-of-a-tree-wet-18310-large.mp4"
rv.commands.addSourcesVerbose([[src1, "+mediaRepName", "Small"]])
rv.commands.addSourceMediaRep("last", "Large", [src2])
Link media brought in via drag and drop to Shotgun
import rv
from rv import commands as rvc
version_id = 6073
# Get the source node currently being viewed
source_node = rvc.sourcesRendered()[0]["node"]
# Make sure the tracking info property exists. Create it if it doesn't exist
tracking_info_prop= "%s.tracking.info" % source_node
if not rvc.propertyExists(tracking_info_prop):
rvc.newProperty(tracking_info_prop, rv.commands.StringType, 2)
# Set the version ID on the tracking info
rvc.setStringProperty(tracking_info_prop, ["id", str(version_id)], True)
# Ask the shotgun_mode to fill in the rest of the tracking info based on the version ID
rv.runtime.eval(
"""shotgun_mode.theMode().updateTrackingInfo("one", nil);""",
["shotgun_mode"]
)
The Shotgun Mode has changed by the way
Building a stack
Works in RV 2024.1.0
import rv
src1 = “https://assets.mixkit.co/videos/preview/mixkit-striking-texture-of-the-liquid-from-a-lava-lamp-51737-large.mp4 1”
src2 = “https://assets.mixkit.co/videos/preview/mixkit-strange-texture-of-a-bubbling-yellow-liquid-51732-large.mp4 1”
src1_node = rv.commands.addSourceVerbose([src1])
src2_node = rv.commands.addSourceVerbose([src2])
rv.extra_commands.setUIName(rv.commands.nodeGroup(src1_node), “src1”)
rv.extra_commands.setUIName(rv.commands.nodeGroup(src2_node), “src2”)
stack_node = rv.commands.newNode(“RVStackGroup”, “PlateStack”)
rv.commands.setNodeInputs(stack_node, [rv.commands.nodeGroup(src2_node), rv.commands.nodeGroup(src1_node)])
Accessing Shotgun from RV (works in 2024.1.0
Adding a source to a sequence (and creating seq if its not already there)
def add_to_custom_sequence(self, stack_node: str):
sequence_node = "MySequenceNode"
if not commands.nodeExists(sequence_node):
commands.newNode("RVSequenceGroup", sequence_node)
input_nodes, _ = commands.nodeConnections(sequence_node)
input_nodes.append(stack_node)
commands.setNodeInputs(sequence_node, input_nodes)
commands.setViewNode(sequence_node)
Moving nodes to a Folder (works in RV 2024.10)
import rv
def move_to_folder(source_group: str,
folder_node="AutoStackFolder",
folder_name="AutoStack Temp Folder"):
if not rv.commands.nodeExists(folder_node):
rv.commands.newNode("RVFolderGroup", folder_node)
rv.extra_commands.setUIName(folder_node, folder_name)
input_nodes = rv.commands.nodeConnections(folder_node, False)[0]
if not source_group in input_nodes:
input_nodes.append(source_group)
rv.commands.setNodeInputs(folder_node, input_nodes)
Influencing the ordering that events are processed between custom modules
You probably want package ordering in your init
calls. Note that this also affects the order that overlapping events are handled, so if you don’t reject() an event the lower modes in the stack won’t get those.
See 12.6
https://help.autodesk.com/view/SGSUB/ENU/?guid=SG_RV_rv_manuals_rv_reference_manual_chapter_twelve_html
Note that we use the sortKey “source_setup” and the sortOrder “20”. This will ensure that our additional sourceSetup runs after the default color management.The included optional package “ocio_source_setup” is a good example of a package that does additional source setup.
Ever wondered how to create a custom property? The docs don’t go into detail on it so here an example.
Works in RV 2024.1.0
Here quick example of creating and setting a custom property
import rv
source = rv.commands.addSourceVerbose(["abc.jpg"])
source_group = rv.commands.nodeGroup(source)
propName = "%s.tags.counter" % source_group
if not rv.commands.propertyExists(propName):
rv.commands.newProperty(propName, rv.commands.IntType, 1)
rv.commands.setIntProperty(propName, [22], True)
print (rv.commands.getIntProperty(propName))
Setting up an Example Look Pipeline
Initial Import
from rv import commands, extra_commands
Get the last source at current frame
source = commands.sourcesAtFrame(commands.frame()[0])
Find the source group
sourceGroup = commands.nodeGroup(source)
Find the look pipe group that is on the source group
lookPipe = extra_commands.nodesInGroupOfType(sourceGroup, “RVLookPipelineGroup”)[0]
Set the order of the look pipe operations
commands.setStringProperty(“%s.pipeline.nodes” % lookPipe, [“LinearToAlexaLogC”, “RVLookLut”, “rec709ToLinear”], True)
Find nodes of type RVLookLUT
looklut = commands.nodesInGroupOfType(“%s.pipeline.nodes”, “RVLookLUT”)
commands.nodeType(lookLUT)
Set the LUT file path on the node you found
commands.setStringProperty(“%s.lut.file” % “/path/to/cube”)
More tips for using Mu via Python
Changing the Composite Type on all Stacks (types other then replace can be found here )
Accessing SG Tracking Info for a given source
def _get_source_shotgun_data(source):
"""
Get the shotgun data from a source.
Args:
source (str): rv source name.
Returns:
dict: shotgun data as a dictionary.
"""
try:
source_data = rv.commands.getStringProperty(
"{}.tracking.info".format(source)
)
data_list = ast.literal_eval(str(source_data))
except:
return {}
return {k: v for k, v in zip(data_list, data_list[1:])}
It’s important to wait until the tracking info is populated though
As far as the fields for the track.info
on each source, they aren’t created immediately. They are created asynchronously slightly after the source is created. If you are trying to access them on source-group-complete, it will be too soon for the API query to have filled out the data. Instead, watch for graph-state-change
where tracking.info
is in the event.contents().
Getting the file path of the current media source
Getting the file name (and path) of the frame currently being played
import rv
# The difference here is that we traverse the graph to find not only the source, but also the source frame number.
info = rv.extra_commands.sourceMetaInfoAtFrame(rv.commands.frame())
metadata = rv.commands.sourceMediaInfo(info['node'])
filename = metadata.get("file")
sourceFrame = info['frame']
# Note: this only works how we want it to for file sequences, error check to make sure you are dealing in file sequencese, as well as protecting yourself against missing framees.
files = rv.commands.existingFilesInSequence(filename)
frames = rv.commands.existingFramesInSequence(filename)
# Assmeble the files and frame numbers in something we can index into.
framesToFiles = dict(zip(frames, files))
# The result can be found here:
framesToFiles[sourceFrame]
Display Feedback in the upper left corner
If you want, you can use commands.displayFeedback
and that will show up a message that disappears and it’s very easy to implement:
from rv import extra_commands as rve
## Hold for 2 seconds
rve.displayFeedback("Shotgun will use same window to play mov", 2.0)
An binding to an event that is only run once
def singleShotBind(self, eventName, callback):
"""Create a bind that will automatically clean itself up after the first successful run.
eventName: The event to bind to.
callback: A runnable that takes the event object. Returning True from this function will
cause the cleanup to occur. Returning False will keep the binding around.
If an unhandled exception occurs in the callback, the binding will be torn down.
"""
How do I install Python Libraries to be used by RV Mode’s I develop?
When it’s Py Libs without compiled c code you can use
python -m pip install tool --target rv-py-libs
and then just add it as a path in your mode
import sys
sys.append("path/to/lib")
But when there is complied c code that doesn’t work as the compiled libs throw an error on import. This here works though (sample from Win)
"C:\Program Files\Autodesk\RV-2024.1.0\bin\python" -m pip install timerit