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

Repository files navigation

OpenQoE

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

License Production Ready TypeScript Go PRs Welcome

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

Guarantee of p90 request latency of <=30ms for event insgestion under any load


πŸ“‹ 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 24+ event types βœ… Dash.js Ready / πŸ—οΈ Others WIP
Go Worker High-performance OTLP ingestion & processing βœ… Production Ready
Grafana Alloy Edge telemetry collector & processor βœ… 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
Distributed Tracing End-to-end tracing with Grafana Tempo βœ… Production Ready
Docker Stack Self-hosted Mimir + Loki + Tempo + Alloy βœ… Production Ready

✨ Features

SDK Capabilities

  • βœ… Multi-Player Support: HTML5, Video.js, HLS.js, Dash.js, Shaka Player
  • βœ… Dash.js Production Ready: Robust integration for MPEG-DASH
  • πŸ—οΈ WIP Adapters: Other players are in active development
  • βœ… Comprehensive Events: 24+ event types with full context capture
  • βœ… Privacy-First: SHA-256 hashing, configurable PII controls
  • βœ… Lightweight: ~10KB gzipped per adapter
  • βœ… TypeScript: Full type definitions included

Go Worker Features

  • βœ… OTLP Ingestion: Native support for OpenTelemetry protocol
  • βœ… High Concurrency: Built with Go for scalable event processing
  • βœ… Cardinality Governance: Automatic high-cardinality dimension management
  • βœ… Dual Destinations: Self-hosted or Grafana Cloud
  • βœ… Health Monitoring: Integrated health and stats endpoints

Observability Stack

  • βœ… Full OTLP Pipeline: Alloy -> Mimir/Loki/Tempo
  • βœ… Distributed Tracing: End-to-end visibility with Tempo
  • βœ… 4 Production Dashboards: VOD, Live, Quality, Impact Explorer
  • βœ… 18 Alert Rules: Critical quality and performance alerts
  • βœ… Self-Hosted: Complete Docker Compose stack (Mimir, Loki, Tempo, Alloy, Grafana)

πŸ—οΈ Architecture

graph TD
    subgraph "Your Application"
        SDK[OpenQoE SDK]
        P1["Dash.js,HLS.js, HTML5 - Ready"]
        P2["Others - WIP"]
        P1 -.-> SDK
        P2 -.-> SDK
    end

    SDK -- "HTTPS POST /v2/events" --> Worker[Go Worker]

    subgraph "Observability Pipeline"
        Worker -- "OTLP" --> Alloy[Grafana Alloy]
        Alloy -- "Metrics" --> Mimir[Grafana Mimir]
        Alloy -- "Logs" --> Loki[Grafana Loki]
        Alloy -- "Traces" --> Tempo[Grafana Tempo]
    end

    subgraph "Visualization"
        Mimir --- Grafana[Grafana]
        Loki --- Grafana
        Tempo --- Grafana
    end
Loading

Flow:

  1. SDK captures events from video players (Dash.js production ready)
  2. Events batched and sent to Go Worker (/v2/events)
  3. Worker validates and forwards via OTLP to Grafana Alloy
  4. Alloy routes data to Mimir (metrics), Loki (logs), and Tempo (traces)
  5. Grafana visualizes with pre-built dashboards and unified observability

1. Clone Repository

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

2. Start Observability Stack

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

# Verify all services are healthy
docker compose ps

3. Start Go Worker

cd worker

# Install dependencies & build
go mod download
go build -o openqoe-worker

# Configure environment (OTEL_URL=http://localhost:4317)
cp .env.example .env

# Run the worker
./openqoe-worker
# Worker available at http://localhost:8788

4. Integrate SDK (Dash.js Example)

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

  const qoe = new OpenQoE({
    orgId: "my-org",
    playerId: "my-website",
    endpointUrl: "http://localhost:8788/v2/events",
  });

  const player = dashjs.MediaPlayer().create();
  player.initialize(videoElement, url, true);

  qoe.attachPlayer("dashjs", player, {
    videoId: "video-123",
    videoTitle: "Production Stream",
  });
