Bernard Review aus einem Skript oder einer Pipeline-Anwendung steuern. Das Protokoll, der Python-Client, jeder Befehl nach Familie, die Ereignisse und vollständige Beispiele.
Bernard Review lässt sich aus Python, Maya, Nuke, Houdini, einem Produktions-Tracker oder jeder Sprache steuern, die eine TCP-Verbindung öffnen kann. Alles, was ein Artist von Hand tut, hat seinen Befehl: Clips öffnen, abspielen, vergleichen, graden, exportieren, eine Sitzung starten, Notizen veröffentlichen. Diese Seite genügt, um den Player zu automatisieren; die erschöpfende Referenz, Feld für Feld, ist die API-Referenz, auf Englisch (auch über Help > API Documentation zu öffnen).
127.0.0.1, standardmäßig Port 5556. Ein mit --ipc-port N gestarteter Player lauscht auf N: So laufen zwei Player auf demselben Rechner.\n, mit einem Feld "cmd": {"cmd": "seek", "frame": 24}.{"status": "ok", "cmd": "seek", ...} oder {"status": "error", "cmd": "seek", "reason": "..."}. Ein Fehler trägt immer einen Grund in einfachen Worten und wartet nie auf Ihr Zeitlimit. Es gibt keine Anfrage-ID: Eine Antwort wird ihrer Anfrage über ihr "cmd" zugeordnet.{"event": ...}) kommen auf derselben Verbindung an, gemischt mit den Antworten (siehe unten).Host:), wird geschlossen, ohne etwas auszuführen: Eine Webseite kann den Player nicht steuern. Eine Zeile umfasst höchstens 16 MiB.Zum Ausprobieren ohne Code: Window > Console (Strg+Umschalt+C) sendet dieselben Befehle aus dem Player heraus, mit Vervollständigung per Tab: status, seek {"frame": 24} oder die vollständige JSON-Form. Sie fragt vor den Befehlen nach, die Dateien schreiben, veröffentlichen oder den Player schließen.

