Saturday, 23 August 2025

Complete Guide: Building a Live Cricket Streaming App for 100M Users

Comprehensive guide to building a scalable live cricket streaming platform for 100M users, covering backend infrastructure, streaming technology, and mobile app implementation.

System Architecture Overview

text
User Devices -> CDN -> Origin Server -> Encoding -> Video Source
API Gateway -> Microservices -> Database/Cache

Backend Infrastructure (AWS Focus)

1. Video Processing Pipeline

Components:

  • AWS Elemental MediaLive: For live video encoding

  • AWS Elemental MediaPackage: For packaging and DRM

  • AWS Elemental MediaStore: For origin storage

  • Amazon CloudFront: CDN for global distribution

Implementation:

bash
# Terraform example for MediaLive channel
resource "aws_medialive_channel" "cricket_stream" {
  name          = "cricket-live-stream"
  channel_class = "STANDARD"
  
  input_specification {
    codec           = "AVC"
    input_resolution = "HD"
    maximum_bitrate = "MAX_20_MBPS"
  }
  
  input_attachments {
    input_attachment_name = "rtmp-input"
    input_id              = aws_medialive_input.cricket_input.id
    
    input_settings {
      source_end_behavior = "CONTINUE"
      
      network_input_settings {
        server_validation = "CHECK_CRYPTOGRAPHY_AND_VALIDATE_NAME"
      }
    }
  }
  
  destinations {
    id = "mediapackage-destination"
    
    settings {
      password_param = "MediaPackagePassword"
      url            = aws_mediapackage_channel.cricket.endpoint_url
      username       = "streamuser"
    }
  }
}

2. Microservices Architecture

Services:

  • User Service

  • Match Service

  • Streaming Service

  • Notification Service

  • Analytics Service

Kubernetes Deployment:

yaml
# streaming-service deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: streaming-service
  namespace: cricket-app
spec:
  replicas: 10
  selector:
    matchLabels:
      app: streaming-service
  template:
    metadata:
      labels:
        app: streaming-service
    spec:
      containers:
      - name: streaming-service
        image: streaming-service:1.0.0
        ports:
        - containerPort: 8080
        env:
        - name: REDIS_HOST
          value: "redis-cluster.redis.svc.cluster.local"
        - name: KAFKA_BROKERS
          value: "kafka-cluster:9092"
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: streaming-service-hpa
  namespace: cricket-app
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: streaming-service
  minReplicas: 10
  maxReplicas: 100
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70

3. Database Architecture

Primary Database: Amazon Aurora PostgreSQL (Global Database)
Cache: Amazon ElastiCache (Redis) with cluster mode
Analytics: Amazon Redshift + Amazon Kinesis Data Streams

Mobile App Implementation (.NET MAUI)

1. Project Structure

text
CricketStreamApp/
├── Services/
│   ├── StreamingService.cs
│   ├── ApiService.cs
│   └── NotificationService.cs
├── Views/
│   ├── LiveMatchPage.xaml
│   ├── LiveMatchPage.xaml.cs
│   ├── MatchListPage.xaml
│   └── MatchListPage.xaml.cs
├── Models/
│   ├── Match.cs
│   ├── StreamQuality.cs
│   └── UserPreferences.cs
└── Utilities/
    ├── ConnectivityService.cs
    └── BitrateCalculator.cs

2. Key Implementation Files

StreamingService.cs (Adaptive Bitrate Streaming):

csharp
using LibVLCSharp.Shared;
using Microsoft.Maui.Controls;

namespace CricketStreamApp.Services
{
    public class StreamingService : IDisposable
    {
        private LibVLC _libVLC;
        private MediaPlayer _mediaPlayer;
        private string _currentStreamUrl;
        private readonly IConnectivityService _connectivityService;
        
        public event EventHandler<MediaPlayerTimeChangedEventArgs> TimeChanged;
        public event EventHandler<MediaPlayerStateChangedEventArgs> StateChanged;
        
        public StreamingService(IConnectivityService connectivityService)
        {
            _connectivityService = connectivityService;
            Core.Initialize();
            _libVLC = new LibVLC("--network-caching=3000", "--adaptive-logic=rate");
            _mediaPlayer = new MediaPlayer(_libVLC);
            
            _mediaPlayer.TimeChanged += (s, e) => TimeChanged?.Invoke(s, e);
            _mediaPlayer.StateChanged += (s, e) => StateChanged?.Invoke(s, e);
        }
        
        public void PlayStream(string streamUrl, string quality = "auto")
        {
            if (_connectivityService.GetNetworkType() == NetworkType.WiFi)
            {
                streamUrl = AdjustStreamQuality(streamUrl, quality);
            }
            else
            {
                streamUrl = AdjustStreamQuality(streamUrl, "low");
            }
            
            using var media = new Media(_libVLC, streamUrl, FromType.FromLocation);
            _mediaPlayer.Media = media;
            _mediaPlayer.Play();
            _currentStreamUrl = streamUrl;
        }
        
