RepoPilotOpen in app →

sahin/mobileplayer-ios

:iphone: :movie_camera: A powerful and completely customizable media player for iOS

Mixed

Stale — last commit 4y ago

worst of 4 axes
Use as dependencyConcerns

non-standard license (Other); last commit was 4y ago…

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • 13 active contributors
  • Other licensed
  • CI configured
Show 4 more →
  • Stale — last commit 4y ago
  • Single-maintainer risk — top contributor 81% of recent commits
  • Non-standard license (Other) — review terms
  • No test directory detected
What would change the summary?
  • Use as dependency ConcernsMixed if: clarify license terms

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Forkable" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/sahin/mobileplayer-ios?axis=fork)](https://repopilot.app/r/sahin/mobileplayer-ios)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/sahin/mobileplayer-ios on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: sahin/mobileplayer-ios

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/sahin/mobileplayer-ios shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

WAIT — Stale — last commit 4y ago

  • 13 active contributors
  • Other licensed
  • CI configured
  • ⚠ Stale — last commit 4y ago
  • ⚠ Single-maintainer risk — top contributor 81% of recent commits
  • ⚠ Non-standard license (Other) — review terms
  • ⚠ No test directory detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live sahin/mobileplayer-ios repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/sahin/mobileplayer-ios.

What it runs against: a local clone of sahin/mobileplayer-ios — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in sahin/mobileplayer-ios | Confirms the artifact applies here, not a fork | | 2 | License is still Other | Catches relicense before you depend on it | | 3 | Default branch develop exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 1418 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>sahin/mobileplayer-ios</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of sahin/mobileplayer-ios. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/sahin/mobileplayer-ios.git
#   cd mobileplayer-ios
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of sahin/mobileplayer-ios and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "sahin/mobileplayer-ios(\\.git)?\\b" \\
  && ok "origin remote is sahin/mobileplayer-ios" \\
  || miss "origin remote is not sahin/mobileplayer-ios (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(Other)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"Other\"" package.json 2>/dev/null) \\
  && ok "license is Other" \\
  || miss "license drift — was Other at generation time"

# 3. Default branch
git rev-parse --verify develop >/dev/null 2>&1 \\
  && ok "default branch develop exists" \\
  || miss "default branch develop no longer exists"

# 4. Critical files exist
test -f "MobilePlayer/MobilePlayerViewController.swift" \\
  && ok "MobilePlayer/MobilePlayerViewController.swift" \\
  || miss "missing critical file: MobilePlayer/MobilePlayerViewController.swift"
test -f "MobilePlayer/MobilePlayerOverlayViewController.swift" \\
  && ok "MobilePlayer/MobilePlayerOverlayViewController.swift" \\
  || miss "missing critical file: MobilePlayer/MobilePlayerOverlayViewController.swift"
test -f "MobilePlayer/Config/MobilePlayerConfig.swift" \\
  && ok "MobilePlayer/Config/MobilePlayerConfig.swift" \\
  || miss "missing critical file: MobilePlayer/Config/MobilePlayerConfig.swift"
test -f "MobilePlayer/MobilePlayerNotification.swift" \\
  && ok "MobilePlayer/MobilePlayerNotification.swift" \\
  || miss "missing critical file: MobilePlayer/MobilePlayerNotification.swift"
test -f "MobilePlayer/Extensions/UIColor+Hex.swift" \\
  && ok "MobilePlayer/Extensions/UIColor+Hex.swift" \\
  || miss "missing critical file: MobilePlayer/Extensions/UIColor+Hex.swift"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 1418 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~1388d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/sahin/mobileplayer-ios"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

MobilePlayer is a fully customizable iOS media player framework written in Swift that wraps AVPlayer with a skinnable UI overlay system. It allows developers to embed branded video playback with flexible controls, watermarks, and a powerful overlay system for pre-roll, pause overlays, post-roll, and timed content injection—all without external dependencies. Single-framework architecture: Swift source lives in the root package (102k Swift), wrapped with Objective-C bridge code (1k), build via Ruby scripts (3.2k). Documentation generated via Jazzy lives in /Documentation. Configuration is entirely code-first via MobilePlayerConfig, MobilePlayerViewController, and *Config classes (BarConfig, ButtonConfig, SliderConfig, etc.), with optional remote JSON loading capability mentioned in README.

