Controle Bernard Review desde un script o una aplicación del pipeline. El protocolo, el cliente de Python, cada comando por familia, los eventos y ejemplos completos.
Bernard Review puede controlarse desde Python, Maya, Nuke, Houdini, un tracker de producción o cualquier lenguaje capaz de abrir una conexión TCP. Todo lo que un artista hace a mano tiene su comando: abrir clips, reproducir, comparar, corregir el color, exportar, iniciar una sesión, publicar notas. Esta página basta para automatizar el reproductor; la referencia exhaustiva, campo por campo, es la referencia de la API, en inglés (también abierta por Help > API Documentation).
127.0.0.1, puerto 5556 por defecto. Un reproductor iniciado con --ipc-port N escucha en N: así es como dos reproductores funcionan en la misma máquina.\n, con un campo "cmd": {"cmd": "seek", "frame": 24}.{"status": "ok", "cmd": "seek", ...} o {"status": "error", "cmd": "seek", "reason": "..."}. Un error siempre lleva un motivo en lenguaje llano y nunca espera a su tiempo de espera. No hay identificador de petición: una respuesta se asocia a su petición por su "cmd".{"event": ...}) llegan por la misma conexión, mezclados con las respuestas (véase más abajo).Host:) se cierra sin ejecutar nada: una página web no puede controlar el reproductor. Una línea contiene como máximo 16 MiB.Para probarlo sin escribir código: Window > Console (Ctrl+Mayús+C) envía los mismos comandos desde el propio reproductor, con autocompletado con Tab: status, seek {"frame": 24}, o la forma JSON completa. Pregunta antes de los comandos que escriben archivos, publican o cierran el reproductor.

