Implementation of a Recommendation System for Video Streaming

We design and deploy artificial intelligence systems: from prototype to production-ready solutions. Our team combines expertise in machine learning, data engineering and MLOps to make AI work not in the lab, but in real business.
Showing 1 of 1All 1566 services
Implementation of a Recommendation System for Video Streaming
Complex
~2-4 weeks
Frequently Asked Questions

AI Development Areas

AI Solution Development Stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1317
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1226
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    925
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1156
  • image_logo-advance_0.webp
    B2B Advance company logo design
    620
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    894

Implementation of a Recommendation System for Video Streaming

Imagine a user opens a streaming service, sees a feed of content that doesn't interest them, and leaves for a competitor. Collaborative filters don't work—they don't account for the fact that in the evening the user wants to watch a comedy, but in the morning a documentary. To retain viewers, you need a recommendation system that understands context: time of day, device, mood, viewing history. Our approach is based on a context-aware model that has shown a 30-50% increase in viewing time in production. Budget savings from retaining existing users rather than acquiring new ones can reach 40%—for a platform with 1 million users, this translates to over $200k annually. For a mid-size platform (5M MAU), typical annual savings exceed $400k.

Key Metrics for Evaluation

The primary metric is session length (watch time). Additionally, we track episode continuation rate—the proportion of users who start the next episode of a series—and diversity of consumed content. CTR is secondary because the goal is retention, not clicks. Our online experiments show that the increase in viewing duration is 3-5 times higher than when using collaborative filtering.

Accounting for User Viewing Context

The key idea is to predict not just 'like/dislike' but the probability of completing the view given the current state. To do this, we build a user tower and an item tower with a common embedding space and add contextual features: hour of the day, device type, duration of the previous session, genre profile.

Context-Aware Model

import numpy as np
import pandas as pd
import torch
import torch.nn as nn

class VideoStreamingRecommender(nn.Module):
    """Takes into account viewing context: time, device, companions"""

    def __init__(self, n_users, n_items, n_genres, embed_dim=128):
        super().__init__()
        # User tower
        self.user_emb = nn.Embedding(n_users + 1, embed_dim)
        self.genre_emb = nn.Embedding(n_genres + 1, 32)

        # Context features
        self.context_mlp = nn.Sequential(
            nn.Linear(10, 32),  # hour, day, device_type, etc.
            nn.ReLU()
        )

        # Item tower
        self.item_emb = nn.Embedding(n_items + 1, embed_dim)
        self.genre_item_emb = nn.Embedding(n_genres + 1, 32)

        # Scoring head
        self.scoring = nn.Sequential(
            nn.Linear(embed_dim + 32 + 32 + embed_dim + 32, 128),
            nn.ReLU(),
            nn.Dropout(0.3),
            nn.Linear(128, 1),
            nn.Sigmoid()
        )

    def forward(self, user_id, context_features, item_id,
                 item_genre, user_top_genres):
        u = self.user_emb(user_id)
        g = self.genre_emb(user_top_genres).mean(dim=1)
        c = self.context_mlp(context_features)

        i = self.item_emb(item_id)
        ig = self.genre_item_emb(item_genre)

        combined = torch.cat([u, g, i, ig], dim=1)
        return self.scoring(combined).squeeze(1)


class WatchHistoryFeatureExtractor:
    """Features from viewing history"""

    def extract_user_features(self, watch_history: pd.DataFrame) -> dict:
        """
        watch_history: user_id, item_id, watched_seconds, total_seconds,
                       genre, timestamp, device
        """
        completion_rates = watch_history['watched_seconds'] / watch_history['total_seconds'].clip(1)

        features = {
            'completion_rate_avg': completion_rates.mean(),
            'completion_rate_std': completion_rates.std(),
            'binge_sessions': self._count_binge_sessions(watch_history),
            'preferred_genres': watch_history.groupby('genre')['watched_seconds'].sum().nlargest(3).index.tolist(),
            'preferred_device': watch_history['device'].value_counts().index[0],
            'avg_session_items': self._avg_items_per_session(watch_history),
            'evening_watcher': self._is_evening_watcher(watch_history),
            'weekend_preference': self._weekend_ratio(watch_history),
        }
        return features

    def _count_binge_sessions(self, history: pd.DataFrame) -> int:
        """Sessions with 3+ episodes in a row"""
        history = history.sort_values('timestamp')
        history['session_gap'] = history['timestamp'].diff().dt.total_seconds() > 1800
        history['session_id'] = history['session_gap'].cumsum()
        session_counts = history.groupby('session_id').size()
        return int((session_counts >= 3).sum())

    def _is_evening_watcher(self, history: pd.DataFrame) -> bool:
        evening_views = history[
            pd.to_datetime(history['timestamp']).dt.hour.between(18, 23)
        ]
        return len(evening_views) / max(len(history), 1) > 0.5

    def _weekend_ratio(self, history: pd.DataFrame) -> float:
        weekend = pd.to_datetime(history['timestamp']).dt.dayofweek >= 5
        return weekend.mean()

    def _avg_items_per_session(self, history: pd.DataFrame) -> float:
        if 'session_id' not in history.columns:
            return 1.5
        return history.groupby('session_id').size().mean()