</script>

5. View Dashboards & Traces

  1. Open Grafana: localhost:3000 (admin/admin)
  2. Navigate to Dashboards β†’ OpenQoE folder
  3. Explore VOD Monitoring or Impact Explorer
  4. Use the Explore tab to view distributed traces in Tempo

OpenQoE v2 is ready! πŸš€


πŸ“š Documentation

Getting Started

Document Description
Deployment Guide Go Worker and Alloy Setup and deployment
API Reference V2 Event Schemas and OTLP details
SDK Integration Dash.js, HLS.js, HTML5 focus (other players WIP)
Architecture Distributed observability pipeline
Production Ready Production readiness report (Dash.js, HLS.js, HTML5)
  1. Open VOD Monitoring dashboard
  2. Play a video and watch metrics appear in real-time!

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

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 in .env
DESTINATION_TYPE=GrafanaCloud
GRAFANA_CLOUD_INSTANCE_ID=123456
GRAFANA_CLOUD_API_KEY=your-api-key

# Run worker
./openqoe-worker

Docs: Grafana Cloud Deployment


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

Best for: Distributed ingestion with on-premise storage

Combine regional Go workers for global ingestion with a central 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 Adapter Status
Dash.js DashJsAdapter βœ… Production Ready
HTML5 HTML5Adapter πŸ—οΈ Work In Progress
Video.js VideoJsAdapter πŸ—οΈ Work In Progress
HLS.js HlsJsAdapter πŸ—οΈ Work In Progress
Shaka Player ShakaAdapter πŸ—οΈ Work In Progress

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

