@mattebox/player-diagnostics 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/cdn/mattebox-player-diagnostics.min.js +1 -124
  2. package/dist/charts.d.ts.map +1 -1
  3. package/dist/charts.js +356 -392
  4. package/dist/charts.js.map +1 -1
  5. package/dist/dom.d.ts +8 -0
  6. package/dist/dom.d.ts.map +1 -0
  7. package/dist/dom.js +15 -0
  8. package/dist/dom.js.map +1 -0
  9. package/dist/element.d.ts.map +1 -1
  10. package/dist/element.js +631 -659
  11. package/dist/element.js.map +1 -1
  12. package/dist/es2015/_virtual/{_@oxc-project_runtime@0.150.0 → _@oxc-project_runtime@0.152.0}/helpers/esm/asyncToGenerator.js +1 -1
  13. package/dist/es2015/_virtual/{_@oxc-project_runtime@0.150.0 → _@oxc-project_runtime@0.152.0}/helpers/esm/defineProperty.js +1 -1
  14. package/dist/es2015/_virtual/{_@oxc-project_runtime@0.150.0 → _@oxc-project_runtime@0.152.0}/helpers/esm/objectSpread2.js +1 -1
  15. package/dist/es2015/_virtual/{_@oxc-project_runtime@0.150.0 → _@oxc-project_runtime@0.152.0}/helpers/esm/toPrimitive.js +1 -1
  16. package/dist/es2015/_virtual/{_@oxc-project_runtime@0.150.0 → _@oxc-project_runtime@0.152.0}/helpers/esm/toPropertyKey.js +1 -1
  17. package/dist/es2015/_virtual/{_@oxc-project_runtime@0.150.0 → _@oxc-project_runtime@0.152.0}/helpers/esm/typeof.js +1 -1
  18. package/dist/es2015/charts.js +2 -1
  19. package/dist/es2015/dom.js +13 -0
  20. package/dist/es2015/element.js +23 -10
  21. package/dist/es2015/report.js +6 -0
  22. package/dist/es2015/style.js +1 -133
  23. package/dist/es2015/support.js +2 -2
  24. package/dist/es2015/trace.js +1 -1
  25. package/dist/format.js +26 -31
  26. package/dist/format.js.map +1 -1
  27. package/dist/host.js +28 -30
  28. package/dist/host.js.map +1 -1
  29. package/dist/icon.js +43 -39
  30. package/dist/icon.js.map +1 -1
  31. package/dist/index.d.ts +1 -1
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +15 -14
  34. package/dist/index.js.map +1 -1
  35. package/dist/report.d.ts +12 -0
  36. package/dist/report.d.ts.map +1 -1
  37. package/dist/report.js +135 -119
  38. package/dist/report.js.map +1 -1
  39. package/dist/sampler.js +187 -199
  40. package/dist/sampler.js.map +1 -1
  41. package/dist/style.d.ts +1 -9
  42. package/dist/style.d.ts.map +1 -1
  43. package/dist/style.js +4 -132
  44. package/dist/style.js.map +1 -1
  45. package/dist/support.js +304 -215
  46. package/dist/support.js.map +1 -1
  47. package/dist/trace.js +80 -81
  48. package/dist/trace.js.map +1 -1
  49. package/package.json +5 -5
