Understanding the OpenMAIC Playback Engine State Machine: Four Core Modes Explained

The OpenMAIC playback engine operates as a finite-state machine with four distinct EngineMode states—idle, playing, paused, and live—that manage transitions between recorded lecture playback and live discussion phases.

The THU-MAIC/OpenMAIC repository provides a sophisticated playback system designed for educational content delivery. At its core, the OpenMAIC playback engine state machine orchestrates how recorded lectures transition into live discussions through well-defined state transitions enforced in lib/playback/engine.ts.

The Four EngineMode States

The current operational mode is represented by the EngineMode type defined in lib/playback/types.ts (lines 17-19). The engine maintains exactly one of four mutually exclusive states at any time, visualized in the engine documentation comment (lines 9-24 of engine.ts).

Idle State

The idle state represents complete inactivity with no playback activity occurring. When the engine initializes or completes a session, it rests here awaiting activation. According to the documentation in engine.ts#L9-L24, the engine accepts start() or continuePlayback() commands only from this state to begin processing content.

Playing State

The playing state indicates active processing of recorded educational content. In this mode, the engine sequentially handles actions including lecture speech synchronization and whiteboard stroke rendering. This represents the standard operational mode during recorded lecture playback, where the system processes stored action sequences.

Paused State

When users interrupt playback or the system requires temporary halting, the engine enters the paused state. Unlike idle, this state preserves the current playback position and context, allowing immediate resumption back to playing via the resume() method. The engine enforces this state through checks such as this.mode === 'playing' before allowing pause operations.

Live State

The live state handles post-lecture discussion phases that follow recorded content. Triggered by handleEndDiscussion(), this mode transitions the engine away from recorded sequences into real-time interaction. While in live, the engine supports pause() and resume() operations but no longer follows the recorded action sequence, as enforced by validation logic such as this.mode !== 'live' in playback control methods.

State Transitions and Code Implementation

The state machine enforces strict transition rules throughout [lib/playback/engine.ts](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/playback/engine.ts). State changes occur through specific method invocations that validate the current mode before executing transitions.

import { PlaybackEngine } from 'lib/playback/engine'

// Initialize engine with scenes, action engine, and audio player
const engine = new PlaybackEngine(scenes, actionEngine, audioPlayer)

// Transition: idle → playing
engine.start()

// Transition: playing → paused
engine.pause()

// Transition: paused → playing
engine.resume()

// Transition: playing → live (end of lecture, start discussion)
engine.handleEndDiscussion()

The implementation guards against invalid transitions by checking the current this.mode property. For example, certain playback controls are disabled when this.mode === 'live', while others require this.mode === 'playing' to execute.

Source Code Architecture

The playback engine state machine spans two critical files in the codebase:

Summary

  • idle – Awaiting initialization via start() or continuePlayback(); no active processing occurs
  • playing – Actively processing recorded lecture actions including audio and whiteboard strokes
  • paused – Temporary halt preserving playback context; can resume to playing state
  • live – Handling real-time discussion phases; supports pause/resume but ignores recorded sequences

Frequently Asked Questions

What triggers the transition from playing to live in OpenMAIC?

The transition occurs when handleEndDiscussion() is invoked on the playback engine, typically signaling the end of a recorded lecture segment and the beginning of a live discussion phase. This method moves the engine from processing recorded actions into a real-time interactive mode where the recorded timeline no longer governs behavior.

How does the engine handle pausing during live mode?

While in live state, the engine supports both pause() and resume() operations similarly to the playing state. However, these actions control real-time discussion flow rather than recorded content playback. The engine maintains validation checks to ensure pause commands are valid regardless of whether the mode is playing or live.

Where is the EngineMode type defined in the OpenMAIC repository?

The EngineMode type is defined as a TypeScript union type in [lib/playback/types.ts](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/playback/types.ts) at lines 17-19. This definition constrains the engine's mode property to the four valid states: 'idle', 'playing', 'paused', or 'live'.

Can the OpenMAIC engine start playback directly from the paused state?

No, the engine cannot initialize directly into paused state. According to the state machine implementation in engine.ts, entering paused requires an active transition from playing (or potentially live). To begin playback, the engine must first transition from idle to playing via start() or continuePlayback() before any pause operations become valid.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →