Connect Bernard Review to a studio pipeline. Tracker configuration, playlists with identifiers, notes coming back, a Version Board built by script and the naming rule.
This page is for pipeline teams. It describes how to bring a review into the player from a production tracker, and how to get the notes out with the right identifiers. The commands mentioned are described in Python API and IPC.
Bernard Engine, AArts Lab's production tracker, and any in-house pipeline go through three mechanisms in this version: the .bpl playlist with its x_tracking block, the build-matrix command and the notes export. Direct publishing to Bernard Engine from the player (the Publish to Bernard Engine button) is coming soon.
A .bpl playlist is a JSON file (schema: api/playlist.schema.json). Each clip can carry an x_tracking block with the tracker's identifiers. Write it from your tool, then load it with load-playlist:
{
"current_idx": 0,
"playlist": [
{
"path": "//server/proj/SQ010/SH010/comp/SQ010_SH010_COMP_v003.%04d.exr",
"in_frame": 1001,
"out_frame": 1100,
"x_tracking": {
"shot_id": "shot_1001",
"shot_name": "SQ010_SH010",
"version_id": "v003",
"task": "Compositing"
}
}
]
}
The x_tracking fields: shot_id, shot_name, version_id, shotgrid_version_id (an integer), ftrack_id, artist, task. The block is kept when the playlist is saved.
export-notes writes, without any dialog, export.json and export.html into the folder asked for, with one JPEG per annotated frame (schema: api/notes_payload.schema.json). For each clip: name, status (Pending, Approved or Not Approved), note, frames (the number and the file of each annotated frame) and, if it was there at load time, the x_tracking block as it was. A script thus routes each note back to the right version by its identifier, without comparing file names.
client.load_playlist("D:/review/SQ010_dailies.bpl")
# ... the review takes place ...
client.export_notes("D:/review/SQ010_dailies_notes")
The files are written in the background: wait for export.json to be up to date before reading it.
The Version Board (Versions) fills itself from file names. A pipeline can also send it ready-made, with build-matrix, without any naming convention. One command per sequence; one department entry per version to offer (send the same department twice with two versions to fill its list):
{"cmd": "build-matrix", "sequence": "SQ010", "id": "seq_42",
"shots": [
{"name": "SH010", "id": "shot_1001", "departments": {
"ANIM": {"version": "v002", "path": "//server/proj/SQ010/SH010/anim/SQ010_SH010_ANIM_v002.mov", "version_id": "ver_77812", "id": "task_501"},
"LGT": {"version": "v001", "path": "//server/proj/SQ010/SH010/lgt/SQ010_SH010_LGT_v001.mov", "version_id": "ver_77950"}}},
{"name": "SH020", "id": "shot_1002", "departments": {
"COMP": {"version": "v003", "path": "//server/proj/SQ010/SH020/comp/SQ010_SH020_COMP_v003.mov", "version_id": "ver_78001"}}}]}
Each path not yet in the playlist is added to it. get-matrix reads the board back. In Python: client.build_matrix(sequence, shots, matrix_id) and client.get_matrix().
The recipe is the same for any tracker: query a sequence's versions, group them by shot and by department (the pipeline step), put the media's path in path and the version's identifier in version_id.
Without a script, every clip added is read against the rule in the naming_rules.json file of the profile folder (see Installation and IT):
{"regex": "^([A-Za-z0-9]+)_([A-Za-z0-9]+)_([A-Za-z]+)_v([0-9]+)",
"groups": {"sequence": 1, "shot": 2, "department": 3, "version": 4}}
That is the [Sequence]_[Shot]_[Department]_v[Version].[ext] convention, for example SQ010_SH010_ANIM_v002.mov. Adapt the regular expression and the group numbers to your studio's convention. A file that does not match goes under DefaultSeq / Base.
The Tracker window connects directly to these three trackers. For a deployment, the sites can be prepared in trackers.json, in the profile folder; that file never holds a secret (a key that looks like a secret is dropped when read):
{"sites": [{
"id": "demo-kitsu", "kind": "kitsu",
"base_url": "https://kitsu.example.test",
"user": "reviewer@example.test",
"proxy": "", "ca_cert_file": "",
"path_map": [{"from": "/mnt/show/",
"to": {"windows": "S:\\show\\", "linux": "/mnt/show/", "macos": "/Volumes/show/"}}],
"status_map": {"approved": "done"}
}]}
kind: kitsu, ftrack or flow. user: the e-mail for Kitsu, the API user for ftrack, the script name for Flow.base_url must start with https:// (http:// only towards localhost).proxy: empty for the environment's, direct for none. ca_cert_file: a PEM file for a studio certificate authority.path_map translates the tracker's paths for each system; status_map maps the player's statuses (pending, approved, not_approved) to the tracker's.BERNARD_TRACKER_<ID>_SECRET environment variable, where <ID> is the site's id in capitals with every character other than A-Z and 0-9 replaced by _: for demo-kitsu, BERNARD_TRACKER_DEMO_KITSU_SECRET. The variable wins.From a script, the tracker-sites, tracker-connect, tracker-projects, tracker-playlists, tracker-load-playlist, tracker-publish (with dry_run to try it), tracker-download-media and tracker-cancel commands do what the window does; their results arrive as events. A request that carries a secret is refused.
A clip loaded from a tracker also keeps in x_tracking the tracker's kind, the site, the task, the playlist, the media reference and, once published, the fingerprint of the note sent: an unchanged note is never published twice.
Going further: the complete manual, parts 6.4 and 6.6 (Help > User Guide in the player), and the schemas in the api/ folder.