ofxOGraf is an openFrameworks addon for creating and rendering portable broadcast graphics using templates from SceneBuilder or After Effects.
Branches ahead of main
These branches have commits not yet on main — could be unmerged fixes or work in progress worth a look.
README
ofxOGraf
ofxOGraf is a tool-neutral openFrameworks authoring and runtime addon for portable broadcast graphics. Templates can be created directly with SceneBuilder or CodeTemplate; After Effects is an optional importer.After Effects composition
↓ export_broadcast_scene_v2.jsx
Broadcast Scene JSON
↓ ofxOGraf
openFrameworks (native or Emscripten/WebAssembly)
↓ OfBroadcastGraphic.js
EBU OGraf v1 rendererThe existing AE path is not a binary
.mogrt converter: it imports AE's scriptable scene model. Native scenes use the neutral Broadcast Scene 0.3 model, while unsupported source-specific features remain extensions or deterministic baked-frame fallbacks.What is included
after-effects/export_broadcast_scene_v2.jsx: recursive exporter for compositions, fonts, images, controls, sampled expressions, masks, mattes, effects, 3D transforms, and shape operators. The original MVP exporter remains available asexport_selected_comp.jsx.after-effects/import_mogrt_to_broadcast_scene.jsx: AE-assisted MOGRT opener, extracted-composition picker, and handoff to the neutral exporter.after-effects/bake_unsupported_layers.jsx: alpha-PNG fallback renderer for AE-only layers and effects.src/ofxOGrafAuthoring.andschema/broadcast-scene-0.3.schema.json: typed, tool-neutral C++ scene authoring with stable IDs, controls, assets, provenance, validation, and deterministic JSON.src/ofxOGrafCodeTemplate.: procedural OF template contract with typed descriptors, explicit time, deterministic random streams, and a lifecycle host.ofxOGraf::RenderSurface: fixed-resolution RGBA rendering, texture/FBO access, and aspect-fitted premultiplied-alpha native previews.scripts/validate-template-definition.mjs: native/WASM/OGraf descriptor and declared-asset validator.scripts/verify-ograf-package.ps1anddocs/package-integrity.md: reproducible ZIP, SHA-256 allowlist, BOM, provenance, offline policy, and deployment verification.docs/native-authoring.md: direct openFrameworks authoring, delivery, and deterministic-runtime guide.docs/css-text-overlays.md: optional descriptor-driven HTML/CSS typography above compiled C++/WebGL templates.schema/broadcast-scene-0.2.schema.json: expanded neutral interchange format; the original 0.1 schema remains for compatibility.src/: openFrameworks addon with deterministic timeline evaluation, asset caching, recursive scene rendering, renderer-extension hooks, AE-style 2D/3D transforms, a neutral controls API, and an optional ofxImGui adapter.example-basic/: dependency-free native/Emscripten example and embind lifecycle bridge.example-imgui/: native inspector example that opts into ofxImGui through its ownaddons.make.ograf/EssentialControls.js: reusable HTML control panel generated from the same neutralscene.controlsmodel.ograf/: OGraf v1 Web Component, manifest, real-time lifecycle, deterministic seeking, and scheduled non-real-time actions.examples/lower-third.scene.jsonandexamples/feature-showcase.scene.json: hand-authored baseline and expanded-feature scenes.examples/ograf-dev-*.scene.json: native ports of selected MIT-licensed ograf.dev tutorials.example-tutorials/: runnable native gallery; press1through4to switch graphics andRto replay the current animation.docs/future-proof-agent-plan.md: ordered roadmap and execution contract for coding agents.docs/scene-compatibility.md: supported scene versions, migration guarantees, and the process for adding future schemas.
Renderer scope
Implemented:
- absolute-time linear, hold, and influence-based Bezier interpolation;
- recursive parenting and precomposition timing;
- 2D and 3D layer transforms, opacity, and time stretch;
- cached TrueType fonts, UTF-8 text, tracking, leading, justification, fills, outlines, and bitmap fallback;
- shape rectangles, ellipses, cubic paths, fills, strokes, linear gradients, trim paths, repeaters, and approximate merge winding;
- masks and alpha track mattes through the stencil buffer;
- effect-derived Fill/Tint overrides plus effect and layer extension registries;
- sampled expression values and baked alpha-PNG fallback sequences;
- Essential Graphics controller discovery and neutral control storage;
- partial JSON data updates;
- OGraf load, dispose, play, update, stop, custom-action error response,
goToTime, andsetActionsSchedule.
- openFrameworks/FreeType metrics are not byte-identical to AE's shaping engine; use a text-layer extension or bake when exact shaping is required;
- merge paths use winding approximation, and track mattes currently implement alpha semantics;
- cameras, lights, arbitrary AE effects, live expression execution, and third-party plugins require an extension or baked fallback.
docs/renderer-support.md for the feature matrix and fallback strategy.Export from After Effects
For an existing After Effects-authored MOGRT, run
import_mogrt_to_broadcast_scene.jsx instead. After Effects extracts the project, the wrapper asks for its root composition, and then invokes the normal exporter. See docs/mogrt-import.md; Premiere-authored MOGRTs are outside this path.1. Open an AE project and make the desired composition active. 2. Run
after-effects/export_broadcast_scene_v2.jsx using File → Scripts → Run Script File. 3. Save the resulting .scene.json. 4. Review report.unsupported and report.warnings in the output. Run bake_unsupported_layers.jsx in AE when the report calls for a baked fallback. 5. Copy the scene and exported assets to example-basic/bin/data/ for native testing or ograf/ for packaging.Native openFrameworks build
Use openFrameworks Project Generator on
example-basic, then build it normally for your platform. It constructs and renders a neutral lower third directly in C++ with SceneBuilder. For procedural drawing, implement CodeTemplate and host it with CodeTemplateHost. The optional example-imgui inspector remains independent of the core addon. See docs/native-authoring.md and docs/essential-controls.md.example-basic also registers the compiled native-lower-third sample and exposes it to Emscripten. In OGraf, select it with code-template="native-lower-third" plus template-definition="./template-definition.json"; the normal scene attribute remains the declarative path.Emscripten build
Install the openFrameworks Emscripten platform/toolchain, then build the OGraf target:
scripts\build-ograf.ps1This keeps the classic localhost preview separate from the OGraf ES-module build, stages
ograf/dist/ofxOGraf.{js,wasm,data}, and creates build/ofxOGraf-graphic.zip. The OGraf module factory is createOfxOGrafModule.To compile the openFrameworks examples for browser preview:
scripts\build-emscripten-examples.ps1This builds
example-basic, example-tutorials, and example-imgui into bin\em\... with index.html, index.js, and index.wasm outputs.To build and host a specific example locally:
scripts\build-emscripten-examples.ps1 -Examples example-tutorials -Serve -ServeExample example-tutorials -Port 8080Then open
http://localhost:8080/ in your browser.OGraf package
Package the contents of
ograf/, including the generated dist artifacts and every scene asset. Serve the directory over HTTP for local preview; ES modules and WASM generally do not work reliably from file://.Create a server-ready ZIP after the Emscripten artifacts exist:
scripts\package-ograf.ps1The packager validates the manifest and referenced runtime files, generates
package-integrity.json and package-bom.json, enforces offline assets, and creates a deterministic archive. Verify the delivered artifact with scripts\verify-ograf-package.ps1 build\ofxOGraf-graphic.zip. For integration steps and the renderer conventions discovered in SuperFlyTV's implementation, see docs/testing-with-ograf-server.md.For a
CodeTemplate, pass its serialized descriptor and asset root explicitly:scripts\package-ograf.ps1
-TemplateDefinition build\template-definition.json
-AssetRoot build\dataThe packager validates the descriptor before staging, copies only its declared
data/ assets, validates that staged filesystem again, hashes the final allowlist, and then creates the ZIP. See docs/package-integrity.md.The manifest declares both real-time and non-real-time support. In non-real-time mode,
setActionsSchedule() stores the action timeline and goToTime() rebuilds scheduled state when seeking backward before positioning the WASM timeline at the requested millisecond.Validation
With Node.js available:
node scripts/validate.mjs
node tests/feature-contract.mjs
node tests/controls-contract.mjs
node tests/authoring-contract.mjs
node tests/code-template-contract.mjs
node tests/css-text-overlay-contract.mjs
node tests/golden-frame-contract.mjs
node scripts/validate-template-definition.mjs
node tests/code-template-delivery-contract.mjs
node tests/package-contract.mjs
node tests/package-integrity-contract.mjs
node tests/scene-migration-contract.mjs
node --check ograf/OfBroadcastGraphic.js
node --check ograf/EssentialControls.jsThe committed
ograf/dist/.gitkeep is intentional; generated WASM artifacts are ignored.Production hardening
Before on-air use, add AE-vs-runtime golden-frame tests for the exact templates, fonts, effects, and GPU drivers in the deployment environment. Register project-specific text/effect handlers for anything that must remain editable and bake the rest.
Standards basis
The package targets the stable EBU OGraf Graphics specification v1. Its manifest uses the normative v1 schema and its custom element implements the required default export and lifecycle methods. The separate OGraf Server/Control API is intentionally outside this addon so draft API changes cannot leak into the scene runtime.
ofxAddons