package/dist/support.js CHANGED
@@ -1,247 +1,336 @@
1
- /**
2
- * What this browser can do, probed the way the engine's playground probes
3
- * it: the platform APIs, the codecs through MSE, the element and Media
4
- * Capabilities, and the DRM key systems with their security levels,
5
- * schemes, persistence, identifiers and output protection. Every probe is
6
- * bounded by a timeout, and the whole run is cached for the page: it does
7
- * not change while the page lives, and the key-system probes are not free.
8
- * Nothing here touches the engine.
9
- */
1
+ //#region src/support.ts
10
2
  const CODECS = [
11
- { label: 'H.264 High 4.0', codec: 'avc1.640028', kind: 'video', containers: ['mp4'] },
12
- { label: 'H.264 Baseline', codec: 'avc1.42e01e', kind: 'video', containers: ['mp4'] },
13
- { label: 'H.265 / HEVC Main', codec: 'hvc1.1.6.L123.B0', kind: 'video', containers: ['mp4'] },
14
- { label: 'VP9 Profile 0', codec: 'vp09.00.40.08', kind: 'video', containers: ['mp4', 'webm'] },
15
- { label: 'AV1 Main', codec: 'av01.0.08M.08', kind: 'video', containers: ['mp4', 'webm'] },
16
- { label: 'AAC-LC', codec: 'mp4a.40.2', kind: 'audio', containers: ['mp4'] },
17
- { label: 'HE-AAC', codec: 'mp4a.40.5', kind: 'audio', containers: ['mp4'] },
18
- { label: 'Opus', codec: 'opus', kind: 'audio', containers: ['mp4', 'webm'] },
19
- { label: 'FLAC', codec: 'flac', kind: 'audio', containers: ['mp4'] },
20
- { label: 'AC-3', codec: 'ac-3', kind: 'audio', containers: ['mp4'] },
21
- { label: 'E-AC-3', codec: 'ec-3', kind: 'audio', containers: ['mp4'] },
3
+ {
4
+ label: "H.264 High 4.0",
5
+ codec: "avc1.640028",
6
+ kind: "video",
7
+ containers: ["mp4"]
8
+ },
9
+ {
10
+ label: "H.264 Baseline",
11
+ codec: "avc1.42e01e",
12
+ kind: "video",
13
+ containers: ["mp4"]
14
+ },
15
+ {
16
+ label: "H.265 / HEVC Main",
17
+ codec: "hvc1.1.6.L123.B0",
18
+ kind: "video",
19
+ containers: ["mp4"]
20
+ },
21
+ {
22
+ label: "VP9 Profile 0",
23
+ codec: "vp09.00.40.08",
24
+ kind: "video",
25
+ containers: ["mp4", "webm"]
26
+ },
27
+ {
28
+ label: "AV1 Main",
29
+ codec: "av01.0.08M.08",
30
+ kind: "video",
31
+ containers: ["mp4", "webm"]
32
+ },
33
+ {
34
+ label: "AAC-LC",
35
+ codec: "mp4a.40.2",
36
+ kind: "audio",
37
+ containers: ["mp4"]
38
+ },
39
+ {
40
+ label: "HE-AAC",
41
+ codec: "mp4a.40.5",
42
+ kind: "audio",
43
+ containers: ["mp4"]
44
+ },
45
+ {
46
+ label: "Opus",
47
+ codec: "opus",
48
+ kind: "audio",
49
+ containers: ["mp4", "webm"]
50
+ },
51
+ {
52
+ label: "FLAC",
53
+ codec: "flac",
54
+ kind: "audio",
55
+ containers: ["mp4"]
56
+ },
57
+ {
58
+ label: "AC-3",
59
+ codec: "ac-3",
60
+ kind: "audio",
61
+ containers: ["mp4"]
62
+ },
63
+ {
64
+ label: "E-AC-3",
65
+ codec: "ec-3",
66
+ kind: "audio",
67
+ containers: ["mp4"]
68
+ }
22
69
  ];
23
70
  const KEY_SYSTEMS = [
24
- {
25
- label: 'Widevine',
26
- keySystems: ['com.widevine.alpha'],
27
- levels: [
28
- ['HW_SECURE_ALL', 'L1'],
29
- ['HW_SECURE_DECODE', 'L1'],
30
- ['HW_SECURE_CRYPTO', 'L2'],
31
- ['SW_SECURE_DECODE', 'L3'],
32
- ['SW_SECURE_CRYPTO', 'L3'],
33
- ],
34
- },
35
- {
36
- label: 'PlayReady',
37
- keySystems: ['com.microsoft.playready.recommendation', 'com.microsoft.playready'],
38
- levels: [
39
- ['3000', 'SL3000'],
40
- ['2000', 'SL2000'],
41
- ['150', 'SL150'],
42
- ],
43
- },
44
- { label: 'FairPlay', keySystems: ['com.apple.fps', 'com.apple.fps.1_0'], levels: [] },
45
- { label: 'ClearKey', keySystems: ['org.w3.clearkey'], levels: [] },
71
+ {
72
+ label: "Widevine",
73
+ keySystems: ["com.widevine.alpha"],
74
+ levels: [
75
+ ["HW_SECURE_ALL", "L1"],
76
+ ["HW_SECURE_DECODE", "L1"],
77
+ ["HW_SECURE_CRYPTO", "L2"],
78
+ ["SW_SECURE_DECODE", "L3"],
79
+ ["SW_SECURE_CRYPTO", "L3"]
80
+ ]
81
+ },
82
+ {
83
+ label: "PlayReady",
84
+ keySystems: ["com.microsoft.playready.recommendation", "com.microsoft.playready"],
85
+ levels: [
86
+ ["3000", "SL3000"],
87
+ ["2000", "SL2000"],
88
+ ["150", "SL150"]
89
+ ]
90
+ },
91
+ {
92
+ label: "FairPlay",
93
+ keySystems: ["com.apple.fps", "com.apple.fps.1_0"],
94
+ levels: []
95
+ },
96
+ {
97
+ label: "ClearKey",
98
+ keySystems: ["org.w3.clearkey"],
99
+ levels: []
100
+ }
46
101
  ];