bernard_api.py verpackt das Protokoll in eine Klasse, BernardClient, mit einer Methode pro Befehl. Er wird neben dem Player im Ordner api installiert:
| System | Ort |
|---|---|
| Windows | C:\Program Files\Bernard Review\bin\api\bernard_api.py |
| Linux (RPM) | /usr/share/bernardplayer/api/bernard_api.py |
Linux (.sh-Archiv) | <install folder>/share/bernardplayer/api/bernard_api.py |
Er braucht nichts außer der Standardbibliothek von Python 3.
import sys
sys.path.append(r"C:\Program Files\Bernard Review\bin\api")
from bernard_api import BernardClient
client = BernardClient(host="127.0.0.1", port=5556)
if not client.connect():
raise SystemExit("Bernard Review does not answer on port 5556")
reply = client.open_media("D:/shots/SQ010_SH010_ANIM_v002.mov")
if reply is None or reply.get("status") == "error":
print("refused:", reply and reply.get("reason"))
else:
client.play()
request(dict) sendet einen Befehl und wartet auf seine Antwort (ein dict), Fehler eingeschlossen: Bei einer Ablehnung durch den Player löst es keine Exception aus und liefert bei einem Zeitlimit oder einer verlorenen Verbindung None.send_command(dict) sendet, ohne zu warten.play(), seek(), set_exposure(), export() ...) rufen die eine oder die andere auf; die, die Daten liefern, laufen über request().on("frame_changed", function) meldet eine Funktion für ein Ereignis an; ein Hintergrund-Thread liest die Verbindung.Ohne den Client genügen ein paar Zeilen:
import json, socket
with socket.create_connection(("127.0.0.1", 5556)) as s:
f = s.makefile("rw", encoding="utf-8", newline="\n")
f.write(json.dumps({"cmd": "status"}) + "\n"); f.flush()
for line in f:
msg = json.loads(line)
if msg.get("cmd") == "status": # skip the events
print(msg["playback"]["currentFrame"]); break
seek, set-in, set-out und die Option --frame nehmen die Position im Clip ab 0 gezählt, nicht die auf dem Lineal gedruckte Nummer. Bei einem Clip, der bei 1001 beginnt, ist das angezeigte Bild 1010 die Position 9. status liefert die Position (playback.currentFrame) und die erste Bildnummer (playback.startOffset).open antwortet, bevor der Clip untersucht ist: status.playback.transitioning bleibt true, bis der Clip auf dem Bildschirm ist. export stellt einen Auftrag in die Warteschlange: Verfolgen Sie ihn mit export-status oder dem Ereignis export-done. export-notes schreibt seine Dateien im Hintergrund. Warten Sie nach set-proxy, bis status.viewport.retiering wieder auf false steht.{"cmd": "set-ui-level", "value": "complete"}.quit antwortet und schließt dann den Player sauber, ohne zu fragen, ob gespeichert werden soll: Senden Sie zuerst save-playlist oder export-notes, wenn das Review wichtig ist.Die 115 Befehle des Players. Die Felder in Klammern sind die wichtigsten; track ist "A" (Standard) oder "B".
Wiedergabe und Bereich
| Befehl | Wirkung |
|---|---|
play, pause, reverse-play | Abspielen, Pause, rückwärts abspielen |
seek (frame) | Zu einer Position gehen (ab 0) |
step-frame (delta) | delta Bilder vor oder zurück gehen |
toggle-loop | Den Bereich wiederholen |
set-playlist-playback (loop_mode 0, 1 oder 2, dont_wait_incomplete_shots) | Wiederholung aus, auf dem Clip oder auf der Playlist |
set-in, set-out (frame, optional) | In- und Out-Punkt; ohne frame der Playhead |
clear-in-out, set-in-out-lock (value) | Den Bereich löschen; verhindern, dass die Maus ihn verschiebt |
set-fps (value), set-start (value) | Bildrate; erste Bildnummer |
set-volume (value 0 bis 1), set-mute (value), toggle-mute | Ton |
Clips und Playlist
| Befehl | Wirkung |
|---|---|
open oder load (path) | Eine Datei oder Sequenz auf Spur A öffnen und der Playlist hinzufügen |
load-playlist (path) | Eine Playlist als .bpl, .otio, .csv, .json oder .edl laden |
save-playlist (path) | Die Playlist als .bpl schreiben (Notizen, Status, Grading, Zeichnungen) |
playlist-add (path), playlist-play (index), playlist-remove (index), playlist-move (from, to), playlist-clear | Die Playlist verwalten (Indizes ab 0) |
drop (paths, at: track_a, track_b oder viewport_b) | Wie das Ablegen von Dateien aus dem Dateimanager |
Vergleich und Versionen
| Befehl | Wirkung |
|---|---|
set-ab-mode (value), toggle-ab | A/B-Modus |
set-track-b (path) | Eine Datei auf Spur B legen |
set-ab-view (value: a, wipe, b), ab-flip | Nur A, Wipe, nur B; A/B umschalten |
set-wipe (position 0 bis 1, angle in Grad) | Position und Winkel des Wipes |
cycle-b (direction: prev, next) | Vorige oder nächste Version auf B |
pin-track-b (value), set-b-version-preload (value) | B anheften; die benachbarten Versionen vorladen |
set-ab-label-mode (interaction, always, never), set-metadata-track (a, b, ab) | A/B-Buchstaben; die Spur des Tabs Metadata |
build-matrix (sequence, id, shots), get-matrix | Das Version Board füllen und lesen (siehe Integrationen) |
Farbe
| Befehl | Wirkung |
|---|---|
set-exposure, set-gamma (value, track) | Belichtung (in Blenden), Gamma |
set-white-balance (temp, tint von -1 bis 1, track), set-offset (value: [r, g, b], track) | Weißabgleich, Offset |
set-colorspace (value) | Eingangsraum von Spur A: ACEScg, sRGB, AP0, AdobeRGB, ProPhoto, Rec709, LogC3, LogC4 oder Auto |
set-channel (value: RGBA, R, G, B, A, L; track) | Angezeigter Kanal |
set-stage (stage, on, track) | Eine Stufe aus- oder einschalten (exposure, levels, curves, gamma ...) |
set-curve (channel: master, r, g, b; points oder reset) | Kurven, Punkte [x, y] auf der ACEScct-Achse |
set-hue-range (range, hue, saturation, lightness) | Farbbereiche |
color-panel (target, before_after, picker, levels_auto, preset_save, preset_apply ...) | Das Farb-Panel; ohne Feld liest es es aus |
scopes (open, kind) | Die Scopes und ihre letzten Messwerte (Histogramm, Clipping) |
set-layer (track_idx, layer_idx), layer-info (track) | Pass eines Multi-Layer-EXR |
Viewer, Oberfläche und Fenster
| Befehl | Wirkung |
|---|---|
zoom (value, 1 = ein Quellpixel pro Bildschirmpixel), pan (x, y), fit, flip | Bildausschnitt |
set-fullscreen (value), set-window-size (width, height), set-ui-scale (percent) | Hauptfenster |
set-theme (dark, light, neon, system; oder sombre, clair, systeme), set-ui-level (essential, complete) | Anzeigemodus und Oberflächenstufe |
reset-layout, new-window (view), close-window (name oder all), windows | Layout und Panel-Kopien |
contact-sheet (open, mode, card_w ...) | Kontaktbogen |
set-tool (tool: pen, text, arrow, rect, laser, eraser, pipette, select) | Zeichenwerkzeug |
debug-mouse (x, y, down, alt, release) | Simulierte Maus, für Oberflächentests |
Notizen, Aufnahmen und Export
| Befehl | Wirkung |
|---|---|
export-notes (output_dir) | export.json und export.html ohne jeden Dialog schreiben |
screenshot (output, frame, annotations) | Ein PNG des Clips von Spur A, gegradet wie auf dem Bildschirm |
export (output, preset, source, playlist, format, codec, color, burn_in, annotations, watermark, recipient ...) | Einzelbilder oder einen Film exportieren; in die Warteschlange gestellt |
export-status, export-cancel, export-presets | Verfolgen, abbrechen, die Presets auflisten |
export-recipe (action: list oder run; name, file oder recipe; clips, recipient) | Export-Rezepte |
Speicher und Decodierung
| Befehl | Wirkung |
|---|---|
set-proxy (proxy_idx: 0 = 1/1, 1 = 1/2, 2 = 1/4, 3 = 1/8, 4 = Smart RAM-Fit) | Decodierauflösung des Clips auf dem Bildschirm |
set-slow-decode-tier (auto, off) | Wenn die Decodierung nicht mithält |
set-gpu-decode (value) | GPU-Decodierung für NOVA (Beta): an, aus oder der Zustand |
set-gpu-yuv (value) | GPU-YUV-Upload für Filme (Beta): an, aus oder der Zustand |
set-gpu-video-decode (value) | GPU-Videodecodierung (Beta): an, aus oder der Zustand |
set-gpu-prores (value) | GPU-ProRes-Decodierung (Beta): an, aus oder der Zustand |
set-ram-limit-gb, set-vram-ring-limit-gb (value; 0 = Auto für VRAM) | Speicherbudgets |
set-hardware-decode (value) | Hardware-Decodierung |
ram-fit-apply, precache-playlist (value), full-quality (value), cache-clip-frames (clip_id) | Smart RAM-Fit, Vorladen |
ram-info (frames) | Speichernutzung, Clip für Clip |
cache-info, cache-purge (scope) | Kompressions-Cache: vorhanden, in dieser Version aber noch leer |
Review-Sitzungen
| Befehl | Wirkung |
|---|---|
session-create (name, user_name, password, reach: network oder this_computer) | Leiten; die Antwort liefert die Links |
session-join (address, user_name, password), session-leave | Beitreten, verlassen |
session-status | Der gesamte Sitzungszustand: Teilnehmer, Pilot, Stimme ... |
session-pass-baton (participant_id), session-set-sync (locked) | Kontrolle weitergeben; Local Review |
chat-send (text), chat-log (last) | Chat |
laser (x, y, active), laser-status | Laserpointer |
voice-test (seconds) | Einen Ton über den Sprachlautsprecher abspielen |
stream-enable (on, width, height), stream-status | Streaming zu Web-Gästen |
Tracker (kein Secret in irgendeiner Anfrage)
| Befehl | Wirkung |
|---|---|
tracker-sites | Die Sites aus trackers.json |
tracker-connect (site), tracker-disconnect (site, forget) | Verbindung |
tracker-projects, tracker-playlists (project_id) | Durchsuchen |
tracker-load-playlist (playlist_id, mode: replace oder append) | Eine Playlist laden |
tracker-publish (items, status, dry_run) | Die Notizen veröffentlichen |
tracker-download-media (index), tracker-cancel | Eine Vorschau herunterladen; abbrechen |
Diagnose
| Befehl | Wirkung |
|---|---|
status | Der gesamte Zustand des Players (siehe unten) |
system-info | Version, System, Grafikkarte, Bibliotheken; kein Name, kein Pfad |
dump-thumbnails (output, track) | Die Vorschaubilder der Timeline als PNG-Bogen |
quit | Den Player sauber schließen |
Der Player sendet diese Zeilen ungefragt an seinen Client:
| Ereignis | Felder |
|---|---|
play, pause | — |
frame_changed | frame: die Position, bei jedem Bild, in dem sie sich ändert (Wiedergabe, Ziehen, Sprung) |
export-done | ok, cancelled, error, frames_written, output, jobs, seconds, encoder |
tracker-connected | ok, site, user, reason |
tracker-projects, tracker-playlists | ok, projects oder playlists, reason |
tracker-loaded | ok, items, missing_media, reason |
tracker-publish-done | published, skipped, failed, dry_run |
tracker-download-done | index, ok, path oder reason |
status {"cmd": "status"} liefert den gesamten Zustand. Die nützlichsten Blöcke: playback (state, currentFrame, startOffset, fps, ab_mode, ab_view, transitioning, die Zähler late_frames und lost_frames), color (Grading von Spur A, Kanal), viewport (decodierte und originale Auflösung, proxy_idx, retiering, zoom), decode (Decodierzeit, too_slow), track_b, ram_fit und playlist (ein Eintrag pro Clip).
Den neuesten Render öffnen und abspielen (zum Beispiel aus einer Nuke-Schaltfläche):
client.open_media("D:/renders/SQ010_SH010_COMP_v003/SQ010_SH010_COMP_v003.1001.exr")
client.set_colorspace("ACEScg")
client.play()
Dem Playhead folgen (zum Beispiel, um eine Maya-Timeline im Gleichschritt zu halten):
client.on("frame_changed", lambda e: print("position", e["frame"]))
client.on("play", lambda e: print("playing"))
Dailies exportieren und auf das Ende warten:
client.export("D:/dailies/<clip>.mov", preset="dailies_prores_lt",
playlist=True, burn_in=True)
result = client.wait_for_export()
print(result["state"], result.get("error"))
Die Notizen eines Reviews einsammeln:
import json, os, time
out = "D:/review/SQ010_notes"
client.export_notes(out)
time.sleep(2) # the files are written in the background
notes = json.load(open(os.path.join(out, "export.json"), encoding="utf-8"))
Eine passwortgeschützte Review-Sitzung starten:
r = client.session_create(name="SQ010 dailies", password="...")
for link in r["links"]:
print(link["kind"], link["link"]) # lan, vpn...
Der Ordner api enthält die JSON-Schemas der ausgetauschten Dateien: playlist.schema.json (die .bpl-Playlist, mit dem Block x_tracking der Tracker-Kennungen), notes_payload.schema.json (das export.json der Notizen) und export_recipe.schema.json (Export-Rezepte) sowie Beispiel-Exportaufträge in export_examples/.
Siehe auch: Kommandozeile und Export ohne Fenster, Integrationen.