        private string AdjustStreamQuality(string url, string quality)
        {
            return quality switch
            {
                "low" => url + "/low.m3u8",
                "medium" => url + "/medium.m3u8",
                "high" => url + "/high.m3u8",
                "auto" => url + "/adaptive.m3u8",
                _ => url + "/adaptive.m3u8"
            };
        }
        
        public void Pause() => _mediaPlayer.Pause();
        public void Stop() => _mediaPlayer.Stop();
        
        public void SetQuality(string quality)
        {
            if (!string.IsNullOrEmpty(_currentStreamUrl))
            {
                Stop();
                PlayStream(_currentStreamUrl, quality);
            }
        }
        
        public void Dispose()
        {
            _mediaPlayer?.Dispose();
            _libVLC?.Dispose();
        }
    }
}

LiveMatchPage.xaml (Video Player UI):

xml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:vlc="clr-namespace:LibVLCSharp.Maui;assembly=LibVLCSharp.Maui"
             x:Class="CricketStreamApp.Views.LiveMatchPage"
             Title="Live Match">
    
    <Grid RowDefinitions="*,Auto,Auto">
        <!-- Video Player -->
        <vlc:VideoView x:Name="VideoPlayer" 
                       Grid.Row="0" 
                       MediaPlayer="{Binding MediaPlayer}" />
        
        <!-- Controls -->
        <StackLayout Grid.Row="1" 
                     Orientation="Horizontal" 
                     HorizontalOptions="Center"
                     Padding="10"
                     BackgroundColor="#CC000000">
            
            <Button Text="" 
                    Clicked="PlayButton_Clicked"
                    WidthRequest="60"
                    BackgroundColor="Transparent"
                    TextColor="White"/>
            
            <Button Text="" 
                    Clicked="PauseButton_Clicked"
                    WidthRequest="60"
                    BackgroundColor="Transparent"
                    TextColor="White"/>
            
            <Slider x:Name="PositionSlider"
                    Minimum="0"
                    Maximum="100"
                    Value="0"
                    ValueChanged="PositionSlider_ValueChanged"
                    WidthRequest="200"
                    ThumbColor="Red"
                    MinimumTrackColor="Red"/>
            
            <Label x:Name="TimeLabel"
                   TextColor="White"
                   VerticalOptions="Center"/>
        </StackLayout>
        
        <!-- Quality Selector -->
        <StackLayout Grid.Row="2" 
                     Orientation="Horizontal" 
                     HorizontalOptions="Center"
                     Padding="10"
                     BackgroundColor="#CC000000">
            
            <Label Text="Quality:" 
                   TextColor="White"
                   VerticalOptions="Center"/>
            
            <Picker x:Name="QualityPicker"
                    Title="Select Quality"
                    SelectedIndexChanged="QualityPicker_SelectedIndexChanged"
                    WidthRequest="150">
                <Picker.Items>
                    <x:String>Auto</x:String>
                    <x:String>High</x:String>
                    <x:String>Medium</x:String>
                    <x:String>Low</x:String>
                </Picker.Items>
            </Picker>
        </StackLayout>
    </Grid>
</ContentPage>

LiveMatchPage.xaml.cs (Code Behind):

csharp
using CricketStreamApp.Services;
using LibVLCSharp.Shared;

namespace CricketStreamApp.Views
{
    public partial class LiveMatchPage : ContentPage
    {
        private readonly StreamingService _streamingService;
        private bool _isSeeking;
        
        public LiveMatchPage(StreamingService streamingService, string matchId)
        {
            InitializeComponent();
            _streamingService = streamingService;
            
            // Set up event handlers
            _streamingService.TimeChanged += OnTimeChanged;
            _streamingService.StateChanged += OnStateChanged;
            
            // Load the stream
            LoadStream(matchId);
        }
        
        private void LoadStream(string matchId)
        {
            var streamUrl = $"https://streaming.cricketapp.com/matches/{matchId}";
            _streamingService.PlayStream(streamUrl);
        }
        
        private void OnTimeChanged(object sender, MediaPlayerTimeChangedEventArgs e)
        {
            if (!_isSeeking)
            {
                MainThread.BeginInvokeOnMainThread(() =>
                {
                    PositionSlider.Value = e.Time;
                    TimeLabel.Text = TimeSpan.FromMilliseconds(e.Time).ToString(@"hh\:mm\:ss");
                });
            }
        }
        
        private void OnStateChanged(object sender, MediaPlayerStateChangedEventArgs e)
        {
            // Update UI based on player state
        }
        
        private void PlayButton_Clicked(object sender, EventArgs e)
        {
            _streamingService.Play();
        }
        
        private void PauseButton_Clicked(object sender, EventArgs e)
        {
            _streamingService.Pause();
        }
        
        private void PositionSlider_ValueChanged(object sender, ValueChangedEventArgs e)
        {
            if (_isSeeking)
            {
                _streamingService.SeekTo(Convert.ToInt64(e.NewValue));
            }
        }
        
