]>
Commit | Line | Data |
---|---|---|
fd3c2e87 C |
1 | import videojs from 'video.js' |
2 | import { PlaybackMetricCreate } from '../../../../../../shared/models' | |
3 | import { MetricsPluginOptions, PlayerMode, PlayerNetworkInfo } from '../../types' | |
4 | ||
5 | const Plugin = videojs.getPlugin('plugin') | |
6 | ||
7 | class MetricsPlugin extends Plugin { | |
8 | private readonly metricsUrl: string | |
9 | private readonly videoUUID: string | |
10 | private readonly mode: PlayerMode | |
11 | ||
12 | private downloadedBytesP2P = 0 | |
13 | private downloadedBytesHTTP = 0 | |
14 | private uploadedBytesP2P = 0 | |
15 | ||
16 | private resolutionChanges = 0 | |
17 | private errors = 0 | |
18 | ||
19 | private lastPlayerNetworkInfo: PlayerNetworkInfo | |
20 | ||
21 | private metricsInterval: any | |
22 | ||
23 | private readonly CONSTANTS = { | |
24 | METRICS_INTERVAL: 15000 | |
25 | } | |
26 | ||
27 | constructor (player: videojs.Player, options: MetricsPluginOptions) { | |
28 | super(player) | |
29 | ||
30 | this.metricsUrl = options.metricsUrl | |
31 | this.videoUUID = options.videoUUID | |
32 | this.mode = options.mode | |
33 | ||
34 | this.player.one('play', () => { | |
35 | this.runMetricsInterval() | |
36 | ||
37 | this.trackBytes() | |
38 | this.trackResolutionChange() | |
39 | this.trackErrors() | |
40 | }) | |
41 | } | |
42 | ||
43 | dispose () { | |
44 | if (this.metricsInterval) clearInterval(this.metricsInterval) | |
45 | } | |
46 | ||
47 | private runMetricsInterval () { | |
48 | this.metricsInterval = setInterval(() => { | |
49 | let resolution: number | |
50 | let fps: number | |
51 | ||
52 | if (this.mode === 'p2p-media-loader') { | |
53 | const level = this.player.p2pMediaLoader().getCurrentLevel() | |
54 | if (!level) return | |
55 | ||
56 | resolution = Math.min(level.height || 0, level.width || 0) | |
57 | ||
58 | const framerate = level?.attrs['FRAME-RATE'] | |
59 | fps = framerate | |
60 | ? parseInt(framerate, 10) | |
61 | : undefined | |
62 | } else { // webtorrent | |
63 | const videoFile = this.player.webtorrent().getCurrentVideoFile() | |
64 | if (!videoFile) return | |
65 | ||
66 | resolution = videoFile.resolution.id | |
67 | fps = videoFile.fps | |
68 | } | |
69 | ||
70 | const body: PlaybackMetricCreate = { | |
71 | resolution, | |
72 | fps, | |
73 | ||
74 | playerMode: this.mode, | |
75 | ||
76 | resolutionChanges: this.resolutionChanges, | |
77 | ||
78 | errors: this.errors, | |
79 | ||
80 | downloadedBytesP2P: this.downloadedBytesP2P, | |
81 | downloadedBytesHTTP: this.downloadedBytesHTTP, | |
82 | ||
83 | uploadedBytesP2P: this.uploadedBytesP2P, | |
84 | ||
85 | videoId: this.videoUUID | |
86 | } | |
87 | ||
88 | this.resolutionChanges = 0 | |
89 | ||
90 | this.downloadedBytesP2P = 0 | |
91 | this.downloadedBytesHTTP = 0 | |
92 | ||
93 | this.uploadedBytesP2P = 0 | |
94 | ||
95 | this.errors = 0 | |
96 | ||
97 | const headers = new Headers({ 'Content-type': 'application/json; charset=UTF-8' }) | |
98 | ||
99 | return fetch(this.metricsUrl, { method: 'POST', body: JSON.stringify(body), headers }) | |
100 | }, this.CONSTANTS.METRICS_INTERVAL) | |
101 | } | |
102 | ||
103 | private trackBytes () { | |
104 | this.player.on('p2pInfo', (_event, data: PlayerNetworkInfo) => { | |
105 | this.downloadedBytesHTTP += data.http.downloaded - (this.lastPlayerNetworkInfo?.http.downloaded || 0) | |
106 | this.downloadedBytesP2P += data.p2p.downloaded - (this.lastPlayerNetworkInfo?.p2p.downloaded || 0) | |
107 | ||
108 | this.uploadedBytesP2P += data.p2p.uploaded - (this.lastPlayerNetworkInfo?.p2p.uploaded || 0) | |
109 | ||
110 | this.lastPlayerNetworkInfo = data | |
111 | }) | |
112 | } | |
113 | ||
114 | private trackResolutionChange () { | |
115 | this.player.on('engineResolutionChange', () => { | |
116 | this.resolutionChanges++ | |
117 | }) | |
118 | } | |
119 | ||
120 | private trackErrors () { | |
121 | this.player.on('error', () => { | |
122 | this.errors++ | |
123 | }) | |
124 | } | |
125 | } | |
126 | ||
127 | videojs.registerPlugin('metrics', MetricsPlugin) | |
128 | export { MetricsPlugin } |