Changelog¶
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[0.0.39] - 2026-04-24¶
Added¶
reeln initcommand — guided first-time setup with interactive sport selection, directory configuration, and config creationNon-interactive mode:
reeln init --sport hockey --source-dir ~/replays --output-dir ~/games
Fixed¶
Plugin install/uninstall now finds
uvin common paths (~/.local/bin,~/.cargo/bin,/opt/homebrew/bin) when shell PATH is minimal (fixes “No module named pip” in Tauri/GUI apps)
[0.0.38] - 2026-04-07¶
Added¶
reeln queuecommand group for staged render-then-publish workflow: list, show, edit, publish, publish-all, remove, targets--queue/-qflag onrender shortandrender apply— renders but queues for review instead of publishing immediatelyPer-target publish tracking — publish to YouTube, review, then selectively push to Instagram/TikTok without re-rendering
ON_QUEUEandON_PUBLISHlifecycle hooks for plugin integration with the queue workflowCentralized metadata generation (
core/metadata.py) — auto-generates title and description from game/event contextQueueItemstores config profile name —queue publishloads the same plugin settings used at queue timeQueue persistence via
render_queue.json(per-game directory) with advisory central index for cross-game listingQueueErrorexception class for queue operation errorsTeam logo overlay on goal shorts — resolves logo from
TeamProfile.logo_path, scales to 80% of box height, right-aligned with text clipping. Supports all four filter chain paths (simple pad/crop, smart pad, speed segments, speed segments + smart pad)reeln plugins authcommand — test authentication for plugins (--jsonfor machine output,--refreshto force reauthentication)reeln plugins uninstallcommand — uninstall a plugin and remove from config (--forceto skip confirmation,--dry-runto preview)Authenticatorcapability protocol — plugins implementauth_check()andauth_refresh()for credential verification and token renewalAuthCheckResult,AuthStatus,PluginAuthReportmodels (reeln/models/auth.py) for structured auth status reporting
[0.0.37] - 2026-04-03¶
Added¶
reeln game list— list games in output directory with status badges (finished/in progress)reeln game info— show detailed game information (teams, venue, progress, livestreams)reeln game delete— delete a game directory with confirmation prompt (--forceto skip)Colored CLI output:
--version,plugins list,plugins search,plugins info,plugins inputs,game list,game info,game deleteall use consistent styled output (bold names, green/red/yellow badges, dim labels)Shared
reeln.commands.stylemodule for consistent CLI formattingPlugin Input Contributions: plugins declare additional user inputs via
input_schemaclass attribute (PluginInputSchema,InputField)--plugin-input KEY=VALUE(-I) repeatable option ongame init,render short, andrender previewInteractive prompts for plugin-contributed inputs (questionary-based, preset-first pattern)
Conditional prompting:
thumbnailandtournamentonly prompted when a plugin declares themInputCollectorwith conflict resolution (same-type dedup, cross-type namespacing)get_input_schema()method support: plugins can conditionally declare inputs based on feature flags (e.g., only prompt for thumbnail whencreate_livestreamis enabled)Registry fallback: plugins without
input_schema/get_input_schema()get inputs fromui_contributions.input_fieldsin registry JSONreeln plugins inputsintrospection command (text + JSON output for reeln-dock)input_contributionsfield onRegistryEntrymodel, parsed fromui_contributions.input_fieldsGoogle plugin registry entry updated with
thumbnail_imageinput field forgame_init
Changed¶
init_game()acceptsplugin_inputskwarg, included inON_GAME_INIT/ON_GAME_READYhook dataPRE_RENDER/POST_RENDERhook data includesplugin_inputswhen presentactivate_plugins()now registers plugin input schemas with theInputCollectorsingletongame initchecks for unfinished games before interactive prompts (fail fast instead of prompting then failing)_resolve_game_dirnow sorts bycreated_atfromgame.jsoninstead of filesystem mtime (which is unreliable due to Spotlight/Time Machine)_resolve_game_dirprefers unfinished games over finished ones, soreeln game finishfinds the right game
[0.0.36] - 2026-04-02¶
Fixed¶
Read the Docs example page links now navigate correctly (renamed wrapper files to match example filenames)
[0.0.35] - 2026-04-02¶
Added¶
examples/directory with 10 step-by-step walkthrough pages covering install, OBS setup, game lifecycle, rendering, profiles, plugins, and smart zoomExamples integrated into Read the Docs via
docs/examples/sectionVideo demo talking points (gitignored, presenter-only)
Changed¶
README.md rewritten: prominent ffmpeg dependency callout, updated CLI reference (removed stale “coming soon” section), added examples link
Docs index updated with ffmpeg admonition, current feature list, and examples toctree entry
[0.0.34] - 2026-04-02¶
Added¶
reeln hooks runandreeln hooks listCLI commands for non-interactive hook execution (JSON-in/JSON-out, designed for reeln-dock integration)reeln-nativev0.2.0 as a required dependency (Rust-powered acceleration)native-devandpluginsMakefile targets for local development
Changed¶
Goal overlay layout: dynamic box height when assists are present, adjusted assist Y-coordinates for better spacing
probe_duration()now accepts single-arg form with auto-discovery (probe_duration(path))Overlay template documentation now covers ASS templates only (JSON templates deferred to native migration)
Removed¶
Dead PNG overlay pipeline (
ResolvedOverlay,resolve_overlay_for_profile,composite_video_overlay) — unreachable code from incomplete JSON template integrationgoal_overlay.jsontemplate (nothing loaded it)Shell completion Makefile targets (replaced by symlink install)
[0.0.33] - 2026-03-23¶
Added¶
Branding overlay on rendered shorts: shows “reeln v{version} by https://streamn.dad” with a black-bordered white text at the top of the video for the first ~5 seconds with a smooth fade-out — enabled by default, configurable via
brandingconfig section, disable with--no-brandingCLI flagBrandingConfigmodel (enabled,template,duration) for per-user branding customizationBundled
branding.assASS template with\fad(300,800)animation and black outline for visibility over any background--no-brandingflag onrender shortandrender previewcommandsBranding renders only on the first iteration in multi-iteration mode
Cross-fade transitions between iterations: uses ffmpeg
xfade+acrossfadefilters for smooth 0.5s fade transitions instead of hard cuts, with automatic fallback to concat demuxer if xfade failsSmart zoom support in the iteration pipeline:
--smart --iteratenow extracts frames once upfront and passes the zoom path through to each iteration’splan_short()callspeed_segmentsin render profiles for variable speed within a single clip — e.g., normal speed → slow motion → normal speed, using the proven split/trim/concat ffmpeg pattern--player-numbers(-n) flag onrender short,render preview, andrender applyfor roster-based player lookup: accepts comma-separated jersey numbers (e.g.,--player-numbers 48,24,2), looks up names from the team roster CSV, and populates goal scorer and assist overlays automatically--event-typeflag on render commands for scoring team resolution:HOME_GOAL/AWAY_GOALdetermines which team’s roster to look upRosterEntrydata model andload_roster()/lookup_players()/resolve_scoring_team()core functions for roster managementGameInfonow persistslevel,home_slug, andaway_slugwhengame init --levelis used, enabling roster lookup during renderingbuild_overlay_context()accepts optionalscoring_teamparameter to override the default (home team)Smart target zoom (
--crop smart): extracts frames from clips, emitsON_FRAMES_EXTRACTEDhook for vision plugins (e.g. reeln-plugin-openai) to detect action targets, then builds dynamic ffmpeg crop expressions that smoothly pan across detected targetsZoomPoint,ZoomPath, andExtractedFramesdata models for smart zoom contractsON_FRAMES_EXTRACTEDlifecycle hook for plugins to analyze extracted video framesextract_frames()method on the Renderer protocol and FFmpegRenderer for frame extractionbuild_piecewise_lerp()andbuild_smart_crop_filter()for dynamic ffmpeg crop expressions--zoom-framesoption onrender shortandrender preview(default 5, range 1-20)Zoom debug output:
debug/zoom/zoom_path.jsonand frame symlinks when--debugis used with smart cropSmart pad mode (
--crop smart_pad): follows action vertically like smart zoom but keeps black bars instead of filling the entire frame — falls back to static pad when no vision plugin provides databuild_smart_pad_filter()for dynamic vertical pad positioning based on zoom path center_yDebug crosshair annotations: extracted frames in
debug/zoom/now include annotated copies with green crop box and red crosshair overlays showing detected center points--scaleoption onrender shortandrender preview(0.5-3.0, default 1.0): zooms in by scaling up the intermediate frame before crop/pad — works with all crop modes including smart tracking--smartflag onrender shortandrender preview: enables smart tracking via vision plugin as an orthogonal option, composable with--crop pad|cropand--scalebuild_overflow_crop_filter()for pad + scale > 1.0: crops overflow after scale-up before paddingAutomatic fallback from smart crop to center crop (or smart_pad to static pad) when no vision plugin provides zoom data
--no-enforce-hooksglobal CLI flag to temporarily disable registry-based hook enforcement for pluginsgame finishnow relocates segment and highlights outputs from the shared output directory intogame_dir/outputs/, preventing file collisions across multiple games per daygame initnow blocks with a clear error if an unfinished game exists — runreeln game finishfirstGameStatetrackssegment_outputsandhighlights_outputfor file relocationfind_unfinished_games()helper scans for active game directoriesrelocate_outputs()helper moves output files into the game directoryreeln doctornow collects and runs health checks from plugins that implementdoctor_checks()doctorcapability added to plugin duck-type detection--tournamentCLI flag ongame initfor optional tournament name/context — flows through to plugins via hook context and overlay templatestournamentandlevelfields now included in template context (build_base_context()), available as{{tournament}}and{{level}}in ASS subtitle templates
Changed¶
Scale, framing (crop/pad), and smart tracking are now orthogonal axes — any combination works without dedicated enum values
Short/preview renders now output to a
shorts/subdirectory by default (e.g.,period-2/shorts/clip_short.mp4) to prevent segment merges from picking up rendered files
Deprecated¶
--crop smart— use--crop crop --smartinstead (still works, shows deprecation warning)--crop smart_pad— use--crop pad --smartinstead (still works, shows deprecation warning)
Fixed¶
team_levelin overlay context now uses the actual team level (e.g., “2016”, “bantam”) instead of the sport name — previously showed “hockey” instead of the levelSegment merge and highlights merge output extension now matches input files instead of being hardcoded to
.mkvHighlights merge now discovers segment files with any video extension (
.mp4,.mkv,.mov, etc.), not just.mkv
[0.0.32] - 2026-03-15¶
Fixed¶
--profilenow resolves relative to the active config directory (parent ofREELN_CONFIG) instead of the platform default, so profiles stored alongside a custom config file are found correctly--profileand--pathCLI arguments now take strict priority overREELN_CONFIGandREELN_PROFILEenvironment variables
[0.0.31] - 2026-03-13¶
Added¶
ON_POST_GAME_FINISHhook — fires afterON_GAME_FINISHwith shared context, enabling cross-plugin data consumption at game finish (mirrorsON_GAME_INIT→ON_GAME_READYpattern)--log-levelCLI option andREELN_LOG_LEVELenv var to control log verbosity (default: WARNING)enforce_hooksplugin config option — restricts plugins to hooks declared in the registry; setfalsefor local plugin developmentRegistry capability enforcement — plugins can only register hooks declared in their
registry/plugins.jsonentry
Fixed¶
Explicit
--profileor--pathto a nonexistent config file now fails immediately instead of silently using defaults
Changed¶
Default log level changed from INFO to WARNING (reduces noise during normal operation)
[0.0.30] - 2026-03-11¶
Added¶
ON_GAME_READYhook — fires afterON_GAME_INITwith shared context, enabling cross-plugin data consumption (e.g. OpenAI generates thumbnail during init, Google updates livestream during ready)config shownow displays the full resolved configuration including all default values and plugin schema defaultsPlugin registry entries for
meta(Facebook Live/Instagram/Threads) andopenai(LLM-powered metadata/thumbnails/translation)
Fixed¶
PyPI Documentation link now points to correct URL (
reeln-cli.readthedocs.io)
Changed¶
Plugins that are not installed log at debug level instead of warning with traceback
[0.0.29] - 2026-03-06¶
Added¶
--version/-Vflag onreeln plugins installandreeln plugins updateto pin a specific version (git tag or PyPI release)Logo on Read the Docs site (sidebar and favicon)
[0.0.28] - 2026-03-04¶
Added¶
--description/-dflag ongame initfor broadcast description--thumbnailflag ongame initfor thumbnail image pathGameInfo.descriptionandGameInfo.thumbnailfieldsInteractive prompts for description and thumbnail (both optional)
[0.0.27] - 2026-03-04¶
Fixed¶
PyPI logo: restore absolute URL for README image (lost during merge)
[0.0.26] - 2026-03-04¶
Added¶
HookContext.shareddict for plugins to pass data back (e.g. livestream URLs)GameState.livestreamsfield — persists livestream URLs written by hook pluginsresolve_config_path()— extracted config path resolution for reuse
Fixed¶
Plugin install now uses
git+{homepage}for GitHub/GitLab plugins instead of PyPI lookupPost-install verification catches silent
uv pip installno-opssave_config()now respectsREELN_CONFIG/REELN_PROFILEenv vars (previously always wrote to default path)detect_installer()passes--python sys.executableto uv so plugins install into the correct environmentHardcoded version strings removed from tests (use
__version__dynamically)
[0.0.25] - 2026-03-04¶
Fixed¶
Logo image on PyPI (use absolute URL for
assets/logo.jpg)Add project URLs to PyPI sidebar (Homepage, Docs, Repo, Changelog, Issues)
[0.0.24] - 2026-03-04¶
Fixed¶
Registry URL casing —
raw.githubusercontent.comis case-sensitive (StreamnDadnotstreamn-dad)mypy errors in
prompts.py(renamed shadowed variables)CI workflows use
uv syncinstead ofuv pip install --system(PEP 668)Plugin registry: correct homepage URL and metadata for
streamn-scoreboard
[0.0.23] - 2026-03-03¶
First feature-complete release of reeln — platform-agnostic CLI toolkit for livestreamers.
Added¶
CLI Commands¶
reeln --version— show version, ffmpeg info, and installed plugin versionsreeln doctor— comprehensive health check: ffmpeg, codecs, hardware acceleration, config, permissionsreeln config show— display current configuration as JSONreeln config doctor— validate config, warn on issuesreeln game init— initialize game workspace with sport-specific segment subdirectoriesreeln game segment <N>— merge replays in a segment directory into a highlight videoreeln game highlights— merge all segment highlights into a full-game highlight reelreeln game finish— mark a game as finished with summaryreeln game prune— remove generated artifacts from a finished game directoryreeln game event list— list events with filters (--segment,--type,--untagged)reeln game event tag— tag an event with type, player, and metadatareeln game event tag-all— bulk-tag all events in a segmentreeln game compile— compile raw event clips into a single video by criteriareeln render short— render a 9:16 short from a clipreeln render preview— fast low-res preview renderreeln render apply— apply a named render profile to a clip (full-frame, no crop/scale)reeln render reel— assemble rendered shorts into a concatenated reelreeln media prune— scan and prune all finished game directoriesreeln plugins list— list installed plugins with version inforeeln plugins search— search the plugin registryreeln plugins info <name>— show detailed plugin informationreeln plugins install <name>— install a plugin from the registry with auto-enablereeln plugins update [name]— update a plugin or all installed pluginsreeln plugins enable <name>/reeln plugins disable <name>— enable/disable plugins
Core Features¶
Package skeleton:
pyproject.toml, Makefile,.coveragerc,pytest.ini,python -m reelnsupportStructured logging module with JSON and human formatters
Error hierarchy:
ReelnErrorbase with typed subclassesFFmpeg discovery with cross-platform support (PATH, brew, apt, choco), version checking (5.0+ minimum)
Media probe helpers: duration, fps, resolution via ffprobe
Deterministic ffmpeg command builders (concat, render) with golden test assertions
FFmpegRendererimplementation withrender()andpreview()methodsConfig system: JSON loading, schema validation,
config_version, XDG-compliant paths, env var overrides (REELN_<SECTION>_<KEY>), deep merge, atomic writes, named profilesSegment model: generic time division abstraction with sport alias registry (hockey, basketball, soccer, football, baseball, lacrosse, generic) and custom sport registration
Game lifecycle:
GameInfo,GameState,GameEventmodels with JSON serialization, double-header auto-detection,game.jsonstate trackingGameEventmodel for first-class event tracking with UUID-based IDs, prefix matching, extensible metadata, and idempotent creationRender state tracking in
game.jsonviaRenderEntrywith event auto-linkingShortConfig model with crop modes (pad, crop), output formats (vertical, square), anchor positions
Filter graph builders: scale, pad, crop, speed, LUT, subtitle — composable and golden-tested
Render profiles: named configuration sets for reusable rendering parameter overrides (speed, LUT, subtitle template, encoding)
Multi-iteration rendering: run a clip through N render profiles sequentially and concatenate results
Template engine:
{{key}}placeholder substitution for.asssubtitle filesTemplateContext,TemplateProviderprotocol,build_base_context()for game/event contextASS subtitle helpers:
rgb_to_ass(),format_ass_time()Bundled
goal_overlayASS subtitle template with dynamic font sizing and team-colored backgroundbuiltin:prefix forsubtitle_templatein render profiles (e.g."builtin:goal_overlay")build_overlay_context()for computing overlay-specific template variables from event metadata--playerand--assistsCLI flags onrender short,render preview, andrender apply— populate overlay template variables without game event tagging; override event data when both are presentDefault
player-overlayrender profile andgoaliteration mapping in bundled configTeamProfilemodel with metadata (logo, roster, colors, jersey colors, period length)Team profile management: load, save, list, delete with atomic writes
Interactive team selection and game time prompting in
game init--game-time,--level,--period-length,--venueoptions ongame init--debugflag on game and render commands — writes pipeline debug artifacts with ffmpeg commands, filter chains, and metadataHTML debug index (
debug/index.html) with summary table and per-operation sections--dry-runsupport across all destructive and render commandsPruneResultmodel,format_bytes(),find_game_dirs()helpersCompilationResultmodel for compilation output trackingquestionaryas optional dependency (pip install reeln[interactive])
Plugin System¶
Plugin system foundation: lifecycle hooks, capability protocols, hook registry
Hookenum with 11 lifecycle hooks:PRE_RENDER,POST_RENDER,ON_CLIP_AVAILABLE,ON_EVENT_CREATED,ON_EVENT_TAGGED,ON_GAME_INIT,ON_GAME_FINISH,ON_HIGHLIGHTS_MERGED,ON_ERROR,ON_SEGMENT_START,ON_SEGMENT_COMPLETEHookRegistrywith safe emission — handler exceptions are caught and loggedCapability protocols:
Uploader,MetadataEnricher,Notifier,GeneratorPlugin orchestrator: sequential pipeline (Generator -> MetadataEnricher -> Uploader -> Notifier)
Plugin loader:
discover_plugins(),load_plugin(),load_enabled_plugins(),activate_plugins()Plugin config schema declaration with
ConfigFieldandPluginConfigSchemaRemote plugin registry with cache, search, install, update, and auto-enable
authorandlicensefields on plugin registry entriesThrottledReaderfor upload throughput limiting,upload_lock()for serializationfilelock>=3.0dependency
CI/CD & Docs¶
GitHub Actions CI workflow (Python 3.11/3.12/3.13 matrix, lint, type check, tests, docs build)
GitHub Actions release workflow (tag-based PyPI publish via trusted publisher)
CI and docs badges in README
Documentation infrastructure: Sphinx + MyST, Furo theme, Read the Docs config
Full docs site: install guide, quickstart tutorial, CLI reference, configuration guide, sports guide
Fixed¶
render short --render-profilenow correctly resolvessubtitle_templatefrom the profile — previously the template was silently dropped in the single-profile path
Changed¶
--rinkCLI flag renamed to--venuefor sport-agnostic terminologySegment merge and highlights merge output written to
paths.output_dirfor discoverabilityperiod_lengthmoved fromTeamProfiletoGameInfoFull test suite with 100% line + branch coverage