47
- const HDCP_VERSIONS = ['1.0', '1.1', '1.2', '1.3', '1.4', '2.0', '2.1', '2.2', '2.3'];
48
- const VIDEO_TYPE = 'video/mp4; codecs="avc1.42e01e"';
49
- const VIDEO_TYPE_ALT = 'video/mp4; codecs="vp09.00.10.08"';
50
- const AUDIO_TYPE = 'audio/mp4; codecs="mp4a.40.2"';
51
- const AUDIO_TYPE_ALT = 'audio/mp4; codecs="opus"';
102
+ const HDCP_VERSIONS = [
103
+ "1.0",
104
+ "1.1",
105
+ "1.2",
106
+ "1.3",
107
+ "1.4",
108
+ "2.0",
109
+ "2.1",
110
+ "2.2",
111
+ "2.3"
112
+ ];
113
+ const VIDEO_TYPE = "video/mp4; codecs=\"avc1.42e01e\"";
114
+ const VIDEO_TYPE_ALT = "video/mp4; codecs=\"vp09.00.10.08\"";
115
+ const AUDIO_TYPE = "audio/mp4; codecs=\"mp4a.40.2\"";
116
+ const AUDIO_TYPE_ALT = "audio/mp4; codecs=\"opus\"";
52
117
  /** A probe that never answers is a no: some CDMs hang instead of rejecting. */
