NAMEFRAME Frame the world. Name the frames.

Studio recipe reference

A recipe is one YAML file describing an entire dataset run: the scene, the camera, the environment, the population rules and the label taxonomy. It is the file Studio's Save recipe button writes, and the file studio-compile consumes.

The lifecycle of a recipe#

# check it without touching Unreal
nameframe studio-validate my_recipe.yml

# see the randomisation it will actually produce
nameframe studio-dry-run my_recipe.yml _local/plans/my_recipe --samples 20

# compile to the low-level plugin job
nameframe studio-compile my_recipe.yml _local/jobs/my_recipe.json

# run it against an open editor
nameframe capture-unreal _local/jobs/my_recipe.json --verify --dataset-out _local/datasets/my_recipe

The smallest valid recipe#

Three things are mandatory: an output folder, a positive frame count, and at least one class with a selector.

capture:
  out_dir: D:/NameFrame/_local/dumps/first
  frames: 100
  seed: 42

classes:
  - label: crate
    select:
      prefix: SM_Crate_

Top-level sections#

SectionRequiredControls
captureyesOutput folder, frame count, seed, depth
classesyesLabels, actor selectors, keypoint policy
scenenoThe Unreal map this recipe expects
cameranoResolution, FOV, motion, zones, rigs, calibration
viewpoint_validationnoRejecting and resampling unusable views
environmentnoWeather driver, sun, fog, clouds, settle time
rendernoRGB quality, exposure, bloom, ray tracing, QA thresholds
performancenoThroughput profile and per-stage waits
populationnoSpawn zones, scatter, spacing, clusters, groups
sensornoOffline lens and sensor simulation applied after capture
visibilitynoHiding non-target actors for clean subsets
name, presetnoHuman name and stable id, carried into the job

capture#

capture:
  out_dir: D:/NameFrame/_local/dumps/beach
  frames: 500
  seed: 42
  write_depth: true

out_dir and a positive frames are required. seed makes the run reproducible: same seed, same frames. write_depth writes depth.npy per frame. Scene depth is still rendered for occlusion labels either way, so turning it off saves disk rather than render time.

classes#

Each class needs a label and exactly one positive selector.

SelectorMatches
prefixActors whose name starts with the string
actor_tagActors carrying that Unreal tag
class_nameActors of that class, for example BP_FoodPlate_C
class_pathActors of that full class path
exclude_prefixNegative filter on name prefix
exclude_actor_tagNegative filter on tag
classes:
  - label: person
    select:
      prefix: BP_RB_
    keypoints: coco

  - label: car
    actor_tag: DatasetTargetCar
    keypoints: none

  - label: food
    class_name: BP_FoodPlate_C
    keypoints: none

Selectors can be nested under select: or written flat. Both work, but do not set the same selector twice.

Keypoints

keypoints: coco emits the 13-joint human pose profile. Everything that is not a human (vehicles, props, food, tools, most animals) should use keypoints: none, which is also the default.

camera#

camera:
  width: 1280
  height: 960
  hfov_deg: 57.3
  altitude_m: [16, 34]
  radius_m: [8, 42]
  lookat_jitter_m: [0, 8]
  min_fill_ratio: 0.12
  near_clip_cm: 10
  far_clip_cm: 200000
  export_intrinsics: true
  camera_zones:
    - name: beach_drone_lane
      center_m: [5, -16, 0]
      radius_m: [8, 42]
      altitude_m: [16, 34]

Any numeric field accepting a range takes [min, max] and gets sampled per frame. Field of view can be given as hfov_deg, fov_deg, or as focal_length_mm plus sensor_width_mm. The compiler derives the horizontal FOV either way.

Other camera keys: fixed_camera_actor to use a named CameraActor, flight_path to follow a named spline, camera_poses for an explicit pose list, and a multi-camera rig with multi_camera set to sample, all or all_per_frame.

viewpoint_validation#

Rejects unusable camera samples and draws again, before the frame is written.

viewpoint_validation:
  enabled: true
  min_targets: 1
  max_targets: 0
  min_visible_percent: 20
  min_bbox_width_px: 16
  min_bbox_height_px: 16
  require_fully_visible: false
  max_retries: 12
  reject_empty_segmentation: true
  reject_invalid_depth: true
  reject_blur: false
  reject_exposure: false
  min_depth_valid_percent: 95
  min_focus_score: 2.5
  min_mean_luma: 35
  max_mean_luma: 220
  fallback: stop_job

fallback takes stop_job, skip_frame, continue or relax_constraints. Also available: min_camera_distance_m, max_camera_distance_m, reject_camera_collision and reject_under_landscape.

environment#

Choose one driver. Omit weather_driver and NameFrame's built-in weather is used unless UDS/UDW keys are present. The nine built-in profiles, their exact sun/fog/cloud ranges, and the complete Ultra Dynamic Sky surface are in Weather, sky and UDS.

Built-in weather

environment:
  weather_driver: builtin
  weather: random
  weather_profiles:
    - {name: clear_sun, weight: 40}
    - {name: fog, weight: 20}
    - {name: rain, weight: 20}
    - {name: storm, weight: 10}
    - {name: snow, weight: 10}
  sun_elevation_deg: [30, 60]
  sun_azimuth_deg: [0, 360]
  fog_density: [0.0, 0.4]
  weather_settle_seconds: 0.75

