Architecture & Plugin Lifecycle
TransBox is pipeline-centric: audio or captions come in → recognition → translation → display/speech. Plugins attach at well-defined extension points.
1. Pipeline & Middleware Insertion Points
[Audio capture / Browser captions]
│
▼
process_audio ← middleware
│
▼
VAD segmentation
│
▼
ASR recognition ← asr Provider
│
▼
process_transcript ← middleware
│
▼
Glossary prompt inject + MT ← mt Provider + glossary
│
▼
process_translation ← middleware
│
├──► UI subtitles
└──► TTS speech ← tts Provider
│
▼
process_tts_audio ← middleware
│
▼
Sound-card playbackMiddleware runs in ascending priority order (smaller number runs first; default 100). An exception thrown by a single middleware is isolated and does not bring down the chain.
Glossary actual order: inject the prompt before translation → mt.translate(...) → middleware rewrites the translation → forced glossary replacement.
2. Plugin Discovery
Scanned at startup:
- Built-in manifests (builtin engines, default theme, browser caption bridge, etc.)
- Application/project
extensions/*/ %APPDATA%/transbox/extensions/*/- Steam:
steamapps/workshop/content/1316080/*/(each subdirectory must containmod.json)
Manifest filename: mod.json preferred, falls back to manifest.json. Manifests without an id are rejected.
UI toggle states are written to QSettings (plugins_state) and restored on the next launch.
3. Enable / Disable Behavior (code facts)
| Type | Enable | Disable |
|---|---|---|
glossary | Register into the global glossary manager | Unregister |
i18n | Switch to that language; mutually exclusive with other third-party language packs | If currently active, fall back to zh-CN |
theme (full) | Apply the theme; mutually exclusive with other full themes | Fall back to the default theme |
| UI extensions in the same slot | Occupy the same slot; mutually disable others | Remove that slot's component |
asr/mt/tts | Can be set as the current engine | If it is the active engine, fall back to another enabled engine |
middleware | Attach to the middleware manager | Unload |
| Built-in default theme | Cannot be disabled | — |
| Built-in browser caption bridge | Tied to the Web service toggle | Tied shutdown of the service |
4. Python Class Loading
For asr / mt / tts / middleware:
- Parse
entrypointasrelative_path.py:ClassName(if no colon,ClassName="Plugin") - Load the module from file via
importlib - The class must inherit a
BasePluginsubclass cls(manifest)→initialize(config)- Instance is cached; call
shutdown()on unload
Configuration:
- The UI renders a form from
config_schema - Saved under QSettings
plugins_config/<id> - Python reads it from
self._config;update_configapplies hot updates
5. Relationship with the UI
- Subtitle, settings, history, and other windows load QML through slots (see UI Slots).
- With
has_settings_tab: true, enabling the plugin adds a Tab to Settings (tab_id/tab_title). - Engine plugins do not need to write a settings UI: declare
config_schemaand a form is generated automatically.
6. Security Model (read this)
- No sandbox: Python plugins run in the same process with the same permissions as the host application.
- Data-type plugins (
theme/glossary/i18n) are lower risk; audit script-type plugins before installing. - The Workshop provides a security notice and a one-click disable-all third-party extensions control.