{"id":49299847,"url":"https://github.com/crawdaddydoo92/manualepisodelinking","last_synced_at":"2026-04-26T06:05:37.879Z","repository":{"id":352333600,"uuid":"1214755339","full_name":"crawdaddydoo92/ManualEpisodeLinking","owner":"crawdaddydoo92","description":"Jellyfin plugin for seamless cross-series episode playback using manual episode linking.","archived":false,"fork":false,"pushed_at":"2026-04-19T03:45:30.000Z","size":51,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-19T04:26:35.193Z","etag":null,"topics":["crossover","jellyfin","media-server","plugin","tv-shows"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/crawdaddydoo92.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-19T02:14:58.000Z","updated_at":"2026-04-19T03:55:49.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/crawdaddydoo92/ManualEpisodeLinking","commit_stats":null,"previous_names":["crawdaddydoo92/manualepisodelinking"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/crawdaddydoo92/ManualEpisodeLinking","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crawdaddydoo92%2FManualEpisodeLinking","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crawdaddydoo92%2FManualEpisodeLinking/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crawdaddydoo92%2FManualEpisodeLinking/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crawdaddydoo92%2FManualEpisodeLinking/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/crawdaddydoo92","download_url":"https://codeload.github.com/crawdaddydoo92/ManualEpisodeLinking/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crawdaddydoo92%2FManualEpisodeLinking/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32287399,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T18:29:39.964Z","status":"online","status_checked_at":"2026-04-26T02:00:05.962Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["crossover","jellyfin","media-server","plugin","tv-shows"],"created_at":"2026-04-26T06:05:21.003Z","updated_at":"2026-04-26T06:05:37.874Z","avatar_url":"https://github.com/crawdaddydoo92.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Manual Episode Linking (Jellyfin Plugin)\r\n\r\n## Overview\r\n\r\nManual Episode Linking is a Jellyfin plugin that lets you control what plays next — even across different shows or movies.\r\n\r\nOriginally built for TV crossovers, it now also supports automatic movie sequel playback.\r\n\r\n---\r\n\r\n## ✨ What This Solves\r\n\r\nJellyfin normally:\r\n\r\n- Plays episodes only within the same series\r\n- Does not support crossovers between shows\r\n- Does not link separate movies together\r\n\r\nThis plugin lets you:\r\n\r\n- Seamlessly continue crossovers between different series\r\n- Automatically play the next movie in a franchise\r\n- Maintain the correct viewing order without renaming or reorganizing files\r\n\r\n---\r\n\r\n## 🆕 New in 1.1.1\r\n\r\n- Movie sequel chaining\r\n  - Automatically plays the next movie (e.g., trilogies)\r\n  - Smooth, seamless transitions\r\n\r\n- Improved playback stability\r\n  - Eliminates duplicate triggers\r\n  - More reliable transitions\r\n\r\n- Smarter execution\r\n  - Movies transition immediately\r\n  - TV waits for a safe playback reset\r\n\r\n---\r\n\r\n## 🆕 New in 1.1.0\r\n\r\n- Full chain support\r\n  - Link items across any number of steps (A → B → C → D → ...)\r\n\r\n- Last-hop protection\r\n  - Prevents unwanted playback when starting at the end of a chain\r\n  - Only completes links when part of a valid sequence\r\n\r\n- Works with all playback styles\r\n  - Natural playback (letting items finish)\r\n  - Skip / next controls\r\n\r\n---\r\n\r\n## ⚙️ How It Works\r\n\r\nThe plugin monitors playback and prepares the next item ahead of time.\r\n\r\n1. Near the end (~99%)\r\n   - Detects if a custom next item exists\r\n   - Queues it without interrupting playback\r\n\r\n2. At the correct moment\r\n   - Movies: transition immediately\r\n   - TV: wait for playback reset, then transition\r\n\r\n### Key Idea\r\n\r\nDetect early → transition at the right moment\r\n\r\n---\r\n\r\n## 📦 Installation\r\n\r\n### 1. Build the plugin\r\n\r\ndotnet build -c Release\r\n\r\n### 2. Copy files to Jellyfin\r\n\r\n/etc/jellyfin/plugins/ManualEpisodeLinking/\r\n\r\nRequired:\r\n\r\n- ManualEpisodeLinking.dll\r\n\r\nOptional:\r\n\r\n- JSON config files (e.g., csi.json, movies.json)\r\n\r\n### 3. Restart Jellyfin (first install only)\r\n\r\nAfter installation, config changes reload automatically.\r\n\r\n---\r\n\r\n## 🧩 Configuration\r\n\r\nThe plugin uses one or more JSON files to define links.\r\n\r\n### Location\r\n\r\n/etc/jellyfin/plugins/ManualEpisodeLinking/\r\n\r\n### Example\r\n\r\n{\r\n  \"Links\": {\r\n    \"ITEM_ID_A\": \"ITEM_ID_B\",\r\n    \"ITEM_ID_B\": \"ITEM_ID_C\"\r\n  }\r\n}\r\n\r\n### Notes\r\n\r\n- Keys = current item\r\n- Values = next item\r\n- IDs must be Jellyfin ItemIds\r\n- Use lowercase, no dashes\r\n- Chains can be any length\r\n\r\n---\r\n\r\n## ⚠️ Movie Configuration Requirement\r\n\r\nFor movie chaining to work correctly when starting playback manually, you must enable:\r\n\r\n\"AllowLastHopFromManualStart\": true\r\n\r\n### Why this matters\r\n\r\nBy default:\r\n\r\nAllowLastHopFromManualStart = false\r\n\r\nThis is ideal for TV crossovers, but for movies it can block the final transition.\r\n\r\n### Recommended movie config\r\n\r\n{\r\n  \"AllowLastHopFromManualStart\": true,\r\n  \"Links\": {\r\n    \"MOVIE_1_ID\": \"MOVIE_2_ID\",\r\n    \"MOVIE_2_ID\": \"MOVIE_3_ID\"\r\n  }\r\n}\r\n\r\n---\r\n\r\n## 🔄 Live Reload\r\n\r\n- Changes apply automatically\r\n- No restart required\r\n- Updates are detected within ~1 second\r\n\r\n---\r\n\r\n## 🔗 How Linking Works\r\n\r\nLinks are directional and defined step-by-step.\r\n\r\nExample:\r\n\r\nEpisode A → Episode B  \r\nEpisode B → Episode C\r\n\r\nIf no link exists, Jellyfin behaves normally.\r\n\r\n---\r\n\r\n## ▶️ Playback Behavior\r\n\r\n- If a link exists → plugin overrides playback\r\n- If no link exists → Jellyfin continues normally\r\n\r\n### TV Behavior\r\n\r\n- Requires entering the chain correctly\r\n- Final step is protected (no forced jump if started there)\r\n\r\n### Movie Behavior\r\n\r\n- Always allows the final step (when configured)\r\n- Designed for seamless franchise playback\r\n\r\n---\r\n\r\n## ⚠️ ItemID Stability (Important)\r\n\r\nLinks rely on Jellyfin ItemIds.\r\n\r\n- Library refreshes do NOT change IDs\r\n- Metadata edits do NOT change IDs\r\n\r\nHowever:\r\n\r\n- Replacing or modifying a file may generate a new ID\r\n\r\nIf this happens, update your JSON config.\r\n\r\n---\r\n\r\n## 🚧 Limitations\r\n\r\n- No UI (manual configuration required)\r\n- Uses polling (not event-based yet)\r\n- Limited multi-session support\r\n- No validation for circular links\r\n- Scrubbing near the end may trigger linking\r\n\r\n---\r\n\r\n## 🔮 Future Plans\r\n\r\n- Web UI for managing links\r\n- Event-based playback detection\r\n- Better multi-user support\r\n- Link validation tools\r\n\r\n---\r\n\r\n## 🧠 Why This Works\r\n\r\nJellyfin resets playback sessions between items.\r\n\r\nThis plugin works around that by:\r\n\r\n- Preparing the next item early\r\n- Waiting for a stable moment to switch\r\n- Avoiding interruptions and timing issues\r\n\r\n---\r\n\r\n## 📁 Project Structure\r\n\r\nManualEpisodeLinking/\r\n├── PlaybackMonitor.cs\r\n├── Plugin.cs\r\n├── csi.json\r\n├── movies.json\r\n├── ManualEpisodeLinking.csproj\r\n\r\n---\r\n\r\n## 📜 License / Status\r\n\r\nPrivate development project (for now)\r\n\r\n---\r\n\r\n## 💬 Summary\r\n\r\nManual Episode Linking gives you full control over playback order:\r\n\r\n- Cross-series episode continuity\r\n- Automatic movie sequel playback\r\n- Clean, uninterrupted viewing experience\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrawdaddydoo92%2Fmanualepisodelinking","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcrawdaddydoo92%2Fmanualepisodelinking","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrawdaddydoo92%2Fmanualepisodelinking/lists"}