        private void QualityPicker_SelectedIndexChanged(object sender, EventArgs e)
        {
            var picker = (Picker)sender;
            var selectedQuality = picker.SelectedItem?.ToString()?.ToLower();
            
            if (!string.IsNullOrEmpty(selectedQuality))
            {
                _streamingService.SetQuality(selectedQuality);
            }
        }
        
        protected override void OnDisappearing()
        {
            base.OnDisappearing();
            _streamingService.Stop();
        }
    }
}

3. API Service Implementation

ApiService.cs:

csharp
using System.Text.Json;

namespace CricketStreamApp.Services
{
    public class ApiService
    {
        private readonly HttpClient _httpClient;
        private const string BaseUrl = "https://api.cricketapp.com/v1";
        
        public ApiService()
        {
            _httpClient = new HttpClient();
            _httpClient.DefaultRequestHeaders.Add("User-Agent", "CricketStreamApp/1.0");
        }
        
        public async Task<List<Match>> GetLiveMatches()
        {
            try
            {
                var response = await _httpClient.GetAsync($"{BaseUrl}/matches/live");
                response.EnsureSuccessStatusCode();
                
                var content = await response.Content.ReadAsStringAsync();
                return JsonSerializer.Deserialize<List<Match>>(content);
            }
            catch (Exception ex)
            {
                // Handle error
                return new List<Match>();
            }
        }
        
        public async Task<MatchDetail> GetMatchDetail(string matchId)
        {
            try
            {
                var response = await _httpClient.GetAsync($"{BaseUrl}/matches/{matchId}");
                response.EnsureSuccessStatusCode();
                
                var content = await response.Content.ReadAsStringAsync();
                return JsonSerializer.Deserialize<MatchDetail>(content);
            }
            catch (Exception ex)
            {
                // Handle error
                return null;
            }
        }
        
        public async Task<bool> UpdateUserPreferences(UserPreferences preferences)
        {
            try
            {
                var json = JsonSerializer.Serialize(preferences);
                var content = new StringContent(json, Encoding.UTF8, "application/json");
                
                var response = await _httpClient.PostAsync($"{BaseUrl}/user/preferences", content);
                return response.IsSuccessStatusCode;
            }
            catch (Exception ex)
            {
                // Handle error
                return false;
            }
        }
    }
}

Infrastructure Setup Guide

1. AWS Setup

  1. Create Media Services:

    • Set up AWS Elemental MediaLive channels for each stream

    • Configure AWS Elemental MediaPackage for packaging

    • Set up CloudFront distribution for MediaPackage endpoints

  2. Kubernetes Cluster:

    • Create EKS cluster with auto-scaling node groups

    • Deploy microservices with horizontal pod autoscaling

    • Set up Redis cluster for caching

  3. Database:

    • Create Aurora Global Database with read replicas

    • Set up connection pooling with PgBouncer

  4. Monitoring:

    • Implement CloudWatch for logging and metrics

    • Set up AWS X-Ray for distributed tracing

    • Configure Elastic Load Balancing with health checks

2. CI/CD Pipeline

yaml
# GitHub Actions example
name: Deploy to Production

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    
    - name: Set up .NET
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: '7.0.x'
        
    - name: Restore dependencies
      run: dotnet restore
      
    - name: Build
      run: dotnet build --configuration Release --no-restore
      
    - name: Test
      run: dotnet test --no-restore --verbosity normal
      
    - name: Publish
      run: dotnet publish -c Release -o ./publish
      
    - name: Deploy to EKS
      uses: aws-actions/amazon-eks-deploy@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: us-west-2
        cluster-name: cricket-app-cluster
        manifest-file: k8s-deployment.yaml

Scaling for 100M Users

1. CDN Strategy

  • Use multiple CDN providers (CloudFront, Akamai, etc.)

  • Implement multi-CDN failover strategy

  • Set up CDN analytics for traffic optimization

2. Database Scaling

  • Use read replicas for read-heavy operations

  • Implement database sharding by region/user

  • Use connection pooling to handle many connections

3. Caching Strategy

  • Implement Redis cluster with sharding

  • Use CDN caching for static assets

  • Implement client-side caching where appropriate

4. Monitoring and Alerting

  • Set up real-time monitoring of all services

  • Implement automated scaling policies

  • Create incident response procedures

Cost Optimization

  1. Use spot instances for non-critical workloads

  2. Implement auto-scaling to scale down during off-peak hours

  3. Use reserved instances for baseline capacity

  4. Implement data transfer optimization between regions

Security Considerations

  1. Implement DRM for video content

  2. Use HTTPS for all communications

  3. Implement DDoS protection (AWS Shield)

  4. Regular security audits and penetration testing

This architecture provides a robust foundation for a cricket streaming app serving 100M users, with scalability, reliability, and performance built into every layer. The .NET MAUI implementation provides a cross-platform solution with native performance characteristics.

Complete Guide: Building a Live Cricket Streaming App for 100M Users

Comprehensive guide to building a scalable live cricket streaming platform for 100M users, covering backend infrastructure, streaming techno...