Streamlining Video Players: Fixing Inconsistent UX

by Admin 51 views
Streamlining Video Players: Fixing Inconsistent UX

Unpacking the Dual Video Player Dilemma: Why We Need a Unified Approach

Hey guys, let's talk about something critical that's been affecting our app's user experience and making life a bit tougher for us developers: the fact that we're currently running with two completely separate video player implementations! Seriously, it's like having two different cars in the garage for the same commute. This isn't just an architectural quirk; it's the direct result of an incomplete migration from an older system, CreateVideoPlayerGroup, to a shiny new one, VideoPlayerView. Imagine logging into your favorite streaming app and seeing different playback controls and on-screen displays (OSDs) depending on whether you're watching a movie or live TV. That's exactly the kind of inconsistent user experience our users are encountering right now, and frankly, it's not ideal.

At its core, this problem means our application is juggling similar underlying logic but with wildly divergent OSDs, controls, and overall component architectures. We're in a situation where ongoing improvements, bug fixes, and refactors are almost exclusively being applied to the newer VideoPlayerView system. This creates a growing chasm between the two, leading to increasing divergence, potential bugs that only affect one system, and a perpetually inconsistent user experience that can frustrate even our most loyal users. From a development standpoint, it's a huge drag on code maintenance and efficiency, making bug fixes a double chore and new feature implementations a repetitive nightmare. Our goal here is to shed light on this issue, understand its full impact, and chart a clear path towards a unified video player architecture that benefits everyone, from our users to our development team. This isn't just about tidying up code; it's about delivering a seamless, high-quality, and future-proof video playback experience across our entire platform.

The Origin Story: How We Ended Up With Two Video Players

Alright, let's dive into the history books a bit to understand how we got into this dual video player implementation situation. It all boils down to a well-intentioned but ultimately incomplete migration project initiated by a previous developer. The idea was solid: move away from an older, direct-playback system to a more modern, queue-based video player (VideoPlayerView) that offered better architecture and a more consistent user experience. However, as often happens in software development, the migration wasn't fully completed. The result? We now have to maintain two parallel video playback systems within our codebase, each with its own quirks and maintenance overhead. It's like having two different sets of blueprints for the same house, but only one set is getting regular updates and renovations.

Let's break down these two systems so you guys can see the difference:

The New Kid on the Block: VideoPlayerView ✅

This is our preferred, modern system, built with a forward-thinking queue-based architecture. It's designed for flexibility and a superior user experience. When you initiate playback through this system, the journey typically begins with QueueManager.playQueue() which then calls CreateVideoPlayerView(). The core components you'll find here are components/video/VideoPlayerView.xml/.bs, which handles the main video component and our sleek, modern OSD and controls. Metadata loading is managed by components/ItemGrid/LoadVideoContentTask.bs. This system is currently responsible for playing movies, episodes (especially when part of a queue), music videos, and trailers. It's where all the cool new features and performance improvements are landing, making it the bedrock for our future video playback capabilities. The unified video playback experience we're striving for is centered around this architecture.

The Old Guard: CreateVideoPlayerGroup ❌

Then we have the legacy system, CreateVideoPlayerGroup. This one represents the older way of doing things, characterized by direct playback and an undeniably outdated OSD and controls. Its primary entry point is CreateVideoPlayerGroup() which then calls VideoPlayer(). The core components are source/VideoPlayer.bs and components/JRVideo.xml/.bs. While it served its purpose well in the past, it's now the source of our inconsistent user experience issues. Crucially, this legacy system is still handling playback for Live TV, recordings, direct episode playback (outside of a queue), quickplay features, and even intro videos. This means a significant portion of our users are still interacting with an older, less polished interface, completely missing out on the enhancements we're building into the new system. Understanding these two distinct video player architectures is the first step in recognizing the scope of our incomplete migration and why a complete transition is absolutely essential for our app's future.

The Unfinished Business: Where Our Legacy Player Still Reigns

Now that we've seen the two systems, it's crucial to identify exactly where the legacy video player system (CreateVideoPlayerGroup) is still being actively used. This isn't just a handful of obscure corners; these are vital parts of our application, directly impacting a significant segment of our user base. Understanding these legacy code paths is key to planning our migration to VideoPlayerView effectively. Each instance represents a point of inconsistent user experience and a missed opportunity for leveraging our modern video player architecture. Let's break down the specific areas where the old system stubbornly persists:

1. Live TV Channels: Stuck in the Past

One of the most impactful areas where the legacy player still operates is in Live TV channel playback. When a user selects a TV channel, the application currently routes through source/Main.bs:536, where it calls CreateVideoPlayerGroup(node.id). This means that users watching live broadcasts are consistently presented with the outdated OSD and controls of the old system. This is a critical feature for many users, and the discrepancy in experience compared to watching a movie (which uses the new system) is immediately noticeable. A true unified video player must handle Live TV seamlessly.

2. Direct Episode Playback: Bypassing the Queue

Similarly, if a user initiates direct episode playback without going through the queue system (e.g., from a details page or a recently watched list), the application falls back to CreateVideoPlayerGroup(node.id) at source/Main.bs:539. This highlights a core issue: any playback not explicitly funneled through QueueManager.playQueue() risks landing in the old system. For users who prefer to jump straight into an episode, this again means a less refined experience, further emphasizing the inconsistent user experience we're trying to eliminate.

3. Recordings: Reliving the Old Days

Just like Live TV, recording playback also utilizes the legacy system. The code at source/Main.bs:542 uses CreateVideoPlayerGroup(node.id) when playing back a recorded show. This is another high-impact area, as users expect a modern, feature-rich experience when engaging with their personal library of content. The absence of newer features and UI elements from the VideoPlayerView in recordings creates a disjointed feel for users who switch between live and recorded content.

4. Live TV Restart: A Relic Returns

Even after a Live TV session finishes, if a user opts to restart it, the old system makes a comeback. At source/Main.bs:778, the condition `if node.selectedItemType =