Plugins
Plugins extend Streamdat without forking core code. They ship as Python packages with a plugin.json manifest and load through app.plugin.loader.
Plugin types
Six kinds are supported today (see PLUGIN_TYPE_MAP in the app repo):
highlight_detector— propose highlight spans from transcript + duration + config.caption_generator— produce caption text from segments and plain text.style_interpreter— map a natural-language style brief into renderer parameters.posting_strategy— suggest a schedule over clips and linked social accounts.pre_render— adjuststyle_paramsbefore FFmpeg runs.post_render— inspect the rendered file path and return optional warnings or metadata.
Manifest
Each plugin directory contains plugin.json with name, type, version, entrypoint (module.ClassName), and optional schema_version, compatible_core (PEP 440 specifier against core semver), permissions, and signatures. Optional .deps/ (from pip install --target) is prepended to sys.path before import.
{
"name": "my_plugin",
"type": "highlight_detector",
"version": "1.0.0",
"schema_version": "1",
"compatible_core": ">=1.0.0,<2.0.0",
"description": "What this plugin does.",
"entrypoint": "main.MyPluginClass",
"permissions": []
}HTTP API
Authenticated users can list plugins and read configs. Admin-only routes install from Git, rescans the plugin directory into the database, toggles enablement, patches config_json, and uninstalls. Shapes are defined on the /api/plugins router in the backend — cross-check the live contract in Swagger.
Sandboxing
When config_json.sandboxed is true, execution uses a subprocess with a trimmed environment and JSON context passed in; the child prints JSON on stdout. Timeouts apply so runaway plugins cannot block the worker indefinitely.
Examples
Reference implementations ship under backend/plugins/ in Streamdat_app (for example keyword_highlighter and emoji_captions). Copy one as a template, change the manifest and class, then run POST /api/plugins/sync or install from a Git URL where your org enables that feature.