Ultra Dynamic Sky / Weather

environment:
  weather_driver: ultra_dynamic
  ultra_dynamic_sky:
    Time of Day: [900, 1700]
    Cloud Coverage: [0, 10]
  ultra_dynamic_weather:
    Weather: [clear_skies, rain_light, snow]
  weather_settle_seconds: 1.5
Exposure with UDS

UDS spans many times of day. If you do not set render.fixed_exposure explicitly, the compiler switches to adaptive exposure for the dynamic driver, because a fixed negative bias inherited from a sunny-only render profile turns valid daytime frames nearly black.

render#

render:
  profile: beach_sunny_drone
  quality: cinematic
  fixed_exposure: true
  exposure_bias: -1.8
  motion_blur_amount: 0.0
  bloom_intensity: 0.65
  ambient_occlusion_intensity: 1.6
  use_ray_tracing_if_enabled: true
  rgb_underexposed_luma: 30.0
  rgb_overexposed_luma: 238.0
  rgb_low_contrast_std: 14.0

Two named profiles ship with the compiler, beach_sunny_drone and concrete_daylight, and they preset both environment and render values. Anything you set explicitly wins over the profile. quality takes standard or cinematic. The three rgb_* values are QA thresholds used to flag frames as under-exposed, over-exposed or low-contrast.

performance#

performance:
  profile: safe
  render_quality: standard
  streaming_timeout_seconds: 5
  weather_batch_frames: 1
  progress_interval_frames: 1

profile takes safe, balanced, fast or custom. Boolean fields control the individual wait and warmup steps: finish asset compilation, warm target shaders, stream level resources, pin target textures, reset temporal history after camera moves, batch weather, record stage timings.

population#

population:
  ground_actor_prefix: Landscape
  max_ground_clearance_m: 2.0
  use_level_spawn_zones: true
  scatter_existing_targets: true
  shuffle_per_frame: true
  scatter_radius_m: [0.5, 4.0]
  scatter_yaw_deg: [0, 360]
  scatter_min_spacing_m: 0.5
  scatter_max_slope_deg: 30
  scatter_max_attempts: 120
  spawn_zones:
    - name: beach_people_area
      center_m: [5, -16, 0]
      radius_m: [0, 45]
      labels: [person]

Clusters, relatives, groups and distances

population:
  cluster_spawn:
    - label: person
      cluster_count: [2, 5]
      actors_per_cluster: [2, 6]
      cluster_radius_m: [3, 12]
      zone: main_spawn

  relative_spawn:
    - label: person
      relative_to: vehicle
      count: [2, 8]
      distance_m: [3, 20]

  inter_class_distances:
    - between: [person, vehicle]
      min_m: 1.5

Group definitions and nested group spawning are also supported, as are named spatial distribution profiles and exact anchor constraints. The example recipes under examples/ whose names end in _testing.yml each demonstrate one of these features end to end.

Declarative distributions#

Any numeric field sampled by the planner can take a distribution object instead of a range.

camera:
  hfov_deg:
    distribution: uniform
    min: 45
    max: 75
  radius_m:
    distribution: normal
    mean: 14
    std: 3
    min: 6
    max: 28
  altitude_m:
    distribution: triangular
    min: 10
    mode: 18
    max: 32

Preview one as JSON plus an SVG histogram before committing to it:

nameframe distribution-preview "{\"distribution\":\"normal\",\"mean\":14,\"std\":3,\"min\":6,\"max\":28}" _local/reports/dist_radius

sensor#

Applied offline, after capture, by the report and dataset exporters. Change it and re-export without re-rendering.

sensor:
  enabled: true
  profile: random
  strength: 1.0
  profile_weights: "realistic_drone:40,dashcam:25,rainy_lens:20,cctv:15"
  save_clean_images: true
  save_segmentation: false

Twenty-seven distinct looks ship under forty names, plus the four random aliases. The full catalogue, the default random weights, and the individual parameters you can override through sensor.effects are in Camera lens profiles. With save_clean_images: true you keep the un-degraded frames alongside the processed ones.

visibility#

Hides actors that resemble targets but must not be labelled, producing a clean subset dataset.

visibility:
  hide_non_target_prefixes: [BP_RB_]
  hide_non_target_actor_tags: [Crowd]
  hide_non_target_class_names: [BP_Extra_C]

Studio warnings#

The compiler emits studio_warnings for risky-but-allowed jobs: no map guard, no custom camera zone, automatic exposure, default RGB QA thresholds, or a target subset with no visibility policy. They never block a capture, they just make the job reviewable. Read them after every studio-compile.

Promoting a recipe to a managed scenario#

For repeatable project work, put recipes under the Scenario Manager. It adds stable ids, immutable versions, config hashes, change notes, archive and duplicate operations, and field-level comparison between versions.

nameframe scenario-init _local/scenarios
nameframe scenario-create _local/scenarios examples/studio_generic_object_detection.yml --id generic-object
nameframe scenario-version _local/scenarios generic-object examples/studio_generic_object_detection.yml --note "wider altitude range"
nameframe scenario-compare _local/scenarios generic-object --from v001 --to v002

Turn a folder of recipes into a browsable HTML gallery:

nameframe presets examples _local/reports/presets

Or start a new one from a template:

nameframe preset-new _local/recipes/my_preset.yml