Implementation of a Recommendation System for Video Streaming

Implementation of a Recommendation System for Video Streaming

AI Development Areas

Frequently Asked Questions

Latest works

  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1284
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1240
  • image_logo-advance_0.webp
    B2B Advance company logo design
    696
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    982
  • image_logo-aider_0.webp
    AIDER company logo development
    917
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    1031

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.