Skip to content
Merged
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
2 changes: 2 additions & 0 deletions src/debugger/chronicle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type CurrentLatency = CreateMetric<"current-latency", number>
type CurrentUrl = CreateMetric<"current-url", string>
type Duration = CreateMetric<"duration", number>
type FramesDropped = CreateMetric<"frames-dropped", number>
type FramesTotal = CreateMetric<"frames-total", number>
type InitialPlaybackTime = CreateMetric<"initial-playback-time", [time: number, timeline: Timeline]>
type MediaElementEnded = CreateMetric<"ended", HTMLMediaElement["ended"]>
type MediaElementPaused = CreateMetric<"paused", HTMLMediaElement["paused"]>
Expand Down Expand Up @@ -73,6 +74,7 @@ export type Metric =
| CurrentUrl
| Duration
| FramesDropped
| FramesTotal
| InitialPlaybackTime
| MediaElementEnded
| MediaElementPaused
Expand Down
12 changes: 6 additions & 6 deletions src/debugger/debugviewcontroller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe("Debug View", () => {
controller.showView()

chronicle.appendMetric("buffer-length", 0)
chronicle.appendMetric("frames-dropped", 4)
chronicle.appendMetric("auto-resume", 4)
chronicle.appendMetric("duration", 30)

controller.addEntries(chronicle.retrieve())
Expand All @@ -31,7 +31,7 @@ describe("Debug View", () => {
expect.objectContaining({
static: [
{ id: "buffer-length", key: "buffer length", value: 0 },
{ id: "frames-dropped", key: "frames dropped", value: 4 },
{ id: "auto-resume", key: "auto resume", value: 4 },
{ id: "duration", key: "duration", value: 30 },
],
})
Expand Down Expand Up @@ -254,22 +254,22 @@ describe("Debug View", () => {

const chronicle = new Chronicle()

chronicle.appendMetric("frames-dropped", 0)
chronicle.appendMetric("auto-resume", 0)

jest.advanceTimersByTime(500)

chronicle.appendMetric("frames-dropped", 1)
chronicle.appendMetric("auto-resume", 1)

jest.advanceTimersByTime(4500)

chronicle.appendMetric("frames-dropped", 4)
chronicle.appendMetric("auto-resume", 4)

controller.addEntries(chronicle.retrieve())

jest.advanceTimersToNextTimer()

expect(DebugView.render).toHaveBeenCalledWith(
expect.objectContaining({ static: [{ id: "frames-dropped", key: "frames dropped", value: 4 }] })
expect.objectContaining({ static: [{ id: "auto-resume", key: "auto resume", value: 4 }] })
)
})

Expand Down
53 changes: 52 additions & 1 deletion src/debugger/debugviewcontroller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,22 @@ type MaxBitrate = {
data: Record<MediaKinds, number>
}

type FrameKind = Extends<MetricKind, "frames-dropped" | "frames-total">

type Frames = {
category: "union"
kind: "frames"
data: {
total?: number
dropped?: number
}
}

type DynamicEntry = TimestampedMessage | TimestampedTrace | Timestamp

type StaticEntry =
| Exclude<TimestampedMetric, MetricForKind<MediaElementStateKind | AudioQualityKind | VideoQualityKind>>
| Exclude<TimestampedMetric, MetricForKind<MediaElementStateKind | AudioQualityKind | VideoQualityKind | FrameKind>>
| Timestamped<Frames>
| Timestamped<MediaElementState>
| Timestamped<AudioQuality>
| Timestamped<VideoQuality>
Expand Down Expand Up @@ -107,6 +119,32 @@ class DebugViewController {
private dynamicEntries: DynamicEntry[] = []
private latestMetricByKey: Partial<Record<StaticEntryKind, StaticEntry>> = {}

private isFrameStat(metric: TimestampedMetric): metric is Timestamped<MetricForKind<FrameKind>> {
const { kind } = metric
return kind === "frames-dropped" || kind === "frames-total"
}

private mergeFrameStat(entry: Timestamped<MetricForKind<FrameKind>>): Timestamped<Frames> {
const prevEntry: Frames =
this.latestMetricByKey.frames == null
? { category: "union", kind: "frames", data: {} }
: (this.latestMetricByKey.frames as Frames)

const { sessionTime, currentElementTime, kind: metricKind, data: metricData } = entry

const keyForKind: Record<FrameKind, string> = {
"frames-dropped": "dropped",
"frames-total": "total",
}

return {
...prevEntry,
sessionTime,
currentElementTime,
data: { ...prevEntry.data, [keyForKind[metricKind]]: metricData },
}
}

private isMediaState(metric: TimestampedMetric): metric is Timestamped<MetricForKind<MediaElementStateKind>> {
const { kind } = metric
const mediaStateMetrics = ["ended", "paused", "playback-rate", "ready-state", "seeking"]
Expand Down Expand Up @@ -219,6 +257,11 @@ class DebugViewController {

switch (category) {
case EntryCategory.METRIC:
if (this.isFrameStat(entry)) {
this.cacheStaticEntry(this.mergeFrameStat(entry))
return
}

if (this.isMediaState(entry)) {
this.cacheStaticEntry(this.mergeMediaState(entry))
return
Expand Down Expand Up @@ -477,6 +520,14 @@ class DebugViewController {
return `${bitratePart} kbps`
}

if (kind === "frames") {
if (data.total == null) {
return null
}

return `${(data.dropped ?? (0 / data.total) * 100).toFixed(2)}% dropped (${data.dropped}/${data.total})`
}

return data.join(", ")
}

Expand Down
Loading