Events Tracked (24+ 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/
β”œβ”€β”€ build
β”‚Β Β  β”œβ”€β”€ build.ninja
β”‚Β Β  β”œβ”€β”€ CMakeCache.txt
β”‚Β Β  β”œβ”€β”€ CMakeFiles
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ 3.28.3
β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ CMakeCXXCompiler.cmake
β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ CMakeDetermineCompilerABI_CXX.bin
β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ CMakeSystem.cmake
β”‚Β Β  β”‚Β Β  β”‚Β Β  └── CompilerIdCXX
β”‚Β Β  β”‚Β Β  β”‚Β Β      β”œβ”€β”€ a.out
β”‚Β Β  β”‚Β Β  β”‚Β Β      β”œβ”€β”€ CMakeCXXCompilerId.cpp
β”‚Β Β  β”‚Β Β  β”‚Β Β      └── tmp
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ cmake.check_cache
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ CMakeConfigureLog.yaml
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ OpenQoEWorker.dir
β”‚Β Β  β”‚Β Β  β”‚Β Β  └── src
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ pkgRedirects
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ rules.ninja
β”‚Β Β  β”‚Β Β  └── TargetDirectories.txt
β”‚Β Β  β”œβ”€β”€ cmake_install.cmake
β”‚Β Β  β”œβ”€β”€ compile_commands.json
β”‚Β Β  └── OpenQoEWorker
β”œβ”€β”€ compose.yaml
β”œβ”€β”€ docs
β”‚Β Β  β”œβ”€β”€ api-reference.md
β”‚Β Β  β”œβ”€β”€ architecture.md
β”‚Β Β  β”œβ”€β”€ contributing.md
β”‚Β Β  β”œβ”€β”€ data-model.md
β”‚Β Β  β”œβ”€β”€ deployment-checklist.md
β”‚Β Β  β”œβ”€β”€ deployment-guide.md
β”‚Β Β  β”œβ”€β”€ observability
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ dashboards.md
β”‚Β Β  β”‚Β Β  └── README.md
β”‚Β Β  β”œβ”€β”€ production-ready.md
β”‚Β Β  β”œβ”€β”€ sdk-integration.md
β”‚Β Β  └── technical-spec.md
β”œβ”€β”€ examples
β”‚Β Β  β”œβ”€β”€ dashjs-demo
β”‚Β Β  β”‚Β Β  └── index.html
β”‚Β Β  β”œβ”€β”€ DEMO_TEMPLATE.md
β”‚Β Β  β”œβ”€β”€ hlsjs-demo
β”‚Β Β  β”‚Β Β  └── index.html
β”‚Β Β  β”œβ”€β”€ html5-demo
β”‚Β Β  β”‚Β Β  └── index.html
β”‚Β Β  β”œβ”€β”€ README.md
β”‚Β Β  β”œβ”€β”€ shaka-demo
β”‚Β Β  β”‚Β Β  └── index.html
β”‚Β Β  └── videojs-demo
β”‚Β Β      └── index.html
β”œβ”€β”€ LICENSE
β”œβ”€β”€ observability
β”‚Β Β  β”œβ”€β”€ alloy
β”‚Β Β  β”‚Β Β  └── config.alloy
β”‚Β Β  β”œβ”€β”€ dashboards
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ impact-explorer.json
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ live-streaming.json
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ quality-delivery.json
β”‚Β Β  β”‚Β Β  └── vod-monitoring.json
β”‚Β Β  β”œβ”€β”€ grafana
β”‚Β Β  β”‚Β Β  └── provisioning
β”‚Β Β  β”‚Β Β      β”œβ”€β”€ dashboards
β”‚Β Β  β”‚Β Β      β”‚Β Β  └── dashboards.yml
β”‚Β Β  β”‚Β Β      └── datasources
β”‚Β Β  β”‚Β Β          └── datasources.yml
β”‚Β Β  β”œβ”€β”€ GRAFANA_DASHBOARDS.md
β”‚Β Β  β”œβ”€β”€ loki
β”‚Β Β  β”‚Β Β  └── loki-config.yaml
β”‚Β Β  β”œβ”€β”€ mimir
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ mimir-config.yml
β”‚Β Β  β”‚Β Β  └── runtime.yml
β”‚Β Β  β”œβ”€β”€ prometheus
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ prometheus.yml
β”‚Β Β  β”‚Β Β  └── rules
β”‚Β Β  β”‚Β Β      β”œβ”€β”€ load-rules.sh
β”‚Β Β  β”‚Β Β      β”œβ”€β”€ openqoe-alert-rules.yml
β”‚Β Β  β”‚Β Β      └── openqoe-recording-rules.yml
β”‚Β Β  β”œβ”€β”€ README.md
β”‚Β Β  └── tempo
β”‚Β Β      └── tempo-config.yaml
β”œβ”€β”€ openqoe-dev.code-workspace
β”œβ”€β”€ README.md
β”œβ”€β”€ sdk
β”‚Β Β  β”œβ”€β”€ jest.config.js
β”‚Β Β  β”œβ”€β”€ package.json
β”‚Β Β  β”œβ”€β”€ package-lock.json
β”‚Β Β  β”œβ”€β”€ README.md
β”‚Β Β  β”œβ”€β”€ rollup.config.js
β”‚Β Β  β”œβ”€β”€ src
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ adapters
β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ DashJsAdapter.ts
β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ HlsJsAdapter.ts
β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ HTML5Adapter.ts
β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ ShakaAdapter.ts
β”‚Β Β  β”‚Β Β  β”‚Β Β  └── VideoJsAdapter.ts
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ core
β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ BatchManager.ts
β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ EventCollector.ts
β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ QueueManager.ts
β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ RetryManager.ts
β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ SessionManager.ts
β”‚Β Β  β”‚Β Β  β”‚Β Β  └── Transport.ts
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ index.ts
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ OpenQoE.ts
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ types.ts
β”‚Β Β  β”‚Β Β  └── utils
β”‚Β Β  β”‚Β Β      β”œβ”€β”€ device.ts
β”‚Β Β  β”‚Β Β      β”œβ”€β”€ logger.ts
β”‚Β Β  β”‚Β Β      └── privacy.ts
β”‚Β Β  β”œβ”€β”€ tests
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ core
β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ BatchManager.test.ts
β”‚Β Β  β”‚Β Β  β”‚Β Β  └── SessionManager.test.ts
β”‚Β Β  β”‚Β Β  └── utils
β”‚Β Β  β”‚Β Β      └── privacy.test.ts
β”‚Β Β  └── tsconfig.json
β”œβ”€β”€ sonar-project.properties
β”œβ”€β”€ test
β”‚Β Β  β”œβ”€β”€ dashjs-test
β”‚Β Β  β”‚Β Β  └── index.html
β”‚Β Β  β”œβ”€β”€ hlsjs-test
β”‚Β Β  β”‚Β Β  └── index.html
β”‚Β Β  β”œβ”€β”€ html5-test
β”‚Β Β  β”‚Β Β  └── index.html
β”‚Β Β  β”œβ”€β”€ shaka-test
β”‚Β Β  β”‚Β Β  └── index.html
β”‚Β Β  └── videojs-test
β”‚Β Β      └── index.html
└── worker
    β”œβ”€β”€ compute
    β”‚Β Β  β”œβ”€β”€ events.go
    β”‚Β Β  β”œβ”€β”€ helpers.go
    β”‚Β Β  β”œβ”€β”€ metrics.go
    β”‚Β Β  β”œβ”€β”€ system_metrics.go
    β”‚Β Β  └── types.go
    β”œβ”€β”€ config
    β”‚Β Β  β”œβ”€β”€ auth.go
    β”‚Β Β  β”œβ”€β”€ cardinality.go
    β”‚Β Β  β”œβ”€β”€ config.go
    β”‚Β Β  β”œβ”€β”€ destination.go
    β”‚Β Β  β”œβ”€β”€ env.go
    β”‚Β Β  └── redis.go
    β”œβ”€β”€ data_structure
    β”‚Β Β  β”œβ”€β”€ pair.go
    β”‚Β Β  └── set.go
    β”œβ”€β”€ Dockerfile
    β”œβ”€β”€ go.mod
    β”œβ”€β”€ go.sum
    β”œβ”€β”€ main.go
    β”œβ”€β”€ middlewares
    β”‚Β Β  β”œβ”€β”€ auth.go
    β”‚Β Β  └── headers.go
    β”œβ”€β”€ otelservice
    β”‚Β Β  β”œβ”€β”€ setup.go
    β”‚Β Β  β”œβ”€β”€ tracer.go
    β”‚Β Β  └── types.go
    β”œβ”€β”€ pool
    β”‚Β Β  └── worker.go
    β”œβ”€β”€ README.md
    └── requesthandlers
        β”œβ”€β”€ controller.go
        β”œβ”€β”€ markdevice.go
        β”œβ”€β”€ requestvalidation.go
        └── types.go

Build SDK

cd sdk
npm install
npm run build
npm test

Run Worker Locally

cd worker
go build .
./worker
# Available at http://localhost:8788

Run Examples

# while in root level
npm install -g http-server
http-server
# 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 2026-27 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
  • Go - Low Latency highly concurrent native application with strict type safety
  • Grafana Alloy - Open Telemetry collector for Observability Signals
  • Grafana Mimir - Prometheus-compatible metrics storage
  • Grafana Loki - Log aggregation
  • Grafana Tempo - Trace Correleation
  • Grafana - Visualization platform
  • Docker - Containerization

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


πŸ“ˆ Project Status

Current Version: 2.0.0 Status: βœ… Dash.js, HLS.js, HTML5 Ready / πŸ—οΈ Core v2 In Beta Last Updated: January 2026

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

What's Production Ready

  • βœ… SDK for all 5 major web players
  • βœ… Low Latency
  • βœ… 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

Packages

No packages published

Contributors 3

  •  
  •  
  •