Skip to content

Open-source video Quality of Experience (QoE) monitoring platform. JavaScript SDK for 5 players, Cloudflare Worker ingestion, and production-ready Grafana dashboards. Monitor VST, rebuffering, errors, and engagement metrics at scale.

License

Notifications You must be signed in to change notification settings

openqoe/openqoe-dev

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

10 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

OpenQoE

Open-Source Video Quality of Experience (QoE) Monitoring Platform

License Production Ready TypeScript PRs Welcome

Production-grade video quality monitoring for web video players with comprehensive business and technical metrics, accurate percentile calculations, and real-time alerting.

This project needs active contribution from the experts in video tech, players and opensource developers. Let's build it together


πŸ“‹ Table of Contents


🎯 Overview

OpenQoE is a complete, production-ready observability platform for video streaming that helps you:

  • Monitor Quality: Track video startup time, rebuffering, errors, and playback quality
  • Understand Engagement: Measure watch time, completion rates, and viewer behavior
  • Optimize Performance: Identify bottlenecks with P50/P95/P99 percentile analysis
  • Alert Proactively: Get notified when quality degrades or business metrics drop
  • Scale Globally: Deploy on Cloudflare's edge network or self-host

What's Included

Component Description Status
JavaScript SDK 5 player adapters capturing 12 event types βœ… Production Ready
Cloudflare Worker Edge ingestion with validation & routing βœ… Production Ready
Grafana Dashboards 4 comprehensive dashboards (58 panels total) βœ… Production Ready
Recording Rules 25 pre-aggregated metrics for performance βœ… Production Ready
Alert Rules 18 production-ready alerts βœ… Production Ready
Docker Stack Self-hosted Mimir + Loki + Grafana βœ… Production Ready

✨ Features

SDK Capabilities

  • βœ… Multi-Player Support: HTML5, Video.js, HLS.js, dash.js, Shaka Player
  • βœ… Comprehensive Events: 12 event types with full context capture
  • βœ… Privacy-First: SHA-256 hashing, configurable PII controls
  • βœ… Offline Support: LocalStorage-backed queue with exponential backoff retry
  • βœ… Lightweight: ~10KB gzipped per adapter
  • βœ… TypeScript: Full type definitions included
  • βœ… Framework Agnostic: Works with React, Vue, Angular, vanilla JS

Worker Features

  • βœ… Histogram Metrics: Accurate P50/P95/P99 percentile calculations
  • βœ… Dual Destinations: Self-hosted (Mimir/Loki) or Grafana Cloud
  • βœ… Authentication: Secure header-based API key auth
  • βœ… Validation: Comprehensive event schema validation with whitelisting
  • βœ… Cardinality Governance: Automatic high-cardinality dimension management
  • βœ… Timeout Protection: 10-second timeout on all HTTP requests
  • βœ… Configuration Validation: Fails fast with clear error messages
  • βœ… Edge Deployment: Runs on Cloudflare's global network

Observability Stack

  • βœ… 4 Production Dashboards: VOD, Live Streaming, Quality & Delivery, Impact Explorer
  • βœ… 58 Dashboard Panels: Comprehensive business + technical coverage
  • βœ… 25 Recording Rules: Pre-aggregated metrics for 10-50x faster queries
  • βœ… 18 Alert Rules: Critical quality, business impact, performance, live streaming alerts
  • βœ… Histogram Support: Accurate percentile calculations (not approximations)
  • βœ… Multi-Tenancy: Full Grafana Cloud support with X-Scope-OrgID header
  • βœ… Self-Hosted: Complete Docker Compose stack included

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      Your Application                     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚ HTML5   β”‚  β”‚Video.js β”‚  β”‚ HLS.js  β”‚  β”‚dash.js/ β”‚    β”‚
β”‚  β”‚ Player  β”‚  β”‚ Player  β”‚  β”‚ Player  β”‚  β”‚  Shaka  β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜    β”‚
β”‚       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β”‚
β”‚                         β”‚                                 β”‚
β”‚                 β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”                       β”‚
β”‚                 β”‚  OpenQoE SDK   β”‚                       β”‚
β”‚                 β”‚  (12 events)   β”‚                       β”‚
β”‚                 β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                          β”‚ HTTPS POST /v1/events
                          β–Ό
         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
         β”‚   Cloudflare Worker (Edge)     β”‚
         β”‚  β€’ Authentication              β”‚
         β”‚  β€’ Validation & Sanitization   β”‚
         β”‚  β€’ Cardinality Governance      β”‚
         β”‚  β€’ Transform to Histograms     β”‚
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                  β”‚               β”‚
        Metrics   β”‚               β”‚   Logs
                  β–Ό               β–Ό
      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
      β”‚    Mimir     β”‚   β”‚     Loki     β”‚
      β”‚  (Metrics)   β”‚   β”‚    (Logs)    β”‚
      β”‚ Prometheus-  β”‚   β”‚ Log          β”‚
      β”‚ compatible   β”‚   β”‚ Aggregation  β”‚
      β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚                  β”‚
             β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      β–Ό
           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
           β”‚      Grafana       β”‚
           β”‚  β€’ 4 Dashboards    β”‚
           β”‚  β€’ 58 Panels       β”‚
           β”‚  β€’ Recording Rules β”‚
           β”‚  β€’ Alert Rules     β”‚
           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Flow:

  1. SDK captures events from video players (all major web players supported)
  2. Events batched and sent to Cloudflare Worker edge endpoint
  3. Worker validates, enriches, and transforms to histogram metrics
  4. Metrics sent to Mimir (Prometheus-compatible), logs to Loki
  5. Grafana visualizes with pre-built dashboards and alerts

πŸš€ Quick Start

Prerequisites

  • Node.js 18+
  • Docker & Docker Compose v2
  • Cloudflare account (for worker deployment)
  • OR Grafana Cloud account (alternative to self-hosting)

1. Clone Repository

git clone https://github.com/openqoe/openqoe-dev.git
cd openqoe

2. Start Observability Stack

# Start Mimir, Loki, and Grafana
docker compose up -d

# Verify all services are healthy
docker compose ps

# Access Grafana at http://localhost:3000 (admin/admin)

3. Load Recording & Alert Rules

cd observability/prometheus/rules

# Load recording rules
./load-rules.sh http://localhost:9009

# Load alert rules
curl -X POST \
  "http://localhost:9009/prometheus/config/v1/rules/anonymous" \
  -H "Content-Type: application/yaml" \
  --data-binary "@openqoe-alert-rules.yml"

4. Deploy Worker (Local Development)

cd worker

# Install dependencies
npm install

# Create local config
cp .dev.vars.example .dev.vars

# Edit .dev.vars with localhost URLs:
# MIMIR_URL=http://localhost:9009/api/v1/push
# LOKI_URL=http://localhost:3100/loki/api/v1/push

# Run locally
npm run dev
# Worker available at http://localhost:8787

5. Integrate SDK

<!DOCTYPE html>
<html>
<head>
  <title>Video Player Example</title>
</head>
<body>
  <video id="myVideo" controls width="640">
    <source src="https://example.com/video.mp4" type="video/mp4">
  </video>

  <script type="module">
    import { OpenQoE } from './sdk/dist/index.js';

    // Initialize SDK
    const qoe = new OpenQoE({
      orgId: 'my-org',
      playerId: 'my-website',
      endpointUrl: 'http://localhost:8787/v1/events',
      debug: true
    });

    // Attach to player
    const video = document.getElementById('myVideo');
    qoe.attachPlayer('html5', video, {
      videoId: 'demo-video-123',
      videoTitle: 'Demo Video'
    });

    // SDK will now automatically track all events!
  </script>
</body>
</html>

6. View Dashboards

  1. Open Grafana: http://localhost:3000
  2. Navigate to Dashboards β†’ OpenQoE folder
  3. Open VOD Monitoring dashboard
  4. Play a video and watch metrics appear in real-time!

That's it! Your video QoE monitoring is now live. πŸŽ‰


πŸ“š Documentation

Getting Started

Document Description
Deployment Guide Complete deployment instructions for all environments
Deployment Checklist Step-by-step validation checklist
SDK Integration Guide SDK setup for all 5 supported players
API Reference Complete API documentation and event schemas

Architecture & Design

Document Description
Architecture Overview System architecture and component design
Technical Specification Detailed technical specifications
Data Model Event schemas and data structures
Production Ready Status Complete production readiness report

Observability

Document Description
Observability README Stack overview, metrics, queries, troubleshooting
Dashboard Documentation Dashboard specifications and panel details
Recording Rules 25 pre-aggregated metrics
Alert Rules 18 production alerts

Component READMEs

Component README
SDK sdk/README.md
Worker worker/README.md
Examples examples/README.md

🌍 Deployment Options

Option 1: Self-Hosted (Docker)

Best for: On-premise deployments, full control, data sovereignty

# Start complete stack
docker compose up -d

# Configure worker for localhost
cd worker && npm run dev

Includes: Mimir (metrics), Loki (logs), Grafana (dashboards)

Docs: Self-Hosted Deployment


Option 2: Grafana Cloud

Best for: Managed service, zero infrastructure, global scale

# Configure worker with Grafana Cloud credentials
cd worker
wrangler secret put GRAFANA_CLOUD_INSTANCE_ID
wrangler secret put GRAFANA_CLOUD_API_KEY
wrangler secret put GRAFANA_CLOUD_METRICS_URL
wrangler secret put GRAFANA_CLOUD_LOGS_URL