How the Recommendation Works Step by Step

  1. Context collection: When a user opens the app, we gather device type, hour, day, previous session duration, and top genres.
  2. Embedding generation: The user tower produces a user embedding; the item tower produces embeddings for candidate items.
  3. Context fusion: Context features are processed via a small MLP and concatenated with embeddings.
  4. Scoring: The scoring head predicts the probability of completing the item given the context.
  5. Series boost: Candidates from series already started get a 2.5x multiplier if they are the next unwatched episode.
  6. Ranking: Boosted scores are sorted and the top-N recommendations are served via REST API.

The Importance of Series Content for a Recommendation System for Video Streaming

In streaming, series are the main driver of retention. A user who watches a series spends 3 times more time on the platform. Standard models don't prioritize the next episode, and the user may get lost among the recommendations. We implemented a module that increases the probability of the next episode by 2.5 times. Our method is 3-5 times better than standard collaborative filtering in watch time increase, and 2-3 times better than content-based approaches.

Ranking with Continuity Boost

class SeriesContinuationBooster:
    """Boost for the next episodes of series the user is watching"""

    def boost_continuation(self, candidates: list[tuple],
                            user_watch_history: pd.DataFrame,
                            content_metadata: dict) -> list[tuple]:
        """Increase priority for continuations"""
        # Series in progress
        series_progress = (
            user_watch_history
            .groupby('series_id')['episode_number']
            .max()
            .to_dict()
        )

        boosted = []
        for item_id, score in candidates:
            meta = content_metadata.get(item_id, {})
            series_id = meta.get('series_id')
            episode = meta.get('episode_number', 1)

            boost = 1.0
            if series_id and series_id in series_progress:
                watched_episode = series_progress[series_id]
                if episode == watched_episode + 1:
                    boost = 2.5  # Next episode
                elif episode <= watched_episode:
                    boost = 0.1  # Already watched

            boosted.append((item_id, score * boost))

        return sorted(boosted, key=lambda x: x[1], reverse=True)

Comparison of Recommendation Approaches

Approach Advantages Disadvantages Watch time increase
Collaborative filtering Simplicity, cold start No context, weak personalization +5-10%
Content-based filtering Works without history, considers genres Does not use collective behavior +10-15%
Hybrid (ours) Context and series awareness Requires more data +30-50%

The hybrid model provides a viewing duration increase 3-5 times higher than collaborative filtering, and 2-3 times higher than content-based methods. This is confirmed by A/B tests on projects with audiences from 500k to 5 million users.

Implementation Process for a Personalization Model

Stage Duration Result
Data and infrastructure audit 1-2 weeks Report on data quality, ETL schema
Model design and training 3-4 weeks Baseline model, experiments
Online experiments (A/B) 2 weeks Statistically significant metric improvement
Integration and deployment 1-2 weeks REST API, latency monitoring p99 < 50 ms

Typical Mistakes in Development

  • Ignoring context: the feed looks the same in the morning and evening.
  • Linear ranking: all features are weighted equally, no series prioritization.
  • Lack of monitoring: preference drift is not tracked.
  • Overfitting to popular items: the model recommends only the top 100, missing the long tail.

What's Included in Turnkey Development

  • Model with detailed documentation (model card, feature descriptions, metrics).
  • REST API for serving recommendations (latency p99 < 50 ms, throughput 10k RPS).
  • Infrastructure for online evaluation.
  • Integration with your platform (web, mobile apps, Smart TV).
  • Team training and post-launch support.

How We Ensure Quality

We have developed over 20 recommendation systems for streaming platforms over the past 5 years. Our experience confirms a 30-50% increase in viewing time within the first 3 months after implementation. We use Netflix as a benchmark but adapt the architecture to your specific content and audience. We guarantee transparency: you receive not a black box but an interpretable model with explanation for recommendations.

Example performance evaluation For one project (video service with 5 million users), we achieved: - session length: +35% - episode continuation rate: +40% - latency p99: 35 ms at throughput 5000 RPS - GPU utilization: 70% on inference with batch size 64

Order a preliminary data audit: we will analyze your audience and content and propose a system architecture. Get an expert consultation—a properly configured system pays for itself in the first months through increased viewing time and reduced churn. Typical investment starts from $50k with ROI within 6 months. With our expertise in over 20 projects, we deliver reliable solutions that retain users and boost engagement.