Sync FTrack Metadata#

This example plugin sync custom shot meta data from FTrack to Prism.

The sync can be triggered from the FTrack menu in the Project Browser for selected shots.

See the section for Single File Plugins on how to load this example.


name = "Sync_FTrack_Metadata"
classname = "Sync_FTrack_Metadata"

from qtpy.QtWidgets import *

class Sync_FTrack_Metadata:
    def __init__(self, core):
        self.core = core
        self.version = "v1.0.0"

        self.core.registerCallback("onProjectBrowserStartup", self.onProjectBrowserStartup, plugin=self, priority=40)
        if self.core.pb:

    def onProjectBrowserStartup(self, origin):
        # add action to FTrack menu in the Project Browser
        if hasattr(origin, "menu_prjMng") and origin.menu_prjMng.title() == "FTrack":
            origin.menu_prjMng.addAction("Sync Shot Meta Data", lambda: self.onSyncTriggered(origin))

    def onSyncTriggered(self, origin):
        # get the currently selected shots in the Project Browser
        tab = origin.tbw_project.currentWidget()
        entities = tab.getCurrentEntities()
        shots = [entity for entity in entities if entity.get("type") == "shot"]
        if not shots:
            self.core.popup("No shots selected")

        ftrackPlug = self.core.getPlugin("FTrack")
        text = "Querying meta data - please wait..."
        popup = self.core.waitPopup(self.core, text, parent=origin, hidden=True)
        with popup:
            prjId = ftrackPlug.getCurrentProjectId()
            if prjId is None:

            # query shot information from FTrack
            filters = [
                " is \"%s\"" % prjId,
                "not custom_attributes any (key is \"noPrism\" and value is True)",
                "name in (%s)" % ",".join(shot["shot"] for shot in shots),
                " in (%s)" % ",".join(shot["sequence"] for shot in shots),
            filters = "where " + " and ".join([f for f in filters])
            cmd = "select, description, custom_attributes from %s %s" % (ftrackPlug.shotIdName, filters)
            ftShots = ftrackPlug.makeDbRequest("query", cmd, "all", popup=popup) or []

            # update the meta data of each shot in Prism
            for ftShot in ftShots:
                if not list(ftShot["ancestors"]):

                for shot in shots:
                    if shot["shot"] == ftShot["name"] and shot["sequence"] == ftShot["ancestors"][-1]["name"]:
                        metaData = self.core.entities.getMetaData(shot)
                        metaData["description"] = {
                            "value": ftShot.get("description", ""),
                            "show": True,
                        for customAttr in ftShot.get("custom_attributes", {}):
                            metaData[customAttr] = {
                                "value": str(ftShot["custom_attributes"][customAttr]),
                                "show": True,

                        self.core.entities.setMetaData(shot, metaData)

            # refresh the meta data GUI in the Project Browser