# Deploy to Cloudflare
wrangler deploy

Docs: Grafana Cloud Deployment


Option 3: Hybrid (Self-Hosted + Cloudflare Worker)

Best for: Edge ingestion with on-premise storage

Combine Cloudflare Worker for global edge ingestion with self-hosted observability stack.

Docs: Hybrid Deployment


πŸ“Š Metrics & Dashboards

Dashboard Overview

Dashboard Panels Purpose Key Metrics
VOD Monitoring 21 Real-time VOD quality VST, rebuffering, completion, quartiles
Live Streaming 11 Live event monitoring Concurrent viewers, join time, geographic
Quality & Delivery 12 Technical deep-dive Seek latency, dropped frames, ABR
Impact Explorer 14 Business analysis Watch time, engagement, revenue

Key Metrics Captured

Business Metrics:

  • Total views, completion rate, watch time
  • Revenue impact calculations
  • Engagement by quartile (25/50/75/100%)
  • Content performance comparison

Technical Metrics:

  • Video Startup Time (P50/P95/P99 via histograms)
  • Rebuffer rate, duration, and frequency
  • Seek latency and performance
  • Error rates by type and family
  • Bitrate distribution and ABR behavior
  • Dropped frames and rendering quality
  • Resolution distribution (360p-8K)
  • Buffer health

Live Streaming:

  • Concurrent viewers (real-time)
  • Join time (P95)
  • Geographic distribution
  • Viewer drop detection

Histogram Metrics

OpenQoE uses true histograms (not gauges) for accurate percentile calculations:

# Accurate P95 Video Startup Time
histogram_quantile(0.95,
  sum(rate(openqoe_video_startup_seconds_bucket[5m])) by (le)
)

# Using pre-aggregated recording rule (10-50x faster)
openqoe:video_startup_seconds:p95

Histogram buckets configured:

  • VST: [0.5, 1, 2, 3, 5, 10, 15, 30] seconds
  • Rebuffer Duration: [0.5, 1, 2, 3, 5, 10, 30] seconds
  • Seek Latency: [0.1, 0.25, 0.5, 1, 2, 5] seconds

🎨 Supported Players

Player Version Adapter Events Status
HTML5 Video Native HTML5Adapter 11/12* βœ… Production
Video.js 7.0+ VideoJsAdapter 12/12 βœ… Production
HLS.js 1.0+ HlsJsAdapter 12/12 βœ… Production
dash.js 4.0+ DashJsAdapter 12/12 βœ… Production
Shaka Player 4.0+ ShakaAdapter 12/12 βœ… Production

*HTML5 doesn't support quality_change events (no native ABR)

Events Tracked (12 Total)

Event Description Business Value
playerready Player initialized Time to interactive
viewstart Video load started View funnel entry
playing Playback started Video Startup Time (VST)
pause User paused Engagement analysis
seek User scrubbed Navigation behavior
stall_start Buffering started Rebuffering detection
stall_end Buffering ended Rebuffer duration
ended Video completed Completion rate
error Playback error Error tracking
quartile 25/50/75/100% reached Drop-off analysis
heartbeat Periodic update (10s) Watch time tracking
quality_change ABR switch Bitrate adaptation

πŸ› οΈ Development

Project Structure

