Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.1.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- Added the `Metrics` API, accessible through `player.metrics`, with `currentBandwidthEstimate` returning the player's estimated available bandwidth in bits per second. On iOS/tvOS this value is only reported for THEOlive/HESP streams.

## [11.6.0]

### Added
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ This section gives an overview of features, limitations and known issues:
- [Fullscreen presentation](./doc/fullscreen.md)
- [Media Control](./doc/mediacontrol.md)
- [Media Caching](./doc/media-caching.md)
- [Metrics](./doc/metrics.md)
- [Migrating to THEOplayer 9.x](./doc/migrating-to-react-native-theoplayer-9.md)
- [Migrating to THEOplayer 10.x🔥](./doc/migrating-to-react-native-theoplayer-10.md)
- [Millicast](./doc/millicast.md)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.theoplayer.drm.ContentProtectionModule
import com.theoplayer.cast.CastModule
import com.theoplayer.broadcast.EventBroadcastModule
import com.theoplayer.media.MediaControlModule
import com.theoplayer.metrics.MetricsModule
import com.theoplayer.player.PlayerModule
import com.theoplayer.theolive.THEOliveModule
import com.theoplayer.theoads.THEOadsModule
Expand All @@ -28,6 +29,7 @@ class ReactTHEOplayerPackage : BaseReactPackage() {
THEOliveModule.NAME -> THEOliveModule(reactContext)
THEOadsModule.NAME -> THEOadsModule(reactContext)
MediaControlModule.NAME -> MediaControlModule(reactContext)
MetricsModule.NAME -> MetricsModule(reactContext)
else -> null
}
}
Expand All @@ -48,6 +50,7 @@ class ReactTHEOplayerPackage : BaseReactPackage() {
THEOliveModule.NAME to THEOliveModule.INFO,
THEOadsModule.NAME to THEOadsModule.INFO,
MediaControlModule.NAME to MediaControlModule.INFO,
MetricsModule.NAME to MetricsModule.INFO,
)
}
}
Expand Down
37 changes: 37 additions & 0 deletions android/src/main/java/com/theoplayer/metrics/MetricsModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.theoplayer.metrics

import com.facebook.react.bridge.*
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.module.model.ReactModuleInfo
import com.theoplayer.ReactTHEOplayerView
import com.theoplayer.util.ViewResolver

@Suppress("unused")
@ReactModule(name = MetricsModule.NAME)
class MetricsModule(context: ReactApplicationContext) : ReactContextBaseJavaModule(context) {
companion object {
const val NAME = "THEORCTMetricsModule"
val INFO = ReactModuleInfo(
name = NAME,
className = NAME,
canOverrideExistingModule = false,
needsEagerInit = false,
isCxxModule = false,
isTurboModule = false,
)
}

private val viewResolver: ViewResolver = ViewResolver(context)

override fun getName(): String {
return NAME
}

// The bandwidth, in bits per second, that the player estimates is currently available.
@ReactMethod
fun currentBandwidthEstimate(tag: Int, promise: Promise) {
viewResolver.resolveViewByTag(tag) { view: ReactTHEOplayerView? ->
promise.resolve(view?.player?.metrics?.currentBandwidthEstimate ?: 0.0)
}
}
}
45 changes: 45 additions & 0 deletions doc/metrics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Metrics

## Overview

The [Metrics API](../src/api/metrics/MetricsAPI.ts) exposes playback metrics gathered by the player. It is available on the [THEOplayer API](../src/api/player/THEOplayer.ts) through `player.metrics`.

Metrics are **poll-based**: there is no change event, so you read a value on demand (for example on an interval, or piggy-backing on an existing event such as a time update).

## Current bandwidth estimate

`player.metrics.currentBandwidthEstimate()` returns the bandwidth, in **bits per second**, that the player estimates is currently available. This is the value the player uses to make adaptive bitrate (ABR) decisions.

```tsx
const onPlayerReady = (player: THEOplayer) => {
// Poll the estimate every second.
setInterval(async () => {
const bps = await player.metrics.currentBandwidthEstimate();
console.log(`Estimated bandwidth: ${bps} bps`);
}, 1000);
};

<THEOplayerView
config={playerConfig}
onPlayerReady={onPlayerReady}
/>
```

> **Note:** A value of `0` means the estimate is **not available yet** (e.g. before playback, after a reset,
> or on a platform/source that does not populate it — see below). It does **not** mean the available
> bandwidth is literally zero.

## Platform specifics

The access path (`player.metrics.currentBandwidthEstimate()`, in bits/s) is identical on every platform,
but the *behaviour* is not uniform:

| Platform | Populated for | Value when unsupported |
|-----------|--------------------------------------------|--------------------------------------------------------|
| Android | All streams, via the Media3/ExoPlayer estimate (HLS, DASH, SmoothStreaming, progressive) | `0.0` when no playback backend is attached |
| Web | All streams driven by THEOplayer's MSE/ABR pipeline (HLS, DASH, HESP) | `0` during native HTML5 playback |
| iOS/tvOS | THEOlive/HESP streams **only** in practice | `0` for regular `AVPlayer` playback (HLS, MP4) |

- On **iOS/tvOS** the value is only meaningful for THEOlive/HESP sources. For ordinary HLS/MP4 played it stays `0`.
- On **Android** and **Web** the estimate is reported for regular adaptive streams as well; it is not
HESP-specific.
Loading
Loading