53
- function withTimeout(promise, fallback, ms = 4000) {
54
- return new Promise((resolve) => {
55
- const timer = setTimeout(() => resolve(fallback), ms);
56
- promise.then((value) => {
57
- clearTimeout(timer);
58
- resolve(value);
59
- }, () => {
60
- clearTimeout(timer);
61
- resolve(fallback);
62
- });
63
- });
118
+ function withTimeout(promise, fallback, ms = 4e3) {
119
+ return new Promise((resolve) => {
120
+ const timer = setTimeout(() => resolve(fallback), ms);
121
+ promise.then((value) => {
122
+ clearTimeout(timer);
123
+ resolve(value);
124
+ }, () => {
125
+ clearTimeout(timer);
126
+ resolve(fallback);
127
+ });
128
+ });
64
129
  }
65
130
  function has(name) {
66
- return name in globalThis ? 'yes' : 'no';
131
+ return name in globalThis ? "yes" : "no";
67
132
  }
68
133
  function platform() {
69
- let changeType = 'no';
70
- try {
71
- if (typeof MediaSource !== 'undefined' && 'changeType' in SourceBuffer.prototype) {
72
- changeType = 'yes';
73
- }
74
- }
75
- catch {
76
- changeType = 'no';
77
- }
78
- return [
79
- { label: 'Secure context', value: window.isSecureContext ? 'yes' : 'no' },
80
- { label: 'MediaSource', value: has('MediaSource') },
81
- { label: 'ManagedMediaSource', value: has('ManagedMediaSource') },
82
- { label: 'SourceBuffer.changeType', value: changeType },
83
- { label: 'Encrypted Media (EME)', value: has('MediaKeys') },
84
- {
85
- label: 'MediaCapabilities',
86
- value: navigator.mediaCapabilities !== undefined ? 'yes' : 'no',
87
- },
88
- { label: 'WebCodecs', value: has('VideoDecoder') },
89
- ];
134
+ let changeType = "no";
135
+ try {
136
+ if (typeof MediaSource !== "undefined" && "changeType" in SourceBuffer.prototype) changeType = "yes";
137
+ } catch {
138
+ changeType = "no";
139
+ }
140
+ return [
141
+ {
142
+ label: "Secure context",
143
+ value: window.isSecureContext ? "yes" : "no"
144
+ },
145
+ {
146
+ label: "MediaSource",
147
+ value: has("MediaSource")
148
+ },
149
+ {
150
+ label: "ManagedMediaSource",
151
+ value: has("ManagedMediaSource")
152
+ },
153
+ {
154
+ label: "SourceBuffer.changeType",
155
+ value: changeType
156
+ },
157
+ {
158
+ label: "Encrypted Media (EME)",
159
+ value: has("MediaKeys")
160
+ },
161
+ {
162
+ label: "MediaCapabilities",
163
+ value: navigator.mediaCapabilities !== void 0 ? "yes" : "no"
164
+ },
165
+ {
166
+ label: "WebCodecs",
167
+ value: has("VideoDecoder")
168
+ }
169
+ ];
90
170
  }
91
171
  function mseSupports(type) {
92
- try {
93
- return typeof MediaSource !== 'undefined' && MediaSource.isTypeSupported(type);
94
- }
95
- catch {
96
- return false;
97
- }
172
+ try {
173
+ return typeof MediaSource !== "undefined" && MediaSource.isTypeSupported(type);
174
+ } catch {
175
+ return false;
176
+ }
98
177
  }
99
178
  function elementSupports(type) {
100
- const answer = document.createElement('video').canPlayType(type);
101
- return answer === 'probably' ? 'yes' : answer === 'maybe' ? 'maybe' : 'no';
179
+ const answer = document.createElement("video").canPlayType(type);
180
+ return answer === "probably" ? "yes" : answer === "maybe" ? "maybe" : "no";
102
181
  }
103
182
  async function decodingInfo(probe) {
104
- const capabilities = navigator.mediaCapabilities;
105
- if (capabilities?.decodingInfo === undefined)
106
- return { smooth: 'na', efficient: 'na' };
107
- const contentType = `${probe.kind}/${probe.containers[0]}; codecs="${probe.codec}"`;
108
- const config = probe.kind === 'video'
109
- ? {
110
- type: 'media-source',
111
- video: { contentType, width: 1920, height: 1080, bitrate: 6_000_000, framerate: 30 },
112
- }
113
- : { type: 'media-source', audio: { contentType, channels: '2', bitrate: 128_000 } };
114
- const info = await withTimeout(capabilities.decodingInfo(config), null);
115
- if (info === null)
116
- return { smooth: 'na', efficient: 'na' };
117
- if (!info.supported)
118
- return { smooth: 'no', efficient: 'no' };
119
- return { smooth: info.smooth ? 'yes' : 'no', efficient: info.powerEfficient ? 'yes' : 'no' };
183
+ const capabilities = navigator.mediaCapabilities;
184
+ if (capabilities?.decodingInfo === void 0) return {
185
+ smooth: "na",
186
+ efficient: "na"
187
+ };
188
+ const contentType = `${probe.kind}/${probe.containers[0]}; codecs="${probe.codec}"`;
189
+ const config = probe.kind === "video" ? {
190
+ type: "media-source",
191
+ video: {
192
+ contentType,
193
+ width: 1920,
194
+ height: 1080,
195
+ bitrate: 6e6,
196
+ framerate: 30
197
+ }
198
+ } : {
199
+ type: "media-source",
200
+ audio: {
201
+ contentType,
202
+ channels: "2",
203
+ bitrate: 128e3
204
+ }
205
+ };
206
+ const info = await withTimeout(capabilities.decodingInfo(config), null);
207
+ if (info === null) return {
208
+ smooth: "na",
209
+ efficient: "na"
210
+ };
211
+ if (!info.supported) return {
212
+ smooth: "no",
213
+ efficient: "no"
214
+ };
215
+ return {
216
+ smooth: info.smooth ? "yes" : "no",
217
+ efficient: info.powerEfficient ? "yes" : "no"
218
+ };
120
219
  }
121
220
  async function codec(probe) {
122
- const cell = (container) => probe.containers.includes(container)
123
- ? mseSupports(`${probe.kind}/${container}; codecs="${probe.codec}"`)
124
- ? 'yes'
125
- : 'no'
126
- : 'na';
127
- const { smooth, efficient } = await decodingInfo(probe);
128
- return {
129
- label: probe.label,
130
- codec: probe.codec,
131
- kind: probe.kind,
132
- mse: cell('mp4'),
133
- webm: cell('webm'),
134
- element: elementSupports(`${probe.kind}/${probe.containers[0]}; codecs="${probe.codec}"`),
135
- smooth,
136
- efficient,
137
- };
221
+ const cell = (container) => probe.containers.includes(container) ? mseSupports(`${probe.kind}/${container}; codecs="${probe.codec}"`) ? "yes" : "no" : "na";
222
+ const { smooth, efficient } = await decodingInfo(probe);
223
+ return {
224
+ label: probe.label,
225
+ codec: probe.codec,
226
+ kind: probe.kind,
227
+ mse: cell("mp4"),
228
+ webm: cell("webm"),
229
+ element: elementSupports(`${probe.kind}/${probe.containers[0]}; codecs="${probe.codec}"`),
230
+ smooth,
231
+ efficient
232
+ };
138
233
  }
139
234
  function videoAlternates(extra = {}) {
140
- return [
141
- { contentType: VIDEO_TYPE, ...extra },
142
- { contentType: VIDEO_TYPE_ALT, ...extra },
143
- ];
235
+ return [{
236
+ contentType: VIDEO_TYPE,
237
+ ...extra
238
+ }, {
239
+ contentType: VIDEO_TYPE_ALT,
240
+ ...extra
241
+ }];
144
242
  }
145
243
  function baseConfig(extra = {}) {
146
- return {
147
- initDataTypes: ['cenc', 'keyids', 'sinf', 'skd'],
148
- videoCapabilities: videoAlternates(),
149
- audioCapabilities: [{ contentType: AUDIO_TYPE }, { contentType: AUDIO_TYPE_ALT }],
150
- ...extra,
151
- };
244
+ return {
245
+ initDataTypes: [
246
+ "cenc",
247
+ "keyids",
248
+ "sinf",
249
+ "skd"
250
+ ],
251
+ videoCapabilities: videoAlternates(),
252
+ audioCapabilities: [{ contentType: AUDIO_TYPE }, { contentType: AUDIO_TYPE_ALT }],
253
+ ...extra
254
+ };
152
255
  }
153
256
  function requestAccess(keySystem, config) {
154
- if (typeof navigator.requestMediaKeySystemAccess !== 'function')
155
- return Promise.resolve(null);
156
- return withTimeout(navigator.requestMediaKeySystemAccess(keySystem, [config]).then((access) => access, () => null), null);
257
+ if (typeof navigator.requestMediaKeySystemAccess !== "function") return Promise.resolve(null);
258
+ return withTimeout(navigator.requestMediaKeySystemAccess(keySystem, [config]).then((access) => access, () => null), null);
157
259
  }
158
260
  const NONE = (label) => ({
159
- label,
160
- keySystem: null,
161
- level: 'na',
162
- schemes: 'na',
163
- persistent: 'na',
164
- identifier: 'na',
165
- hdcp: 'na',
261
+ label,
262
+ keySystem: null,
263
+ level: "na",
264
+ schemes: "na",
265
+ persistent: "na",
266
+ identifier: "na",
267
+ hdcp: "na"
166
268
  });
167
269
  async function keySystem(probe) {
168
- let system = null;
169
- let access = null;
170
- for (const candidate of probe.keySystems) {
171
- access = await requestAccess(candidate, baseConfig());
172
- if (access !== null) {
173
- system = candidate;
174
- break;
175
- }
176
- }
177
- if (system === null || access === null)
178
- return NONE(probe.label);
179
- let level = probe.levels.length === 0 ? 'n/a for this system' : 'none granted';
180
- for (const [robustness, name] of probe.levels) {
181
- const granted = await requestAccess(system, baseConfig({ videoCapabilities: videoAlternates({ robustness }) }));
182
- if (granted !== null) {
183
- level = `${name} (${robustness})`;
184
- break;
185
- }
186
- }
187
- // Only a scheme the browser echoes back counts: an old EME grants any.
188
- const echoed = [];
189
- let schemeApi = false;
190
- for (const scheme of ['cenc', 'cbcs']) {
191
- const granted = await requestAccess(system, baseConfig({ videoCapabilities: videoAlternates({ encryptionScheme: scheme }) }));
192
- const answer = granted
193
- ?.getConfiguration()
194
- .videoCapabilities?.find((c) => c.contentType !== '')?.encryptionScheme;
195
- if (answer !== undefined && answer !== null)
196
- schemeApi = true;
197
- if (answer === scheme)
198
- echoed.push(scheme);
199
- }
200
- const schemes = !schemeApi
201
- ? 'unknown (no API)'
202
- : echoed.length === 0
203
- ? 'none'
204
- : echoed.join(', ');
205
- const persistent = await requestAccess(system, baseConfig({ persistentState: 'required', sessionTypes: ['persistent-license'] }));
206
- const identifier = await requestAccess(system, baseConfig({ distinctiveIdentifier: 'required' }));
207
- let hdcp = 'na';
208
- try {
209
- const keys = (await withTimeout(access.createMediaKeys(), null));
210
- if (keys !== null && typeof keys.getStatusForPolicy === 'function') {
211
- let best = null;
212
- for (const version of HDCP_VERSIONS) {
213
- const status = await withTimeout(keys.getStatusForPolicy({ minHdcpVersion: version }), 'unknown');
214
- if (status !== 'usable')
215
- break;
216
- best = version;
217
- }
218
- hdcp = best === null ? 'no output protection' : `up to ${best}`;
219
- }
220
- }
221
- catch {
222
- hdcp = 'na';
223
- }
224
- return {
225
- label: probe.label,
226
- keySystem: system,
227
- level,
228
- schemes,
229
- persistent: persistent !== null ? 'yes' : 'no',
230
- identifier: identifier !== null ? 'yes' : 'no',
231
- hdcp,
232
- };
270
+ let system = null;
271
+ let access = null;
272
+ for (const candidate of probe.keySystems) {
273
+ access = await requestAccess(candidate, baseConfig());
274
+ if (access !== null) {
275
+ system = candidate;
276
+ break;
277
+ }
278
+ }
279
+ if (system === null || access === null) return NONE(probe.label);
280
+ let level = probe.levels.length === 0 ? "n/a for this system" : "none granted";
281
+ for (const [robustness, name] of probe.levels) if (await requestAccess(system, baseConfig({ videoCapabilities: videoAlternates({ robustness }) })) !== null) {
282
+ level = `${name} (${robustness})`;
283
+ break;
284
+ }
285
+ const echoed = [];
286
+ let schemeApi = false;
287
+ for (const scheme of ["cenc", "cbcs"]) {
288
+ const answer = (await requestAccess(system, baseConfig({ videoCapabilities: videoAlternates({ encryptionScheme: scheme }) })))?.getConfiguration().videoCapabilities?.find((c) => c.contentType !== "")?.encryptionScheme;
289
+ if (answer !== void 0 && answer !== null) schemeApi = true;
290
+ if (answer === scheme) echoed.push(scheme);
291
+ }
292
+ const schemes = !schemeApi ? "unknown (no API)" : echoed.length === 0 ? "none" : echoed.join(", ");
293
+ const persistent = await requestAccess(system, baseConfig({
294
+ persistentState: "required",
295
+ sessionTypes: ["persistent-license"]
296
+ }));
297
+ const identifier = await requestAccess(system, baseConfig({ distinctiveIdentifier: "required" }));
298
+ let hdcp = "na";
299
+ try {
300
+ const keys = await withTimeout(access.createMediaKeys(), null);
301
+ if (keys !== null && typeof keys.getStatusForPolicy === "function") {
302
+ let best = null;
303
+ for (const version of HDCP_VERSIONS) {
304
+ if (await withTimeout(keys.getStatusForPolicy({ minHdcpVersion: version }), "unknown") !== "usable") break;
305
+ best = version;
306
+ }
307
+ hdcp = best === null ? "no output protection" : `up to ${best}`;
308
+ }
309
+ } catch {
310
+ hdcp = "na";
311
+ }
312
+ return {
313
+ label: probe.label,
314
+ keySystem: system,
315
+ level,
316
+ schemes,
317
+ persistent: persistent !== null ? "yes" : "no",
318
+ identifier: identifier !== null ? "yes" : "no",
319
+ hdcp
320
+ };
233
321
  }
234
322
  let cached = null;
235
323
  /** Probes the browser once per page and answers from the cache after. */
236
- export function probeSupport() {
237
- if (cached === null) {
238
- cached = (async () => ({
239
- userAgent: navigator.userAgent,
240
- platform: platform(),
241
- codecs: await Promise.all(CODECS.map(codec)),
242
- drm: await Promise.all(KEY_SYSTEMS.map(keySystem)),
243
- }))();
244
- }
245
- return cached;
324
+ function probeSupport() {
325
+ if (cached === null) cached = (async () => ({
326
+ userAgent: navigator.userAgent,
327
+ platform: platform(),
328
+ codecs: await Promise.all(CODECS.map(codec)),
329
+ drm: await Promise.all(KEY_SYSTEMS.map(keySystem))
330
+ }))();
331
+ return cached;
246
332
  }
333
+ //#endregion
334
+ export { probeSupport };
335
+
247
336
  //# sourceMappingURL=support.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"support.js","sourceRoot":"","sources":["../src/support.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"support.js","names":[],"sources":["../src/support.ts"],"sourcesContent":["/**\n * What this browser can do, probed the way the engine's playground probes\n * it: the platform APIs, the codecs through MSE, the element and Media\n * Capabilities, and the DRM key systems with their security levels,\n * schemes, persistence, identifiers and output protection. Every probe is\n * bounded by a timeout, and the whole run is cached for the page: it does\n * not change while the page lives, and the key-system probes are not free.\n * Nothing here touches the engine.\n */\n\n/** A probe's answer: yes, no, not applicable, maybe, or a text of its own. */\nexport type Cell = 'yes' | 'no' | 'na' | 'maybe' | (string & {});\n\nexport interface PlatformRow {\n readonly label: string;\n readonly value: Cell;\n}\n\nexport interface CodecRow {\n readonly label: string;\n readonly codec: string;\n readonly kind: 'video' | 'audio';\n /** Through MSE, in fMP4 and in WebM. */\n readonly mse: Cell;\n readonly webm: Cell;\n /** The video element's own `canPlayType`. */\n readonly element: Cell;\n /** Media Capabilities: smooth and power-efficient at 1080p30, or stereo 128 kbps. */\n readonly smooth: Cell;\n readonly efficient: Cell;\n}\n\nexport interface DrmRow {\n readonly label: string;\n readonly keySystem: string | null;\n readonly level: Cell;\n readonly schemes: Cell;\n readonly persistent: Cell;\n readonly identifier: Cell;\n readonly hdcp: Cell;\n}\n\nexport interface Support {\n readonly userAgent: string;\n readonly platform: readonly PlatformRow[];\n readonly codecs: readonly CodecRow[];\n readonly drm: readonly DrmRow[];\n}\n\ninterface CodecProbe {\n readonly label: string;\n readonly codec: string;\n readonly kind: 'video' | 'audio';\n readonly containers: readonly string[];\n}\n\nconst CODECS: readonly CodecProbe[] = [\n { label: 'H.264 High 4.0', codec: 'avc1.640028', kind: 'video', containers: ['mp4'] },\n { label: 'H.264 Baseline', codec: 'avc1.42e01e', kind: 'video', containers: ['mp4'] },\n { label: 'H.265 / HEVC Main', codec: 'hvc1.1.6.L123.B0', kind: 'video', containers: ['mp4'] },\n { label: 'VP9 Profile 0', codec: 'vp09.00.40.08', kind: 'video', containers: ['mp4', 'webm'] },\n { label: 'AV1 Main', codec: 'av01.0.08M.08', kind: 'video', containers: ['mp4', 'webm'] },\n { label: 'AAC-LC', codec: 'mp4a.40.2', kind: 'audio', containers: ['mp4'] },\n { label: 'HE-AAC', codec: 'mp4a.40.5', kind: 'audio', containers: ['mp4'] },\n { label: 'Opus', codec: 'opus', kind: 'audio', containers: ['mp4', 'webm'] },\n { label: 'FLAC', codec: 'flac', kind: 'audio', containers: ['mp4'] },\n { label: 'AC-3', codec: 'ac-3', kind: 'audio', containers: ['mp4'] },\n { label: 'E-AC-3', codec: 'ec-3', kind: 'audio', containers: ['mp4'] },\n];\n\ninterface KeySystemProbe {\n readonly label: string;\n /** Tried in order; the first the browser grants wins. */\n readonly keySystems: readonly string[];\n /** Robustness strings and their names, highest first. */\n readonly levels: ReadonlyArray<readonly [string, string]>;\n}\n\nconst KEY_SYSTEMS: readonly KeySystemProbe[] = [\n {\n label: 'Widevine',\n keySystems: ['com.widevine.alpha'],\n levels: [\n ['HW_SECURE_ALL', 'L1'],\n ['HW_SECURE_DECODE', 'L1'],\n ['HW_SECURE_CRYPTO', 'L2'],\n ['SW_SECURE_DECODE', 'L3'],\n ['SW_SECURE_CRYPTO', 'L3'],\n ],\n },\n {\n label: 'PlayReady',\n keySystems: ['com.microsoft.playready.recommendation', 'com.microsoft.playready'],\n levels: [\n ['3000', 'SL3000'],\n ['2000', 'SL2000'],\n ['150', 'SL150'],\n ],\n },\n { label: 'FairPlay', keySystems: ['com.apple.fps', 'com.apple.fps.1_0'], levels: [] },\n { label: 'ClearKey', keySystems: ['org.w3.clearkey'], levels: [] },\n];\n\nconst HDCP_VERSIONS = ['1.0', '1.1', '1.2', '1.3', '1.4', '2.0', '2.1', '2.2', '2.3'];\nconst VIDEO_TYPE = 'video/mp4; codecs=\"avc1.42e01e\"';\nconst VIDEO_TYPE_ALT = 'video/mp4; codecs=\"vp09.00.10.08\"';\nconst AUDIO_TYPE = 'audio/mp4; codecs=\"mp4a.40.2\"';\nconst AUDIO_TYPE_ALT = 'audio/mp4; codecs=\"opus\"';\n\n/** A probe that never answers is a no: some CDMs hang instead of rejecting. */\nfunction withTimeout<T>(promise: Promise<T>, fallback: T, ms = 4000): Promise<T> {\n return new Promise((resolve) => {\n const timer = setTimeout(() => resolve(fallback), ms);\n promise.then(\n (value) => {\n clearTimeout(timer);\n resolve(value);\n },\n () => {\n clearTimeout(timer);\n resolve(fallback);\n },\n );\n });\n}\n\nfunction has(name: string): Cell {\n return name in globalThis ? 'yes' : 'no';\n}\n\nfunction platform(): PlatformRow[] {\n let changeType: Cell = 'no';\n try {\n if (typeof MediaSource !== 'undefined' && 'changeType' in SourceBuffer.prototype) {\n changeType = 'yes';\n }\n } catch {\n changeType = 'no';\n }\n return [\n { label: 'Secure context', value: window.isSecureContext ? 'yes' : 'no' },\n { label: 'MediaSource', value: has('MediaSource') },\n { label: 'ManagedMediaSource', value: has('ManagedMediaSource') },\n { label: 'SourceBuffer.changeType', value: changeType },\n { label: 'Encrypted Media (EME)', value: has('MediaKeys') },\n {\n label: 'MediaCapabilities',\n value: navigator.mediaCapabilities !== undefined ? 'yes' : 'no',\n },\n { label: 'WebCodecs', value: has('VideoDecoder') },\n ];\n}\n\nfunction mseSupports(type: string): boolean {\n try {\n return typeof MediaSource !== 'undefined' && MediaSource.isTypeSupported(type);\n } catch {\n return false;\n }\n}\n\nfunction elementSupports(type: string): Cell {\n const answer = document.createElement('video').canPlayType(type);\n return answer === 'probably' ? 'yes' : answer === 'maybe' ? 'maybe' : 'no';\n}\n\nasync function decodingInfo(probe: CodecProbe): Promise<{ smooth: Cell; efficient: Cell }> {\n const capabilities = navigator.mediaCapabilities;\n if (capabilities?.decodingInfo === undefined) return { smooth: 'na', efficient: 'na' };\n const contentType = `${probe.kind}/${probe.containers[0]}; codecs=\"${probe.codec}\"`;\n const config: MediaDecodingConfiguration =\n probe.kind === 'video'\n ? {\n type: 'media-source',\n video: { contentType, width: 1920, height: 1080, bitrate: 6_000_000, framerate: 30 },\n }\n : { type: 'media-source', audio: { contentType, channels: '2', bitrate: 128_000 } };\n const info = await withTimeout(\n capabilities.decodingInfo(config) as Promise<MediaCapabilitiesDecodingInfo | null>,\n null,\n );\n if (info === null) return { smooth: 'na', efficient: 'na' };\n if (!info.supported) return { smooth: 'no', efficient: 'no' };\n return { smooth: info.smooth ? 'yes' : 'no', efficient: info.powerEfficient ? 'yes' : 'no' };\n}\n\nasync function codec(probe: CodecProbe): Promise<CodecRow> {\n const cell = (container: string): Cell =>\n probe.containers.includes(container)\n ? mseSupports(`${probe.kind}/${container}; codecs=\"${probe.codec}\"`)\n ? 'yes'\n : 'no'\n : 'na';\n const { smooth, efficient } = await decodingInfo(probe);\n return {\n label: probe.label,\n codec: probe.codec,\n kind: probe.kind,\n mse: cell('mp4'),\n webm: cell('webm'),\n element: elementSupports(`${probe.kind}/${probe.containers[0]}; codecs=\"${probe.codec}\"`),\n smooth,\n efficient,\n };\n}\n\nfunction videoAlternates(\n extra: Partial<MediaKeySystemMediaCapability> = {},\n): MediaKeySystemMediaCapability[] {\n return [\n { contentType: VIDEO_TYPE, ...extra },\n { contentType: VIDEO_TYPE_ALT, ...extra },\n ];\n}\n\nfunction baseConfig(extra: Partial<MediaKeySystemConfiguration> = {}): MediaKeySystemConfiguration {\n return {\n initDataTypes: ['cenc', 'keyids', 'sinf', 'skd'],\n videoCapabilities: videoAlternates(),\n audioCapabilities: [{ contentType: AUDIO_TYPE }, { contentType: AUDIO_TYPE_ALT }],\n ...extra,\n };\n}\n\nfunction requestAccess(\n keySystem: string,\n config: MediaKeySystemConfiguration,\n): Promise<MediaKeySystemAccess | null> {\n if (typeof navigator.requestMediaKeySystemAccess !== 'function') return Promise.resolve(null);\n return withTimeout(\n navigator.requestMediaKeySystemAccess(keySystem, [config]).then(\n (access) => access,\n () => null,\n ),\n null,\n );\n}\n\nconst NONE = (label: string): DrmRow => ({\n label,\n keySystem: null,\n level: 'na',\n schemes: 'na',\n persistent: 'na',\n identifier: 'na',\n hdcp: 'na',\n});\n\nasync function keySystem(probe: KeySystemProbe): Promise<DrmRow> {\n let system: string | null = null;\n let access: MediaKeySystemAccess | null = null;\n for (const candidate of probe.keySystems) {\n access = await requestAccess(candidate, baseConfig());\n if (access !== null) {\n system = candidate;\n break;\n }\n }\n if (system === null || access === null) return NONE(probe.label);\n\n let level: Cell = probe.levels.length === 0 ? 'n/a for this system' : 'none granted';\n for (const [robustness, name] of probe.levels) {\n const granted = await requestAccess(\n system,\n baseConfig({ videoCapabilities: videoAlternates({ robustness }) }),\n );\n if (granted !== null) {\n level = `${name} (${robustness})`;\n break;\n }\n }\n\n // Only a scheme the browser echoes back counts: an old EME grants any.\n const echoed: string[] = [];\n let schemeApi = false;\n for (const scheme of ['cenc', 'cbcs']) {\n const granted = await requestAccess(\n system,\n baseConfig({ videoCapabilities: videoAlternates({ encryptionScheme: scheme }) }),\n );\n const answer = granted\n ?.getConfiguration()\n .videoCapabilities?.find((c) => c.contentType !== '')?.encryptionScheme;\n if (answer !== undefined && answer !== null) schemeApi = true;\n if (answer === scheme) echoed.push(scheme);\n }\n const schemes: Cell = !schemeApi\n ? 'unknown (no API)'\n : echoed.length === 0\n ? 'none'\n : echoed.join(', ');\n\n const persistent = await requestAccess(\n system,\n baseConfig({ persistentState: 'required', sessionTypes: ['persistent-license'] }),\n );\n const identifier = await requestAccess(system, baseConfig({ distinctiveIdentifier: 'required' }));\n\n let hdcp: Cell = 'na';\n try {\n const keys = (await withTimeout(access.createMediaKeys(), null)) as\n | (MediaKeys & {\n getStatusForPolicy?: (policy: { minHdcpVersion: string }) => Promise<string>;\n })\n | null;\n if (keys !== null && typeof keys.getStatusForPolicy === 'function') {\n let best: string | null = null;\n for (const version of HDCP_VERSIONS) {\n const status = await withTimeout(\n keys.getStatusForPolicy({ minHdcpVersion: version }),\n 'unknown',\n );\n if (status !== 'usable') break;\n best = version;\n }\n hdcp = best === null ? 'no output protection' : `up to ${best}`;\n }\n } catch {\n hdcp = 'na';\n }\n\n return {\n label: probe.label,\n keySystem: system,\n level,\n schemes,\n persistent: persistent !== null ? 'yes' : 'no',\n identifier: identifier !== null ? 'yes' : 'no',\n hdcp,\n };\n}\n\nlet cached: Promise<Support> | null = null;\n\n/** Probes the browser once per page and answers from the cache after. */\nexport function probeSupport(): Promise<Support> {\n if (cached === null) {\n cached = (async (): Promise<Support> => ({\n userAgent: navigator.userAgent,\n platform: platform(),\n codecs: await Promise.all(CODECS.map(codec)),\n drm: await Promise.all(KEY_SYSTEMS.map(keySystem)),\n }))();\n }\n return cached;\n}\n"],"mappings":"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"}