closed-captioner

ClosedCaptioner — project steering

Concise map of what the app is, how it is built, what is broken, and what is next.
For task-specific runbooks, see AGENTS.md and docs/agent/.


What it is

Native iOS 16.4+ SwiftUI app for live speech-to-text captions in portrait. Mic → on-screen text → optional edit, history, nearby share. Monetized with AdMob (banner + interstitial) and a Remove Ads non-consumable IAP.

Item Value
Scheme / target ClosedCaptioner
Bundle ID RaveSociety.ClosedCaptioner
Team RaveSociety (66R936J3XS)
Marketing version 1.2.1 (MARKETING_VERSION in Xcode)
Build number Xcode Cloud CI_BUILD_NUMBER at archive time
Repo kbibireddy/closed-captioner · branch main
ASC app 6754772689

Features (current)

Core captioning

Appearance

Settings (gear, full-screen overlay)

| Tab | Purpose | |—–|———| | Preferences | Display name, emoji detection (experimental), Huddle relay, Day/Night, theme, font | | KPIs | App vs phone CPU/memory/threads; 15 min @ 3s for live series, 1 h @ 30s for slow counters; Message Log can be cleared | | Activity | Captions history (source chips) + Huddle log (plain log lines); Day/Night-style switcher | | Purchases | Remove Ads IAP + Restore |

Huddle (nearby P2P) (Multipeer cc-p2p)

Monetization

Built but not in UI


Architecture

MVVM with small controllers and singleton managers.

ContentView
├── SpeechService          ← recognition, emojis
├── MicController          ← 15s timer, bridges SpeechService
├── AppStateViewModel      ← theme, day/night, overlays, display name, relay flag
├── HistoryManager         ← UserDefaults persistence
├── P2PInboxService        ← Huddle (Multipeer) + log + KPI counters
├── PremiumManager         ← StoreKit 2, entitlements
└── ControlsView           ← chrome, banners, P2P HUD, mic/keyboard/eraser

SettingsView → Preferences | KPIs | Activity | Purchases
Layer Key files
Models ColorMode, Theme, CaptionText
ViewModels AppStateViewModel
Views ContentView, ControlsView, CaptionTextDisplay, SettingsView, …
Services SpeechService, AudioService, P2PInboxService, ShakeDetectionService, PickupLineService, AppPerformanceMonitor
Controllers MicController
Managers HistoryManager, ExportManager
Ads AdsBootstrap, BannerAdView, InterstitialCoordinator, AdConfig
IAP PremiumManager, IAPConfig, ClosedCaptioner.storekit

UI layering (z-order)

  1. Caption canvas (center)
  2. ControlsView — top bar, banners, P2P log, bottom bar
  3. Overlays — keyboard, settings (zIndex 10)

Persistence (UserDefaults)

Theme, color mode, display name, relay flag, caption history, P2P KPI counters (persist; no in-app reset).


Main screen controls

Location Action
Top left Settings
Top right Huddle + status (Tap to join off; on: ↓/↑ B/s from 30s window)
Bottom left Keyboard
Bottom center Mic (long-press start/stop)
Bottom right Eraser
Center caption Flick up (±60°) anywhere on canvas to send (Huddle on); Sent! / Try again

Day/Night, theme, and font are not on the main screen — Settings → Preferences only.


Release & ops

Topic Doc
Device install docs/agent/device-deploy.md
Xcode Cloud → App Store docs/agent/xcode-cloud.md
IAP / Remove Ads Retry docs/agent/iap.md
AdMob app-ads.txt docs/agent/app-ads-txt.md — must live at domain root https://kbibireddy.github.io/app-ads.txt
P2P testing docs/agent/p2p-test.md
Privacy copy PrivacyPolicy.md

CI: Push to main → Xcode Cloud archives Release → uploads to App Store Connect. Bump MARKETING_VERSION before a new store version; do not reuse a version already Ready for Distribution.

Local IAP testing: Xcode Run with scheme StoreKit config ClosedCaptioner.storekit. TestFlight / xcodebuild installs use the live store catalog.


Known issues & gaps

Issue Status / fix
Remove Ads shows Retry / purchase unavailable on TestFlight or device deploy StoreKit returns empty catalog until ASC Paid Apps agreement is Active and IAP ClosedCaptioner is Ready to Submit with full metadata. See docs/agent/iap.md. Local .storekit only applies to Xcode Run.
Export ExportManager implemented; no user-facing export action.
Speech locale Hard-coded en-US only.
Huddle / P2P Background keep-alive exists (UIBackgroundTask + audio/Bluetooth modes) with auto-off timer; iOS may still suspend. Relay is best-effort TTL hop.
ASC assets Prefer Desktop Closed Captioner Assets/output/processed_screenshots/1242x2688 for store screenshots.

No automated test target in the Xcode project.


What’s next (suggested)

Store / monetization

Product

P2P

Housekeeping


Agent quick rules

  1. Read AGENTS.md first; open only the agent doc for your task.
  2. Match existing MVVM patterns; keep banner layout in a single ControlsView VStack.
  3. Do not write incoming P2P text into SpeechService or center caption.
  4. Do not commit unless the user asks.
  5. Escalate to human: Developer Mode, PLA/Paid Apps contracts, phone unlock, ASC banking.