openqoe/
β”œβ”€β”€ sdk/                          # JavaScript SDK
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ adapters/            # Player adapters (5 total)
β”‚   β”‚   β”œβ”€β”€ core/                # Core SDK modules
β”‚   β”‚   β”‚   β”œβ”€β”€ EventCollector.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ SessionManager.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ BatchManager.ts
β”‚   β”‚   β”‚   └── Transport.ts
β”‚   β”‚   β”œβ”€β”€ utils/               # Privacy, device detection
β”‚   β”‚   └── OpenQoE.ts           # Main SDK class
β”‚   β”œβ”€β”€ dist/                    # Built bundles
β”‚   └── package.json
β”‚
β”œβ”€β”€ worker/                       # Cloudflare Worker
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ index.ts             # Main handler
β”‚   β”‚   β”œβ”€β”€ config.ts            # Configuration
β”‚   β”‚   β”œβ”€β”€ destinations.ts      # Destination manager
β”‚   β”‚   β”œβ”€β”€ validation.ts        # Event validation
β”‚   β”‚   β”œβ”€β”€ prometheus.ts        # Histogram metrics
β”‚   β”‚   β”œβ”€β”€ loki.ts              # Log transformation
β”‚   β”‚   β”œβ”€β”€ cardinality.ts       # Cardinality governance
β”‚   β”‚   └── auth.ts              # Authentication
β”‚   β”œβ”€β”€ wrangler.toml            # Worker configuration
β”‚   β”œβ”€β”€ validate.sh              # Pre-deployment validation
β”‚   └── package.json
β”‚
β”œβ”€β”€ observability/                # Observability stack
β”‚   β”œβ”€β”€ dashboards/              # 4 Grafana dashboards (58 panels)
β”‚   β”‚   β”œβ”€β”€ vod-monitoring.json
β”‚   β”‚   β”œβ”€β”€ live-streaming.json
β”‚   β”‚   β”œβ”€β”€ quality-delivery.json
β”‚   β”‚   └── impact-explorer.json
β”‚   β”œβ”€β”€ prometheus/
β”‚   β”‚   └── rules/
β”‚   β”‚       β”œβ”€β”€ openqoe-recording-rules.yml  # 25 rules
β”‚   β”‚       β”œβ”€β”€ openqoe-alert-rules.yml      # 18 alerts
β”‚   β”‚       └── load-rules.sh
β”‚   β”œβ”€β”€ mimir/
β”‚   β”‚   β”œβ”€β”€ mimir-config.yml
β”‚   β”‚   └── runtime.yml
β”‚   β”œβ”€β”€ loki/
β”‚   β”‚   └── loki-config.yml
β”‚   └── grafana/
β”‚       └── provisioning/
β”‚
β”œβ”€β”€ examples/                     # Example/demo pages for all 5 players
β”œβ”€β”€ docs/                         # Documentation
β”‚   β”œβ”€β”€ deployment-guide.md
β”‚   β”œβ”€β”€ deployment-checklist.md
β”‚   β”œβ”€β”€ production-ready.md
β”‚   β”œβ”€β”€ sdk-integration.md
β”‚   β”œβ”€β”€ api-reference.md
β”‚   β”œβ”€β”€ architecture.md
β”‚   β”œβ”€β”€ data-model.md
β”‚   β”œβ”€β”€ technical-spec.md
β”‚   β”œβ”€β”€ contributing.md
β”‚   └── observability/
β”‚       β”œβ”€β”€ README.md
β”‚       └── dashboards.md
β”œβ”€β”€ compose.yml                   # Docker Compose stack
β”œβ”€β”€ LICENSE                       # Apache 2.0
└── README.md                     # This file

Build SDK

cd sdk
npm install
npm run build
npm test

Run Worker Locally

cd worker
npm install
npm run dev
# Available at http://localhost:8787

Type Check

npm run type-check

Run Examples

cd examples
npx http-server -p 8080
# Open http://localhost:8080

🀝 Contributing

We welcome contributions! Whether it's:

  • πŸ› Bug reports
  • ✨ Feature requests
  • πŸ“ Documentation improvements
  • πŸ”§ Code contributions

Please read our Contributing Guide for guidelines.

Quick Contribution Steps

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Commit with clear messages (git commit -m 'Add amazing feature')
  5. Push to your branch (git push origin feature/amazing-feature)
  6. Open a Pull Request

πŸ“„ License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

Copyright 2024 OpenQoE Contributors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

πŸ’¬ Support

Community Support

Getting Help

  1. Check the documentation
  2. Search existing issues
  3. Check troubleshooting guide
  4. Ask in Discussions

🌟 Acknowledgments

OpenQoE is built with:

  • TypeScript - Type-safe development
  • Cloudflare Workers - Edge compute platform
  • Grafana Mimir - Prometheus-compatible metrics storage
  • Grafana Loki - Log aggregation
  • Grafana - Visualization platform
  • Docker - Containerization

Inspired by commercial QoE monitoring solutions for continuous improvement and industry best practices.


πŸ“ˆ Project Status

Current Version: 1.0.0 Status: βœ… Production Ready Last Updated: November 2024

See docs/production-ready.md for complete production readiness report.

What's Production Ready

  • βœ… SDK for all 5 major web players
  • βœ… Cloudflare Worker with histogram support
  • βœ… 4 comprehensive Grafana dashboards (58 panels)
  • βœ… 25 recording rules for performance
  • βœ… 18 production-ready alerts
  • βœ… Self-hosted Docker stack
  • βœ… Grafana Cloud support
  • βœ… Complete documentation

Roadmap

Phase 2 (Optional):

  • Worker Health Dashboard (pipeline monitoring)
  • Advanced cardinality analytics
  • Custom metric extensions
  • Load testing framework

πŸ™ Star Us!

If you find OpenQoE useful, please consider giving us a star ⭐ on GitHub. It helps others discover the project!

Star on GitHub


Made with ❀️ by the OpenQoE Community

About

Open-source video Quality of Experience (QoE) monitoring platform. JavaScript SDK for 5 players, Cloudflare Worker ingestion, and production-ready Grafana dashboards. Monitor VST, rebuffering, errors, and engagement metrics at scale.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Contributors 3

  •  
  •  
  •