feat: Infuse mode — external-player subtitles for Apple TV#987
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (10)
🚧 Files skipped from review as they are similar to previous changes (9)
WalkthroughThis pull request introduces Infuse mode, an external player integration that rewrites qualifying playable streams into ChangesInfuse Mode—External Player Subtitle Injection
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
packages/docs/content/docs/guides/infuse.mdx (1)
38-38: ⚡ Quick winConsider clarifying how to access Advanced mode.
The line mentions "(Advanced mode)" but doesn't explain how users should enable or access it. Users unfamiliar with the interface might not know where to find this toggle.
📝 Suggested clarification
-In the configure UI: **Miscellaneous → Playback → Infuse (External Player)** (Advanced mode). +In the configure UI: **Miscellaneous → Playback → Infuse (External Player)** (enable Advanced mode first to see this section).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/docs/content/docs/guides/infuse.mdx` at line 38, Update the sentence "In the configure UI: **Miscellaneous → Playback → Infuse (External Player)** (Advanced mode)" to explicitly tell users how to enable or access Advanced mode — e.g., add a short parenthetical or following clause such as "— enable Advanced mode via the top-right gear/menu or by toggling 'Advanced' in the UI header" or the exact steps/button name shown in the app; reference the same UI path (Miscellaneous → Playback → Infuse (External Player)) so the location remains clear.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@packages/frontend/src/components/menu/miscellaneous/_components/playback-behavior.tsx`:
- Around line 227-235: The onValueChange handler for updating infuse.topN
(inside setUserData) only clamps the lower bound; update it to clamp both bounds
so topN = Math.max(0, Math.min(50, Number(value ?? 5))) (or equivalent) before
storing in userData.infuse.topN to enforce the schema's max 50 in the UI; locate
the onValueChange block that currently updates setUserData and replace the
sanitisation with a two-sided clamp referencing infuse.topN and setUserData.
In `@packages/server/src/app.ts`:
- Around line 294-304: The fetch to the upstream subtitle URL (the await
fetch(upstream, { redirect: 'follow' }) call that produces upstreamRes and then
Buffer.from(await upstreamRes.arrayBuffer())) needs a request timeout and a
maximum allowed response size: wrap the fetch with an AbortController and cancel
the request after a configurable timeout, and before buffering validate the size
using upstreamRes.headers.get('content-length') (reject if > MAX_BYTES) and, if
content-length is absent, read the body as a stream and accumulate bytes up to
MAX_BYTES, aborting and throwing if the limit is exceeded; update the logic
around upstreamRes, arrayBuffer/Buffer creation, and the handler that logs and
returns the subtitle to use these checks and ensure the fetch is aborted on
timeout or size breach.
---
Nitpick comments:
In `@packages/docs/content/docs/guides/infuse.mdx`:
- Line 38: Update the sentence "In the configure UI: **Miscellaneous → Playback
→ Infuse (External Player)** (Advanced mode)" to explicitly tell users how to
enable or access Advanced mode — e.g., add a short parenthetical or following
clause such as "— enable Advanced mode via the top-right gear/menu or by
toggling 'Advanced' in the UI header" or the exact steps/button name shown in
the app; reference the same UI path (Miscellaneous → Playback → Infuse (External
Player)) so the location remains clear.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: fa0a7779-60d2-4aa1-a8a8-a59fda7d9edd
📒 Files selected for processing (10)
packages/core/src/db/schemas.tspackages/core/src/main/infuse.test.tspackages/core/src/main/infuse.tspackages/core/src/main/resources.tspackages/core/src/utils/fieldMeta.tspackages/core/tsconfig.jsonpackages/docs/content/docs/guides/infuse.mdxpackages/docs/content/docs/guides/meta.jsonpackages/frontend/src/components/menu/miscellaneous/_components/playback-behavior.tsxpackages/server/src/app.ts
Adds an opt-in, per-user "Infuse mode". When enabled, playable streams are
rewritten into direct `infuse://x-callback-url/play?url=…&sub=…&filename=…`
launch links with a subtitle resolved and baked in, so playback opens in Infuse
(Apple TV) with subtitles already loaded — Infuse never requests subtitles the
way Stremio's built-in player does.
- Per-user config (UserData.infuse { enabled, topN, candidates }); off by
default → no behaviour change unless a user enables it.
- Subtitle language reuses the user's Preferred Subtitles (defaults to English);
multiple languages are tried in priority order. Provider priority follows the
user's subtitle-addon order. No new hardcoded provider/language.
- A small `.srt` subtitle proxy serves the chosen upstream with the right
extension/content-type and a language-labelled filename so Infuse recognises
and labels the track; N candidates per stream give silent fallback.
- Pure helpers in packages/core/src/main/infuse.ts with unit tests; SPA control
under Miscellaneous → Playback; docs guide added.
Notes: Stremio app only (other clients build the Infuse launch themselves);
Infuse supports one subtitle per video; torrent/p2p streams are skipped.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Thanks for the review! Addressed all three points in
Also rebased onto the latest |
What & why
When playing via Infuse on Apple TV, Infuse plays embedded (mostly English) subtitle tracks but never requests subtitles the way Stremio's built-in player does — so non-embedded languages mean manual downloads every time. This adds an opt-in way to resolve a subtitle up front and bake it into the Infuse launch link.
How it works
UserData.infuse { enabled, topN, candidates }), off by default → no behaviour change unless enabled.infuse://x-callback-url/play?url=…&sub=…&filename=…..srtsubtitle proxy serves the chosen upstream with the right extension/content-type + language-labelled filename so Infuse recognises/labels the track; N candidates give silent fallback.packages/core/src/main/infuse.tswith unit tests; SPA control under Miscellaneous → Playback; docs guide added.Scope / safety
Default off; movie/series only; skipped during precaching; keeps
stream.urlso preload still works. Stremio app only (Fusion/Omni build the Infuse launch themselves — documented). One subtitle per video (Infuse scheme limit).Testing
Unit tests + full build (tsc + rsbuild) green; validated end-to-end on Apple TV.
Happy to adjust the config approach (per-user vs env/instance), commit layout, or test placement to match project conventions.
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Behaviour
Documentation
Infrastructure