Back to Work

Case Study

Media Playback & Reels Systems

I designed and implemented the feed and reels playback systems behind StartupKroo’s video-heavy experience across Android and iOS, solving for smooth scrolling, faster video startup, controlled memory usage, and platform-specific playback constraints.

AndroidiOSFeedReelsExoPlayerAVPlayer
Media playback and reels system visual

Problem

Build a smooth, production-ready feed and reels experience for mixed-content scrolling environments without letting video playback break memory, responsiveness, or UX across Android and iOS.

Scope

Covered feed and reels playback systems across both platforms, including player lifecycle, preloading strategy, paging behavior, memory control, and platform-specific implementation choices.

Focus

Playback speed, scroll performance, memory efficiency, architecture under platform constraints, and choosing solutions that matched product scope instead of copying large-team systems blindly.

Context

Engineering context and system requirements

Feed and reels started as relatively lightweight features, especially in earlier MVP phases where content volume was lower and the priority was to move fast. That was enough initially, but once the product matured and short-form video became more important, playback quality and perceived smoothness became core product expectations.

The hard part was not simply showing video. The challenge was building a system that could handle scrolling environments, mixed content, and real production usage while still feeling responsive and controlled on mobile hardware.

This became a serious engineering problem across both Android and iOS, because the same user-facing requirement — smooth feed and reels playback — had to be solved using very different platform realities.

Challenges

Performance constraints and playback realities

The feed was not a video-only surface. It included mixed content such as single-image posts, multi-image posts, reels thumbnail carousels, and video posts, which made memory and recycling behavior much more demanding.

Fast playback mattered in both reels and feed, but the product had to stay stable over long sessions rather than winning only on short demo scenarios.

Android and iOS required fundamentally different solutions. A strategy that worked well on one platform could be inefficient or impractical on the other.

ExoPlayer is powerful but heavy. AVPlayer is more controlled in some ways but offers far less natural support for caching and aggressive preload workflows.

The system had to support vertical paging, autoplay based on visibility, and smooth transitions between items without relying on brute-force multi-player approaches.

Performance work had to stay grounded in actual product scope, time, and maintainability — not overbuilt as if this were a large dedicated media infrastructure team.

Decisions

Key engineering decisions

The key technical calls and trade-offs that shaped the platform.

Single-player architecture on Android

For Android feed and reels, I chose a single ExoPlayer architecture instead of separate players per item or a larger pool of players. ExoPlayer is expensive in terms of decoder, surface, and overall resource cost in scroll-heavy environments. A single-player system with visibility-based playback gave the best balance of responsiveness, control, and stability.

SurfaceView over TextureView

I preferred SurfaceView because it is more performance-friendly for ExoPlayer-based rendering and better aligned with long-term needs like DRM-supported content. That decision favored system efficiency over UI flexibility where the product did not actually need TextureView-level behavior.

PreloadManager over earlier Android preload attempts

I iterated through multiple preload strategies before landing on Media3 PreloadManager. A background ExoPlayer preload approach was not reliable enough because HLS adaptive streaming could still choose different tracks at playback time. Partial chunk download using HLSDownloader and StreamKeys also became too fragile for the realities of our content variations. PreloadManager gave the most production-suitable balance for our scope.

Player pooling on iOS instead of Android-style caching assumptions

On iOS, I did not try to force an Android mental model onto AVPlayer. Since AVPlayer does not offer the same natural, efficient caching story for this kind of scroll-based preload system, I used a player-pooling approach where three players formed a moving window around the active item.

UIKit for feed and reels instead of forcing SwiftUI

SwiftUI worked well in earlier phases for simpler modules, but when feed and reels needed real paging, memory control, diffing, and media lifecycle handling, I moved those modules into UIKit. That decision gave me the control needed to implement performance-aware systems instead of fighting the abstraction.

Approach

Playback architecture and implementation direction

Scroll-aware playback control

Across both platforms, playback was tied to visibility rather than naive per-item media ownership. The active video was determined by what the user was actually seeing, which kept the experience aligned with natural feed and reels behavior while avoiding wasteful playback management.

Platform-specific performance architecture

I treated Android and iOS as different engineering problems instead of pretending there was one universal playback pattern. The goal was consistent product behavior, but the implementation had to respect what each platform was actually good at.

Sliding-window thinking for preload systems

A useful mental model for both platforms was the sliding window: the currently active item, the next likely item, and nearby context around it. On Android, that shaped how media preloading worked. On iOS, it shaped the player pool design. This gave the founder a clear conceptual model too, which helped in product and investor-facing discussions.

Performance without blind over-engineering

The system had to be fast, but also realistic for one primary engineer building within product constraints. I deliberately avoided solutions that only made sense for larger teams or much heavier infrastructure footprints.

Key Implementations

Systems implemented

Mixed-content feed playback system

Built feed architecture that could support images, multiple images, reels thumbnails, and video posts in one scrolling surface while keeping playback logic isolated, visibility-driven, and memory-conscious.

Android single-player feed and reels implementation

Implemented a shared ExoPlayer model for feed and reels, where the active video is attached and controlled based on visibility rather than giving each item its own long-lived player instance.

Android media preloading with Media3

Integrated Media3 PreloadManager to preload upcoming media chunks in a way that improved startup speed for likely next items without turning the system into a brittle custom downloader pipeline.

iOS player-pool design for fast startup

Implemented a 3-player pool on iOS as a moving window for vertical paging environments, allowing nearby videos to be prepared without requiring a heavy multi-player-per-item strategy.

Hybrid SwiftUI/UIKit integration

Kept performance-heavy modules like feed and reels in UIKit while allowing the broader app to continue using SwiftUI where it remained productive and sufficient. This preserved control without forcing a total rewrite.

Playback-focused mental models for product leadership

Translated deep playback decisions into structured concepts the founder could understand and explain, including the sliding-window mindset for preloading and why Android and iOS needed different technical strategies to achieve similar product outcomes.

Outcome

Performance outcomes

Delivered a feed and reels experience that moved beyond MVP playback and toward a much more production-ready video system.

Improved perceived startup speed for upcoming videos through preload strategies matched to each platform’s actual capabilities.

Kept memory and rendering behavior controlled in mixed-content feed environments instead of relying on unstable multi-player patterns.

Built a playback system the product could grow on without forcing platform-inappropriate abstractions or infrastructure overhead.

Turned a major product uncertainty — whether fast, modern playback was realistically achievable at this scope — into a working system shipped across both platforms.

Tech Stack

Playback stack and supporting technologies

ExoPlayerMedia3PreloadManagerSurfaceViewAVPlayerUIKitSwiftUIRecyclerViewUICollectionViewPagingVideo PlaybackPerformance Engineering