Trey t ba24c767a0 Improve stream quality: stop capping resolution, allow AVPlayer to ramp
SingleStream: pass preserveServerResolutionWhenBest=false so "best"
always reaches the server for a full multi-variant manifest. Increase
buffer to 8s and enable automaticallyWaitsToMinimizeStalling so AVPlayer
can measure bandwidth and select higher variants. Add quality monitor
that nudges AVPlayer if observed bandwidth far exceeds indicated bitrate.

MultiStream: remove broken URL-param resolution detection that falsely
skipped upgrades, log actual indicatedBitrate instead. Extend upgrade
check windows from [2,4,7]s to [2,4,7,15,30]s for slow-to-stabilize
streams.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:38:38 -05:00
2026-03-26 15:37:31 -05:00

mlbTVOS

Personal MLB streaming app for Apple TV and iPhone/iPad, built with SwiftUI. Streams live and archived MLB games, plus a few non-MLB channels (MLB Network, an authenticated private feed).

Targets

  • mlbTVOS — tvOS application (primary)
  • mlbIOS — iOS/iPadOS application (shares most sources with the tvOS target)
  • mlbTVOSTests — Swift Testing unit tests

The Xcode project is generated from project.yml via XcodeGen. After editing project.yml or adding/removing source files, run:

xcodegen generate

Building

Requires Xcode 26.3+ and tvOS/iOS 18.0 SDKs.

# tvOS
xcodebuild build -project mlbTVOS.xcodeproj -scheme mlbTVOS \
  -destination 'platform=tvOS Simulator,name=Apple TV 4K (3rd generation)'

# Tests
xcodebuild test -project mlbTVOS.xcodeproj -scheme mlbTVOSTests \
  -destination 'platform=tvOS Simulator,name=Apple TV 4K (3rd generation)'

Features

Dashboard

Today's live/scheduled/final games, standings ticker, and special channel entry points. Tapping a game opens the Game Center with at-bat timeline, pitch sequence, spray chart, and strike zone overlays.

Multi-stream view

Up to four simultaneous streams in an adaptive grid. Only one stream holds audio focus at a time; tap any tile to transfer focus. Streams can be single broadcasts, team-filtered feeds, or special channels.

Single-stream player

Full-screen AVPlayer with HLS adaptive streaming, custom HTTP headers, and automatic retry on failure.

Special playback channels

  • MLB Network — 24/7 channel via the public MLB stream
  • Werkout NSFW — authenticated private feed served by ofapp on the home server; uses a JWT cookie and rotates clips through a per-model random shuffle

Video shuffle (per-model random)

VideoShuffle groups clips by source folder (e.g. which model/creator the video came from) and picks randomly one bucket at a time, excluding the previously-played bucket. This guarantees no back-to-back same source and produces a roughly uniform distribution across sources even when one source dominates the raw data by a large factor. See mlbTVOS/Services/VideoShuffle.swift and mlbTVOSTests/VideoShuffleTests.swift for the pure functions and their test coverage.

Architecture

  • mlbTVOS/mlbTVOSApp.swift — app entry point, creates a single GamesViewModel injected into the environment
  • mlbTVOS/ViewModels/GamesViewModel.swift — observable state store for games, standings, active streams, audio focus, and video shuffle bags; fetches from MLB Stats API and the auxiliary stream service
  • mlbTVOS/ViewModels/GameCenterViewModel.swift — per-game live data (at-bats, pitches, box score) used by the Game Center screen
  • mlbTVOS/Services/ — API clients (MLBStatsAPI, MLBServerAPI) and pure helpers (VideoShuffle)
  • mlbTVOS/Views/ — SwiftUI screens and component library (Components/AtBatTimelineView, PitchSequenceView, SprayChartView, StrikeZoneView, etc.)

All new Swift code uses Swift 6 strict concurrency (SWIFT_STRICT_CONCURRENCY: complete).

Configuration

No secret management is set up. The authenticated feed cookie is hardcoded in mlbTVOS/Views/DashboardView.swift (SpecialPlaybackChannelConfig.werkoutNSFWCookie) and must be refreshed manually when the JWT expires — generate a new one from the ofapp server's jwt_secret using the same userId and a longer exp.

Description
No description provided
Readme 473 KiB
Languages
Swift 100%