👥Who it's for

iOS app developers (Swift/Objective-C) who need to embed video playback with custom branding, A/B testable UI configurations, and rich engagement features like overlays and pre/post-roll content without building a media player from scratch.

🌱Maturity & risk

Actively maintained and production-ready. The project has comprehensive Jazzy-generated documentation, CI via Travis CI, supports both CocoaPods and Carthage, and is fully Swift-based (102k lines). However, visible incomplete features in README future plans (NSNotifications, volume controls, AirPlay, VAST) suggest ongoing development rather than feature-complete maturity.

Low external dependency risk (zero dependencies as advertised), but single-maintainer repository structure and no visible open issue count in provided data creates sustainability concern. The .travis.yml presence indicates some CI, but no test directory visible in top-level structure raises test coverage uncertainty. Last commit recency unknown from provided data.

Active areas of work

No PR or commit history visible in provided data. Future plans in README indicate active roadmap: NSNotifications, volume UI, AirPlay, plugin system, analytics integrations, and VAST support. The presence of generated documentation suggests recent doc builds.

🚀Get running

git clone https://github.com/sahin/mobileplayer-ios.git
cd mobileplayer-ios
pod install
# or for Carthage:
carthage update

Then open the generated .xcworkspace (or add as CocoaPods/Carthage dependency to your project).

Daily commands: This is a framework library, not an executable app. To verify builds: xcodebuild -workspace MobilePlayer.xcworkspace -scheme MobilePlayer -configuration Debug build or integrate via CocoaPods/Carthage into a test app. No standalone dev server.

🗺️Map of the codebase

  • MobilePlayer/MobilePlayerViewController.swift — Core entry point and primary controller managing the entire media player lifecycle, state transitions, and overlay coordination.
  • MobilePlayer/MobilePlayerOverlayViewController.swift — Manages the UI overlay including playback controls, progress tracking, and interactive elements—essential for understanding the player's visual layer.
  • MobilePlayer/Config/MobilePlayerConfig.swift — Central configuration model that drives all customization; required reading to understand how to configure any player instance.
  • MobilePlayer/MobilePlayerNotification.swift — Notification and event system that decouples controller communication and enables external observers to react to player state changes.
  • MobilePlayer/Extensions/UIColor+Hex.swift — Utility extension for hex color parsing used throughout config styling; lightweight but widely referenced.
  • MobilePlayer/Parsers/YoutubeParser.swift — Handles YouTube URL parsing and video source extraction; critical for understanding media source handling strategy.
  • MobilePlayer.podspec — Package specification defining dependencies (none), platform targets, and public API surface.

🛠️How to make changes

Add a custom playback control button

  1. Define button appearance in MobilePlayerConfig by instantiating ButtonConfig with desired styling (MobilePlayer/Config/MobilePlayerConfig.swift)
  2. Create button element in overlay using ButtonConfig and assign closure callback via ClosureSupport extension (MobilePlayer/Extensions/ClosureSupport.swift)
  3. Wire button action to post MobilePlayerNotification events for state communication (MobilePlayer/MobilePlayerNotification.swift)
  4. Add button layout constraints and gesture recognizers in overlay VC's setupControlsUI method (MobilePlayer/MobilePlayerOverlayViewController.swift)

Support a new video source provider

  1. Create new parser file (e.g., VimeoParser.swift) in MobilePlayer/Parsers/ following YoutubeParser pattern (MobilePlayer/Parsers/YoutubeParser.swift)
  2. Implement URL detection and video source extraction logic in the parser class (MobilePlayer/Parsers/YoutubeParser.swift)
  3. Integrate parser into MobilePlayerViewController's media source initialization logic (MobilePlayer/MobilePlayerViewController.swift)
  4. Post MobilePlayerNotification.SourceParsed to signal successful source extraction (MobilePlayer/MobilePlayerNotification.swift)

