In the fast-paced world of streaming, user experience is paramount. While many apps focus heavily on content navigation and discovery, the video player itself often doesn't get the attention it deserves—even though it’s where users spend most of their time. Recently, we worked on an ambitious project for a broadcaster: unifying 4 different XIB-based iPhone and iPad video players for various streaming formats—SVOD, PVOD, AVOD, linear TV, live sports, movies, and TV shows—into a single, code-based solution using Swift and UIKit.
This transition not only made the player more flexible and easier to maintain, but it also significantly improved performance across devices, ensuring the broadcaster’s app could handle any content type, orientation, or device. Here's how we tackled this project.
The Challenge: Managing Multiple Content Types
The broadcaster's streaming app had to support a variety of content requirements. For example, AVOD uses HLS Interstitials and requires call-to-action (CTA) buttons to be displayed during ad playback. Sports content often includes live statistics or a channel list (for the same event) on a side pane. According to subscription plans, or PVOD, assets behave differently when launching the player. Maintaining separate XIB-based players for each content type led to redundant code and slower load times.
The goal was to build a unified player that could dynamically adapt to all these environments, handle different control sets, and support all iOS and iPadOS devices—while still being responsive and easy to use.
The Power of AVPlayer: Native Performance and Advanced Features
At the heart of the video player is AVPlayer, Apple’s native video playback engine. AVPlayer is the most performant player available for iOS and iPadOS because it’s deeply integrated into the system. It also provides access to the latest set of streaming features designed specifically for Apple devices. By building the player on top of AVPlayer, we were able to harness the full power of Apple's media frameworks, ensuring smooth playback, low-latency streaming, and seamless integration with Apple’s advanced features like AirPlay, Picture-in-Picture, HLS Interstitials and HDR. AVPlayer’s native capabilities made it the ideal foundation for a high-performance player, giving us a strong platform to build a flexible and adaptable user interface.
The Broadcaster’s Signature UX/UI Design
Underneath the player, we used AVPlayer as the foundation for video playback, which is a common choice in streaming apps. However, the entire UX/UI design was crafted based on the broadcaster's own Figmas, making the player feel like a unique and recognizable part of their app. This distinctive design, incorporating the broadcaster’s branding and user experience guidelines, ensured the player fit seamlessly with the rest of the app, maintaining the broadcaster’s signature look and feel. From the way controls were displayed to the overall user interaction flow, the player had to embody the broadcaster’s vision while still delivering top-tier performance.
Addressing Interoperability with DRM and Short HLS Segments
One of the more challenging aspects of this project was ensuring seamless interoperability between AVPlayer and the broadcaster's custom streaming setup, which included the use of short HLS segments (40 frames) for low-latency live streaming. While AVPlayer natively supports HLS streaming, these short segments put extra pressure on the player, which thrives on having advanced content to properly react and manage features like Picture-in-Picture (PiP), buffering, and seamless playback. The short buffer meant that the player had to continuously adapt, ensuring the stream remained smooth without interruptions.
It’s worth noting that the segment duration, particularly for VOD content, will likely be revised in the future to better align with industry standards and improve the overall user experience. However, for now, the unified player manages these complexities efficiently while maintaining the high-performance standards expected for the broadcaster's diverse range of content.
Explicit Main Thread Management with UIKit
When working with UIKit, one of the important aspects is managing how and when the UI gets updated. Since UIKit handles all of its interface changes on the main thread—the part of the system that directly interacts with what the user sees—developers need to be explicit in ensuring that any changes or updates happen at the right time. If this isn’t done carefully, it can cause the app to slow down or crash or certain features, like picture-in-picture, to stop working correctly. This is particularly true when navigating within the app while trying to keep the video player running smoothly in the background (PIP).
Handling Picture-in-Picture (PiP)
One of the more challenging features is indeed PiP, particularly in-app PiP which is mixing video playback and app navigation. Since UIKit requires careful main thread management, ensuring PiP worked seamlessly required a lot of testing. Each navigation scenario within the app had to be considered to make sure PiP continued functioning smoothly as users switched between different areas of the app. Whether using system-level PiP or the broadcaster’s custom in-app PiP, performance and user experience were a priority.
Other Interactions During Playback
Beyond video playback itself, the player also had to handle ongoing data exchanges with external services. For example, Nice People At Work (NPAW) statistics gathering is integrated to monitor and optimize the quality of experience. This system collects real-time data to ensure smooth playback and identify any performance bottlenecks. Additionally, the player regularly communicated with the broadcaster's API to send the player's position in the video. This allowed users to resume playback at the same point on any device, ensuring a seamless multi-device viewing experience. These background interactions have to be managed efficiently without affecting overall playback performance.
Flexible Controls for Various Content Types
One of the player’s key features is its flexible controls, which dynamically adapt based on content type and the user’s environment. For example:
- Language controls (audio and subtitle) are essential across most content.
- A “next episode” button appears only for TV dramas.
- Channel selection is available only for live sports.
- Real-time statistics are displayed only for sports with stats.
These controls must also adjust based on screen orientation and device size, ensuring the player remains intuitive and uncluttered. When the player size or orientation changes, the controls automatically adjust to optimize the user experience.
Improved Performance: The Case for Code-Based Players
Another significant benefit of switching to a code-based player was improved performance. XIBs require all elements to be prepared in advance, meaning the system has to load the entire XIB before displaying the player. When working with four separate XIBs, this loading process had to be repeated four times, leading to slower performance and memory management issues.
In contrast, a code-based approach allows for more controlled memory management, with resources only being loaded when needed and freed when no longer in use. This approach drastically reduced load times and improved performance, especially on older devices with limited CPU and memory resources. The new player is faster, more efficient, and avoids the common pitfalls of XIB overuse.
Testing During a Major iOS Update
The project coincided with the release of iOS 18, the first Swift 6-based version of iOS, which made testing more complicated. It wasn’t always clear whether issues were caused by the code, the system, or the environment. Special attention was given to testing on legacy devices, where the performance improvements were most noticeable due to their limited resources.
Metrics and User Feedback (Coming Soon)
At this stage, there are no concrete user metrics—such as hang rates, memory consumption, or feedback from reviews and NPS surveys—but initial tests show substantial improvements in speed and flexibility. This case study will be updated as more user data becomes available.
Flexibility and Performance Are Essential
In modern streaming apps, flexibility and performance are crucial to delivering a top-notch user experience. By unifying the broadcaster’s video players into a single, code-based solution, we simplified development, improved performance, and ensured the player could seamlessly adapt to different content types and environments.
This project highlights the importance of focusing on the video player itself, not just the navigation around it, as it’s ultimately where users spend most of their time.