bernard_api.py envuelve el protocolo en una clase, BernardClient, con un método por comando. Se instala junto al reproductor, en la carpeta api:
| Sistema | Ubicación |
|---|---|
| Windows | C:\Program Files\Bernard Review\bin\api\bernard_api.py |
| Linux (RPM) | /usr/share/bernardplayer/api/bernard_api.py |
Linux (archivo .sh) | <install folder>/share/bernardplayer/api/bernard_api.py |
No necesita nada más que la biblioteca estándar de 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) envía un comando y espera su respuesta (un dict), errores incluidos: no lanza ninguna excepción por la negativa del reproductor, y devuelve None si se agota el tiempo de espera o se pierde la conexión.send_command(dict) envía sin esperar.play(), seek(), set_exposure(), export()...) llaman a uno u otro; los que devuelven datos pasan por request().on("frame_changed", function) suscribe una función a un evento; un hilo en segundo plano lee la conexión.Sin el cliente, bastan unas pocas líneas:
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 y la opción --frame toman la posición en el clip contada desde 0, no el número impreso en la regla. En un clip que empieza en 1001, el fotograma mostrado 1010 es la posición 9. status da la posición (playback.currentFrame) y el número del primer fotograma (playback.startOffset).open responde antes de que se sondee el clip: status.playback.transitioning permanece en true hasta que el clip está en pantalla. export pone un trabajo en cola: sígalo con export-status o con el evento export-done. export-notes escribe sus archivos en segundo plano. Tras set-proxy, espere a que status.viewport.retiering vuelva a false.{"cmd": "set-ui-level", "value": "complete"}.quit responde y después cierra el reproductor de forma limpia, sin preguntar si se guarda: envíe antes save-playlist o export-notes si la revisión importa.Los 115 comandos del reproductor. Los campos entre paréntesis son los principales; track es "A" (el valor por defecto) o "B".
Reproducción y rango
| Comando | Efecto |
|---|---|
play, pause, reverse-play | Reproducir, pausa, reproducir hacia atrás |
seek (frame) | Ir a una posición (desde 0) |
step-frame (delta) | Avanzar o retroceder delta fotogramas |
toggle-loop | Repetir el rango en bucle |
set-playlist-playback (loop_mode 0, 1 o 2, dont_wait_incomplete_shots) | Bucle desactivado, sobre el clip o sobre la playlist |
set-in, set-out (frame, opcional) | Puntos de entrada y de salida; sin frame, el cabezal |
clear-in-out, set-in-out-lock (value) | Borrar el rango; impedir que el ratón lo mueva |
set-fps (value), set-start (value) | Frecuencia de imagen; número del primer fotograma |
set-volume (value de 0 a 1), set-mute (value), toggle-mute | Sonido |
Clips y playlist
| Comando | Efecto |
|---|---|
open o load (path) | Abrir un archivo o una secuencia en la pista A, añadiéndolo a la playlist |
load-playlist (path) | Cargar una playlist .bpl, .otio, .csv, .json o .edl |
save-playlist (path) | Escribir la playlist como .bpl (notas, estados, corrección de color, dibujos) |
playlist-add (path), playlist-play (index), playlist-remove (index), playlist-move (from, to), playlist-clear | Gestionar la playlist (índices desde 0) |
drop (paths, at: track_a, track_b o viewport_b) | Como soltar archivos desde el explorador de archivos |
Comparación y versiones
| Comando | Efecto |
|---|---|
set-ab-mode (value), toggle-ab | Modo A/B |
set-track-b (path) | Poner un archivo en la pista B |
set-ab-view (value: a, wipe, b), ab-flip | Solo A, cortinilla, solo B; intercambiar A/B |
set-wipe (position de 0 a 1, angle en grados) | Posición y ángulo de la cortinilla |
cycle-b (direction: prev, next) | Versión anterior o siguiente en B |
pin-track-b (value), set-b-version-preload (value) | Fijar B; precargar las versiones vecinas |
set-ab-label-mode (interaction, always, never), set-metadata-track (a, b, ab) | Letras A/B; la pista de la pestaña Metadata |
build-matrix (sequence, id, shots), get-matrix | Rellenar y leer el Version Board (véase Integraciones) |
Color
| Comando | Efecto |
|---|---|
set-exposure, set-gamma (value, track) | Exposición (en stops), gamma |
set-white-balance (temp, tint de -1 a 1, track), set-offset (value: [r, g, b], track) | Balance de blancos, offset |
set-colorspace (value) | Espacio de entrada de la pista A: ACEScg, sRGB, AP0, AdobeRGB, ProPhoto, Rec709, LogC3, LogC4, o Auto |
set-channel (value: RGBA, R, G, B, A, L; track) | Canal mostrado |
set-stage (stage, on, track) | Desactivar o activar una etapa (exposure, levels, curves, gamma...) |
set-curve (channel: master, r, g, b; points o reset) | Curvas, puntos [x, y] en el eje ACEScct |
set-hue-range (range, hue, saturation, lightness) | Rangos de tono |
color-panel (target, before_after, picker, levels_auto, preset_save, preset_apply...) | El panel de color; sin ningún campo, lo lee |
scopes (open, kind) | Los scopes y sus últimas medidas (histograma, recorte) |
set-layer (track_idx, layer_idx), layer-info (track) | Pase de un EXR multicapa |
Visor, interfaz y ventanas
| Comando | Efecto |
|---|---|
zoom (value, 1 = un píxel de origen por píxel de pantalla), pan (x, y), fit, flip | Encuadre |
set-fullscreen (value), set-window-size (width, height), set-ui-scale (percent) | Ventana principal |
set-theme (dark, light, neon, system; o sombre, clair, systeme), set-ui-level (essential, complete) | Modo de visualización y nivel de la interfaz |
reset-layout, new-window (view), close-window (name o all), windows | Disposición y copias de paneles |
contact-sheet (open, mode, card_w...) | Hoja de contactos |
set-tool (tool: pen, text, arrow, rect, laser, eraser, pipette, select) | Herramienta de dibujo |
debug-mouse (x, y, down, alt, release) | Ratón simulado, para pruebas de la interfaz |
Notas, capturas y exportación
| Comando | Efecto |
|---|---|
export-notes (output_dir) | Escribir export.json y export.html sin ningún cuadro de diálogo |
screenshot (output, frame, annotations) | Un PNG del clip de la pista A, con la corrección de color como en pantalla |
export (output, preset, source, playlist, format, codec, color, burn_in, annotations, watermark, recipient...) | Exportar fotogramas o una película; en cola |
export-status, export-cancel, export-presets | Seguir, cancelar, enumerar los preajustes |
export-recipe (action: list o run; name, file o recipe; clips, recipient) | Recetas de exportación |
Memoria y decodificación
| Comando | Efecto |
|---|---|
set-proxy (proxy_idx: 0 = 1/1, 1 = 1/2, 2 = 1/4, 3 = 1/8, 4 = Smart RAM-Fit) | Resolución de decodificación del clip en pantalla |
set-slow-decode-tier (auto, off) | Cuando la decodificación no da abasto |
set-gpu-decode (value) | Decodificación en GPU para NOVA (beta): activada, desactivada, o el estado |
set-gpu-yuv (value) | Carga YUV en GPU para películas (beta): activada, desactivada, o el estado |
set-gpu-video-decode (value) | Decodificación de vídeo en GPU (beta): activada, desactivada, o el estado |
set-gpu-prores (value) | Decodificación ProRes en GPU (beta): activada, desactivada, o el estado |
set-ram-limit-gb, set-vram-ring-limit-gb (value; 0 = Auto para la VRAM) | Presupuestos de memoria |
set-hardware-decode (value) | Decodificación por hardware |
ram-fit-apply, precache-playlist (value), full-quality (value), cache-clip-frames (clip_id) | Smart RAM-Fit, precarga |
ram-info (frames) | Uso de memoria, clip a clip |
cache-info, cache-purge (scope) | Caché de compresión: presente, pero todavía vacía en esta versión |
Sesiones de revisión
| Comando | Efecto |
|---|---|
session-create (name, user_name, password, reach: network o this_computer) | Organizar; la respuesta da los enlaces |
session-join (address, user_name, password), session-leave | Unirse, salir |
session-status | Todo el estado de la sesión: participantes, piloto, voz... |
session-pass-baton (participant_id), session-set-sync (locked) | Ceder el control; Local Review |
chat-send (text), chat-log (last) | Chat |
laser (x, y, active), laser-status | Puntero láser |
voice-test (seconds) | Reproducir un tono por el altavoz de la voz |
stream-enable (on, width, height), stream-status | Retransmisión a los invitados web |
Trackers (ningún secreto en ninguna petición)
| Comando | Efecto |
|---|---|
tracker-sites | Los sitios de trackers.json |
tracker-connect (site), tracker-disconnect (site, forget) | Conexión |
tracker-projects, tracker-playlists (project_id) | Explorar |
tracker-load-playlist (playlist_id, mode: replace o append) | Cargar una playlist |
tracker-publish (items, status, dry_run) | Publicar las notas |
tracker-download-media (index), tracker-cancel | Descargar una previsualización; cancelar |
Diagnóstico
| Comando | Efecto |
|---|---|
status | Todo el estado del reproductor (véase más abajo) |
system-info | Versión, sistema, tarjeta gráfica, bibliotecas; sin nombre, sin ruta |
dump-thumbnails (output, track) | Las miniaturas de la timeline como una hoja PNG |
quit | Cerrar el reproductor de forma limpia |
El reproductor difunde estas líneas a su cliente, sin que se las pidan:
| Evento | Campos |
|---|---|
play, pause | — |
frame_changed | frame: la posición, en cada fotograma en que cambia (reproducción, arrastre, salto) |
export-done | ok, cancelled, error, frames_written, output, jobs, seconds, encoder |
tracker-connected | ok, site, user, reason |
tracker-projects, tracker-playlists | ok, projects o playlists, reason |
tracker-loaded | ok, items, missing_media, reason |
tracker-publish-done | published, skipped, failed, dry_run |
tracker-download-done | index, ok, path o reason |
status {"cmd": "status"} devuelve todo el estado. Los bloques más útiles: playback (state, currentFrame, startOffset, fps, ab_mode, ab_view, transitioning, los contadores late_frames y lost_frames), color (la corrección de la pista A, canal), viewport (resolución decodificada y original, proxy_idx, retiering, zoom), decode (tiempo de decodificación, too_slow), track_b, ram_fit y playlist (una entrada por clip).
Abrir el último render y reproducirlo (desde un botón de Nuke, por ejemplo):
client.open_media("D:/renders/SQ010_SH010_COMP_v003/SQ010_SH010_COMP_v003.1001.exr")
client.set_colorspace("ACEScg")
client.play()
Seguir el cabezal de reproducción (para mantener sincronizada una timeline de Maya, por ejemplo):
client.on("frame_changed", lambda e: print("position", e["frame"]))
client.on("play", lambda e: print("playing"))
Exportar dailies y esperar al final:
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"))
Recoger las notas de una revisión:
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"))
Iniciar una sesión de revisión protegida con contraseña:
r = client.session_create(name="SQ010 dailies", password="...")
for link in r["links"]:
print(link["kind"], link["link"]) # lan, vpn...
La carpeta api contiene los esquemas JSON de los archivos intercambiados: playlist.schema.json (la playlist .bpl, con el bloque x_tracking de identificadores del tracker), notes_payload.schema.json (el export.json de las notas) y export_recipe.schema.json (recetas de exportación), y trabajos de exportación de ejemplo en export_examples/.
Véanse también: Línea de comandos y exportación sin ventana, Integraciones.