Customize player UI appearance globally

  1. Create MobilePlayerConfig instance and configure BarConfig, ButtonConfig, LabelConfig with desired colors/fonts (MobilePlayer/Config/MobilePlayerConfig.swift)
  2. Use UIColor+Hex extension to specify colors via hex strings (e.g., #FFFFFF) for easy theming (MobilePlayer/Extensions/UIColor+Hex.swift)
  3. Pass configured MobilePlayerConfig to MobilePlayerViewController initializer (MobilePlayer/MobilePlayerViewController.swift)
  4. Verify styling propagates to overlay controls via MobilePlayerOverlayViewController's applyConfig method (MobilePlayer/MobilePlayerOverlayViewController.swift)

React to player state changes from external code

  1. Register observer for desired MobilePlayerNotification event (e.g., PlaybackStateChanged) (MobilePlayer/MobilePlayerNotification.swift)
  2. Implement notification handler callback to execute custom logic when player state changes (MobilePlayer/MobilePlayerNotification.swift)
  3. Use NotificationCenter.default.addObserver with the notification name from MobilePlayerNotification (MobilePlayer/MobilePlayerViewController.swift)
  4. Clean up observer in deinit or viewWillDisappear to avoid retain cycles (MobilePlayer/MobilePlayerViewController.swift)

🔧Why these technologies

  • AVFoundation (AVPlayer) — Native iOS media playback engine; no external dependencies, handles audio/video decoding, streaming, DRM.
  • UIKit — Native iOS UI framework for customizable overlay controls, layout constraints, gesture recognition.
  • NotificationCenter — Decoupled event propagation allowing external observers to react to player state without tight coupling.
  • Swift — Modern type-safe language enabling compile-time safety for configuration objects and UI layout.

⚖️Trade-offs already made

  • Zero external dependencies (no Pods/Carthage requirements)

    • Why: Reduces integration friction, avoids version conflicts, simplifies installation.
    • Consequence: Cannot leverage battle-tested libraries; all streaming logic, caching, analytics must be custom-built by consumer.
  • Declarative config-driven UI customization (MobilePlayerConfig classes)

    • Why: Enables runtime appearance changes without code changes; easy for non-engineer product teams.
    • Consequence: Limited visual expressiveness—constrained to pre-defined configuration surfaces; requires code for truly custom layouts.
  • Single-provider parser architecture (YoutubeParser pattern)

    • Why: Clean separation of concerns; each provider's URL extraction logic isolated.
    • Consequence: Requires manual registration/discovery of new parsers; no auto-detection mechanism for providers.
  • Tight coupling between MobilePlayerViewController and AVPlayer (no abstraction layer)

    • Why: Simplicity; direct access to AVPlayer APIs for playback control.
    • Consequence: Difficult to swap playback engines or mock for testing; changes to AVPlayer API require controller changes.

🚫Non-goals (don't propose these)

  • Real-time analytics or event tracking (integrations are consumer responsibility)
  • Adaptive bitrate streaming or HLS variant negotiation (consumer must provide variant URLs)
  • DRM license management beyond AVPlayer native support
  • Live streaming chat or comments integration
  • Picture-in-picture (PiP) support (not implemented)
  • Closed captions or subtitle rendering (passthrough only via AVPlayer)
  • Android or tvOS support (iOS only)

🪤Traps & gotchas

JSON Configuration Loading: MobilePlayerViewController can load config from remote JSON URLs—ensure HTTPS and timeout handling are tested, as network failures could silently degrade UI. Watermark Positioning: WatermarkPosition enum exists but exact coordinate calculation not visible; test edge cases on different screen sizes and orientations. Overlay Timing: Timed overlays require precise playback time tracking—potential audio/video sync issues not obvious from code structure. No explicit testability: No Tests/ folder visible suggests integration testing may require launching full app or using snapshot tests. Swift Version Constraint: .swift-version file exists—verify Xcode/Swift version compatibility during CI setup.

🏗️Architecture

💡Concepts to learn

  • Configuration Object Pattern — MobilePlayer's entire customization system is built on *Config classes (MobilePlayerConfig, ButtonConfig, BarConfig, SliderConfig, WatermarkConfig) that serialize/deserialize from JSON and define UI behavior—understanding this pattern is essential to extending the player without code changes
  • ViewController Composition & Container Patterns — MobilePlayerViewController acts as a container embedding AVPlayer, overlays, and UI elements through MobilePlayerOverlayViewController—this hierarchical VC pattern is core to understanding how overlays inject content at runtime
  • AVPlayer Wrapping & State Management — The player wraps system AVPlayer and exposes a State enum (visible in docs); understanding the state machine (playing, paused, stopped) is needed to hook custom logic and overlays at correct playback moments
  • JSON Schema Deserialization in Swift — MobilePlayer supports loading entire player config from remote JSON files; understanding Codable protocol and custom JSONDecoder setup is required to extend configuration with new fields or support external config servers
  • Watermark Positioning & Layout Calculation — WatermarkConfig with WatermarkPosition enum handles absolute positioning of branding overlays; ElementWidthCalculation enum suggests flexible layout math—critical for maintaining watermark visibility across device sizes and orientations
  • Timed Overlay Injection & Playback Synchronization — The overlay system supports 'timed overlays' (showing overlays during defined playback intervals); this requires syncing ViewController presentation with AVPlayer currentTime tracking—non-trivial for audio/video sync at millisecond precision
  • Pre-roll / Post-roll & Content Sequencing — MobilePlayer's engagement model shows overlays before (pre-roll) and after (post-roll) video content; this sequencing pattern is common in monetization/advertising systems and requires careful state transitions to avoid UX breaks
  • xybang/YBImageBrowser — Full-screen media viewer with customizable UI and overlay support; shares the 'flexible skinning + overlays' pattern for visual content
  • PlayerKit/player — AVPlayer wrapper with modular architecture; similar goal of simplifying video player integration with custom controls
  • google/ExoPlayer — Industry standard adaptive media player (Android); MobilePlayer aspires to iOS equivalent level of customization and engagement features
  • brightcove/brightcove-player-sdk-ios — Commercial video player SDK for iOS with branding and pre/post-roll; direct feature competitor in same ecosystem
  • sahin/mobileplayer-android — Official Android port of this framework; if you're supporting cross-platform video, this is the sibling repo with analogous architecture

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add GitHub Actions CI/CD workflow to replace Travis CI

The repo uses outdated .travis.yml for CI. GitHub Actions is now the standard for GitHub repositories and would provide faster, more integrated CI/CD. This includes running Swift linting, building the framework, and running any unit tests. The repo has no visible test files, so setting up a basic build verification workflow would catch regressions early.

  • [ ] Create .github/workflows/swift-build.yml to build the framework on push/PR
  • [ ] Configure the workflow to test against multiple iOS SDK versions (reference .swift-version file)
  • [ ] Add a step to verify documentation can be generated (via jazzy, evident from Documentation/ folder)
  • [ ] Optionally deprecate or remove .travis.yml once workflow is validated

Create unit tests for MobilePlayerViewController and core configuration classes

The Documentation folder shows several config classes (MobilePlayerConfig, BarConfig, ButtonConfig, ElementConfig, etc.) but there are no visible test files in the repo structure. These configuration classes are critical to the library's customization feature and lack test coverage. Adding unit tests would improve code reliability and serve as usage examples.

  • [ ] Create Tests/ directory structure mirroring Sources/ (if not already present)
  • [ ] Add unit tests for MobilePlayerConfig covering initialization and property setters
  • [ ] Add unit tests for ElementConfig, BarConfig, ButtonConfig, and other config classes to verify they properly accept and store custom values
  • [ ] Test WatermarkConfig with different WatermarkPosition enum values
  • [ ] Add tests to verify ElementWidthCalculation enum behavior in configuration contexts

Complete and fix the README badges and add quick-start code example

The README has a broken StackOverflow link ('httpx://' typo) and incomplete Gitter badge. More critically, the README lacks a quick-start code example showing how to instantiate MobilePlayerViewController and configure it. Given the library's focus on customization, a concrete example using MobilePlayerConfig would significantly improve discoverability and reduce contributor friction.

  • [ ] Fix the malformed StackOverflow badge link (httpx:// → https://)
  • [ ] Complete the truncated Gitter badge markup
  • [ ] Add a 'Quick Start' section with a minimal code example showing MobilePlayerViewController initialization
  • [ ] Include an example demonstrating MobilePlayerConfig customization (e.g., hiding certain UI elements or customizing colors)
  • [ ] Add a link to the Documentation/index.html (Jazzy docs) in the README for detailed API reference

🌿Good first issues

  • Add unit tests for ButtonConfig, BarConfig, and SliderConfig JSON deserialization (Configuration classes exist but no test files visible in top 60 structure; write tests in Tests/ConfigurationTests.swift to validate JSON→model mapping)
  • Implement missing ElementType.volumeButton and ElementType.volumeSlider cases (README lists 'Volume button and volume slider elements' as future; add enum cases, then create VolumeSliderConfig.swift following SliderConfig pattern)
  • Add comprehensive inline documentation examples to MobilePlayerViewController showing how to programmatically configure overlays for pre-roll, pause, and post-roll (Classes are 100% documented per README but practical overlay setup examples missing from docstrings)

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 84e9edc — docs(readme): remove waffle badge (isair)
  • 0fa9779 — docs(readme): fix broken badge and remove broken intro gif (isair)
  • e9b04c2 — Merge branch 'release/1.3.0' (isair)
  • 85d9241 — Update cocoapods to 1.6.1 (isair)
  • dd9dd4d — Use Ruby 2.5.3 (isair)
  • 433c9e9 — Merge pull request #198 from viniciussoares/master (isair)
  • 487b47e — Update video url and docs (viniciussoares)
  • 9b65add — Update ruby version, dotfiles and cocoapods (viniciussoares)
  • 2f47245 — Update travis osx image (viniciussoares)
  • 83c4132 — Upgrade test target to 4.2 (viniciussoares)

🔒Security observations

The mobileplayer-ios repository shows a reasonable security baseline for an iOS library project with no obvious critical vulnerabilities visible in the provided file structure. The project claims zero external dependencies which is a positive security indicator. However, several configuration files have unavailable content (.ruby-version, .travis.yml, .swiftlint.yml) that should be reviewed. The main recommendations are: (1) verify outdated tooling versions are not used, (2) audit CI/CD pipeline for secure practices, (3) ensure sensitive files are properly gitignored, and (4) maintain strict SwiftLint rules for secure coding patterns. No injection risks, hardcoded secrets, or obvious misconfigurations were detected in available files.

  • Medium · Outdated Ruby Version File — .ruby-version. The .ruby-version file is present but its content is not visible. This could indicate outdated Ruby dependencies if the version is old. Ruby versions older than 2.7 may have known security vulnerabilities. Fix: Verify Ruby version is up-to-date (3.0+). Update build tools and dependencies regularly.
  • Low · Missing HTTPS in README Badge URL — README snippet. The README contains a malformed URL 'httpx://stackoverflow.com' instead of 'https://stackoverflow.com', indicating possible typo but not a direct security risk. Fix: Correct the URL to use proper HTTPS protocol.
  • Low · Incomplete Security Configuration Review — MobilePlayer/.swiftlint.yml. The .swiftlint.yml configuration file is present but its content is not visible. SwiftLint can help enforce secure coding practices, but effectiveness depends on configuration. Fix: Review and ensure SwiftLint rules include security-related checks (e.g., force_unwrap, implicitly_unwrapped_optional).
  • Low · Travis CI Configuration Not Analyzed — .travis.yml. The .travis.yml file is present but content not visible. CI/CD configurations can contain secrets or insecure practices if not properly configured. Fix: Ensure CI/CD pipeline: (1) never logs secrets, (2) uses encrypted environment variables, (3) performs security scanning, (4) validates dependencies.
  • Low · Git Repository Metadata Exposed — .gitignore, .github/. The .github/ISSUE_TEMPLATE.md and .gitignore files are present. Verify .gitignore properly excludes sensitive files (API keys, certificates, etc.). Fix: Audit .gitignore to ensure it excludes: *.pem, *.key, *.p12, *.mobileprovision, .env files, and any local config with credentials.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · sahin/mobileplayer-ios — RepoPilot