Scene Playback And Directing
Last reviewed: 2026-06-30
Playback Model
PresentationController treats each config scene as a playback unit. It preloads scene media into LoadedSceneAsset, builds a resolved timeline, then plays scenes in order.
| Step | Behavior |
|---|---|
| Preload | Load first scene image, voiceover audio, background audio, and bot motion plan. |
| Start capture | Begin AVPro capture when local capture or remote render requires it. |
| Present scene | Trigger scene index, set image texture, transition camera, apply bot motion, play voiceover. |
| Wait | Wait for audio duration or timing fallback, then scene pause. |
| Progress | For remote renders, emit percentage progress through Python protocol. |
| Complete | Stop capture and wait for AVPro final file callback. |
Timing
Timing comes from a mix of config and loaded media:
| Source | Use |
|---|---|
voiceover.audio.durationSeconds |
Duration estimate when audio clip length is unavailable. |
Loaded AudioClip.length |
Preferred scene audio duration when clip loads. |
timing.start / timing.end |
Fallback scene duration and ordering context. |
timing.pauseSeconds |
Pause after a scene. |
| Capture frame rate | Offline/manual audio capture frame stepping. |
Voiceover word timings are not used to schedule scene playback in the main controller. They are bound to AnuvaBotAnimator for bot cadence and to virtual screens only through the separate screen-content controller/builder path.
Voiceover Playback
Voiceover audio is loaded through UnityWebRequestMultimedia.GetAudioClip() with audio type inferred from URL extension. The controller creates scene audio sources under audioSourceParentObject or an owned root. It supports real-time Unity audio capture and offline/manual audio encoding into AVPro.
Background audio is loaded separately from audio.background.url, looped/mixed during timeline playback, and volume-controlled by config.
Camera Directing
PresentationController.CamTransition() routes shots through:
CameraSpaceTogglerforFullScreencanvas mode.CamController.SetCameraShot()for named camera shot cuts.- DOTween orbit or zoom-in animation.
The config field directing.camera.shot is consumed, but supported values are bounded by CameraShots.json and the serialized camShots array. If the config shot is not found, the controller falls back to Unity-side behavior. This means camera direction is currently partly deterministic and partly Unity fallback-driven.
Bot Behavior
Bot motion follows this priority:
- If
useBotMotionPlanis true and a scene plan exists, play timed beats fromPresentationBotMotionPlan. - If no scene plan exists, apply
PresentationScene.motiondirectly. - Bind voiceover word timings when available so secondary motion can respond to speech cadence.
- If no animator exists or
applyBotMotionis false, bot motion is skipped.
Anuva_TataMotors_Scene contains AnuvaBotAnimator, bot anchors, look targets, and tester components. Other scenes may have no bot animator wiring.
Screen Transitions
The main controller confirms direct image swapping onto a presentation renderer. The generated virtual-screen path has its own scheduler:
playbackOrderentries drivegoToSlide/showEvent.- fragment timings drive
showFragment. - emphasis event end timings drive
hideEvent.
Integration between PresentationController and AnuvaVirtualScreensPlaybackController is Unknown / not confirmed in repo; both systems can load PresentationConfig.json, but no direct call from the main controller to the virtual-screen controller was found.