@kkcompany/player 2.25.0-canary.1 → 2.25.0-canary.10
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.
- package/CHANGELOG.md +57 -0
- package/dist/core.mjs +5 -95
- package/dist/index.js +7656 -7422
- package/dist/index.mjs +729 -496
- package/dist/modules.mjs +163 -136
- package/dist/plugins.mjs +3 -4
- package/dist/react.mjs +605 -380
- package/package.json +1 -2
package/dist/modules.mjs
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
import axios from 'axios';
|
|
2
1
|
import mitt from 'mitt';
|
|
3
2
|
import UAParser from 'ua-parser-js';
|
|
4
3
|
|
|
5
4
|
/* eslint-disable no-param-reassign */
|
|
6
|
-
|
|
7
5
|
const waitMs$1 = time => new Promise(resolve => {
|
|
8
6
|
setTimeout(resolve, time);
|
|
9
7
|
});
|
|
10
8
|
|
|
11
|
-
const handleRequestError = (
|
|
9
|
+
const handleRequestError = (request, {
|
|
12
10
|
onError,
|
|
13
11
|
retryTimes = 0
|
|
14
|
-
}) =>
|
|
15
|
-
retry: () => handleRequestError(
|
|
12
|
+
}) => request().catch(error => onError(error, {
|
|
13
|
+
retry: () => handleRequestError(request, {
|
|
16
14
|
onError,
|
|
17
15
|
retryTimes: retryTimes + 1
|
|
18
16
|
}),
|
|
@@ -23,7 +21,7 @@ const ignoreMinorError = async (event, {
|
|
|
23
21
|
retry,
|
|
24
22
|
retryTimes
|
|
25
23
|
} = {}) => {
|
|
26
|
-
var _event$response, _event$response2, _event$
|
|
24
|
+
var _event$response, _event$response2, _event$response3;
|
|
27
25
|
|
|
28
26
|
console.warn(event);
|
|
29
27
|
|
|
@@ -32,17 +30,34 @@ const ignoreMinorError = async (event, {
|
|
|
32
30
|
return retry();
|
|
33
31
|
}
|
|
34
32
|
|
|
35
|
-
|
|
33
|
+
const url = new URL(((_event$response3 = event.response) === null || _event$response3 === void 0 ? void 0 : _event$response3.url) || 'http://unknown/');
|
|
34
|
+
|
|
35
|
+
if (/start$|info$|heartbeat$/.test(url.pathname)) {
|
|
36
36
|
return Promise.reject(event);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
if (/end$/.test(
|
|
39
|
+
if (/end$/.test(url.pathname)) {
|
|
40
40
|
return Promise.resolve();
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
console.log('Ignore non-critical playback API fail', event);
|
|
44
44
|
return new Promise(() => {});
|
|
45
45
|
};
|
|
46
|
+
/** @param {Response} response */
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
const handleFetchResponse = response => {
|
|
50
|
+
if (response.ok) {
|
|
51
|
+
return response.status === 200 ? response.json() : '';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return response.json().then(errorData => {
|
|
55
|
+
const error = new Error(`HTTP error status: ${response.status} ${errorData.message}`);
|
|
56
|
+
error.data = errorData;
|
|
57
|
+
error.response = response;
|
|
58
|
+
return Promise.reject(error);
|
|
59
|
+
});
|
|
60
|
+
};
|
|
46
61
|
|
|
47
62
|
const createApi = (config, {
|
|
48
63
|
onError = ignoreMinorError
|
|
@@ -67,28 +82,26 @@ const createApi = (config, {
|
|
|
67
82
|
|
|
68
83
|
const request = (url, {
|
|
69
84
|
method
|
|
70
|
-
} = {}) => handleRequestError(
|
|
85
|
+
} = {}) => handleRequestError(() => fetch(`${url}?${new URLSearchParams(params).toString()}`, {
|
|
71
86
|
method,
|
|
72
|
-
headers: getHeaders()
|
|
73
|
-
|
|
74
|
-
}), {
|
|
87
|
+
headers: getHeaders()
|
|
88
|
+
}).then(handleFetchResponse), {
|
|
75
89
|
onError
|
|
76
|
-
})
|
|
90
|
+
});
|
|
77
91
|
|
|
78
92
|
const sessionRequest = (path, {
|
|
79
93
|
method = 'POST',
|
|
80
94
|
type,
|
|
81
95
|
id,
|
|
82
96
|
token
|
|
83
|
-
}) => handleRequestError(
|
|
97
|
+
}) => handleRequestError(() => fetch(`${host}/sessions/${type}/${id}/playback/${deviceId}/${path}?${new URLSearchParams({ ...params,
|
|
98
|
+
playback_token: token
|
|
99
|
+
}).toString()}`, {
|
|
84
100
|
method,
|
|
85
|
-
headers: getHeaders()
|
|
86
|
-
|
|
87
|
-
playback_token: token
|
|
88
|
-
}
|
|
89
|
-
}), {
|
|
101
|
+
headers: getHeaders()
|
|
102
|
+
}).then(handleFetchResponse), {
|
|
90
103
|
onError
|
|
91
|
-
})
|
|
104
|
+
});
|
|
92
105
|
|
|
93
106
|
return {
|
|
94
107
|
config,
|
|
@@ -377,38 +390,6 @@ const validateEnvironment = (supportEnvironmentList = []) => {
|
|
|
377
390
|
}
|
|
378
391
|
}; // Some touch devices with a mouse can't be distinguished, assume no mouse
|
|
379
392
|
|
|
380
|
-
const timeoutError = () => new Error('request timeout');
|
|
381
|
-
/**
|
|
382
|
-
* @param {URL|RequestInfo} url
|
|
383
|
-
* @param {RequestInit} options
|
|
384
|
-
* @param {{responseType: 'json'|'text'}}
|
|
385
|
-
*/
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
const retryRequest = (url, options = {}, {
|
|
389
|
-
responseType = 'json',
|
|
390
|
-
timeout = 6,
|
|
391
|
-
retryTimes = 6
|
|
392
|
-
} = {}) => new Promise((resolve, reject) => {
|
|
393
|
-
setTimeout(() => reject(timeoutError()), timeout * 1000);
|
|
394
|
-
fetch(url, options).then(response => {
|
|
395
|
-
var _response$responseTyp;
|
|
396
|
-
|
|
397
|
-
return resolve(((_response$responseTyp = response[responseType]) === null || _response$responseTyp === void 0 ? void 0 : _response$responseTyp.call(response)) || response);
|
|
398
|
-
}).catch(reject);
|
|
399
|
-
}).catch(error => {
|
|
400
|
-
console.log(error);
|
|
401
|
-
|
|
402
|
-
if (retryTimes > 0) {
|
|
403
|
-
return retryRequest(url, options, {
|
|
404
|
-
timeout,
|
|
405
|
-
retryTimes: retryTimes - 1
|
|
406
|
-
});
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
return error;
|
|
410
|
-
});
|
|
411
|
-
|
|
412
393
|
const protocolExtensions = {
|
|
413
394
|
hls: 'm3u8',
|
|
414
395
|
dash: 'mpd'
|
|
@@ -506,88 +487,6 @@ const getSource = (sourceOptions, {
|
|
|
506
487
|
};
|
|
507
488
|
};
|
|
508
489
|
|
|
509
|
-
function getVersion() {
|
|
510
|
-
try {
|
|
511
|
-
// eslint-disable-next-line no-undef
|
|
512
|
-
return "2.25.0-canary.1";
|
|
513
|
-
} catch (e) {
|
|
514
|
-
return undefined;
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
const matchAll = (input, pattern) => {
|
|
519
|
-
const flags = [pattern.global && 'g', pattern.ignoreCase && 'i', pattern.multiline && 'm'].filter(Boolean).join('');
|
|
520
|
-
const clone = new RegExp(pattern, flags);
|
|
521
|
-
return Array.from(function* () {
|
|
522
|
-
let matched = true;
|
|
523
|
-
|
|
524
|
-
while (1) {
|
|
525
|
-
matched = clone.exec(input);
|
|
526
|
-
|
|
527
|
-
if (!matched) {
|
|
528
|
-
return;
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
yield matched;
|
|
532
|
-
}
|
|
533
|
-
}());
|
|
534
|
-
};
|
|
535
|
-
|
|
536
|
-
const rewriteUrls = (manifest, sourceUrl) => manifest.replace(/((#EXT-X-MEDIA:.*URI=")([^"]*))|((#EXT-X-STREAM-INF.*\n)(.*)(?=\n))/g, (...matches) => [matches[2], matches[5], new URL(matches[3] || matches[6], sourceUrl)].filter(Boolean).join(''));
|
|
537
|
-
|
|
538
|
-
const filterHlsManifestQualities = (originalManifest, filter) => {
|
|
539
|
-
if (!filter) {
|
|
540
|
-
return;
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
const manifest = `${originalManifest}\n`;
|
|
544
|
-
const profiles = matchAll(manifest, /RESOLUTION=(\d+)x(\d+)/g).map(([, width, height]) => ({
|
|
545
|
-
width: +width,
|
|
546
|
-
height: +height
|
|
547
|
-
}));
|
|
548
|
-
const allowed = filter(profiles) || profiles;
|
|
549
|
-
const newManifest = manifest.replace(/#EXT-X-STREAM-INF.*RESOLUTION=(\d+)x(\d+).*\n.*\n/g, (item, width, height) => allowed.some(p => p.width === +width && p.height === +height) ? item : '');
|
|
550
|
-
return newManifest !== manifest && newManifest;
|
|
551
|
-
};
|
|
552
|
-
|
|
553
|
-
const meetRestriction = (quality, {
|
|
554
|
-
minHeight,
|
|
555
|
-
maxHeight
|
|
556
|
-
} = {}) => !(quality.height < minHeight || quality.height > maxHeight);
|
|
557
|
-
|
|
558
|
-
const selectHlsQualities = async (source, restrictions = {}) => {
|
|
559
|
-
if (!needNativeHls() || !(restrictions.minHeight || restrictions.maxHeight)) {
|
|
560
|
-
return source;
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
const selected = getSource(source, {
|
|
564
|
-
preferManifestType: 'hls'
|
|
565
|
-
});
|
|
566
|
-
|
|
567
|
-
if (!((selected === null || selected === void 0 ? void 0 : selected.type.toLowerCase()) === mimeTypes.hls)) {
|
|
568
|
-
return source;
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
const filtered = filterHlsManifestQualities(await retryRequest(selected.src, {}, {
|
|
572
|
-
responseType: 'text'
|
|
573
|
-
}), items => items.filter(item => meetRestriction(item, restrictions)));
|
|
574
|
-
|
|
575
|
-
if (filtered) {
|
|
576
|
-
return { ...selected,
|
|
577
|
-
|
|
578
|
-
/*
|
|
579
|
-
Native Safari couldn't support blob .m3u8. and will throw MediaError: 4
|
|
580
|
-
We find the hacky method: dataURI.
|
|
581
|
-
By the way, bitmovin also use this form even user gives the blob URI.
|
|
582
|
-
*/
|
|
583
|
-
src: `data:application/x-mpegURL,${encodeURI(rewriteUrls(filtered, selected.src))}`
|
|
584
|
-
};
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
return source;
|
|
588
|
-
};
|
|
589
|
-
// for unit test
|
|
590
|
-
|
|
591
490
|
/* eslint-disable no-param-reassign */
|
|
592
491
|
|
|
593
492
|
const SHAKA_LIVE_DURATION = 4294967296;
|
|
@@ -1089,6 +988,15 @@ const mapLogEvents$1 = ({
|
|
|
1089
988
|
};
|
|
1090
989
|
};
|
|
1091
990
|
|
|
991
|
+
function getVersion() {
|
|
992
|
+
try {
|
|
993
|
+
// eslint-disable-next-line no-undef
|
|
994
|
+
return "2.25.0-canary.10";
|
|
995
|
+
} catch (e) {
|
|
996
|
+
return undefined;
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
|
|
1092
1000
|
const logEventNames = {
|
|
1093
1001
|
playbackBeganLoading: 'playback_began_player_loading',
|
|
1094
1002
|
playbackBeganPlayerStartupTime: 'playback_began_player_startup_time',
|
|
@@ -1394,6 +1302,12 @@ const retrieveModuleConfig = (modulesConfig, query) => {
|
|
|
1394
1302
|
|
|
1395
1303
|
/* eslint-disable camelcase */
|
|
1396
1304
|
const HEARTBEAT_INTERVAL_MS = 10000;
|
|
1305
|
+
//@ts-ignore
|
|
1306
|
+
const axios$1 = {
|
|
1307
|
+
post: (...args) => {
|
|
1308
|
+
console.log(args);
|
|
1309
|
+
}
|
|
1310
|
+
}; // TODO
|
|
1397
1311
|
|
|
1398
1312
|
const eventHeartbeat = ({
|
|
1399
1313
|
token,
|
|
@@ -1426,7 +1340,7 @@ const eventHeartbeat = ({
|
|
|
1426
1340
|
}; // Avoid template literals because the env variable would be replaced in the rollup
|
|
1427
1341
|
|
|
1428
1342
|
await retryWithBackoff$1({
|
|
1429
|
-
fn: () => axios.post(endpoint, payload, {
|
|
1343
|
+
fn: () => axios$1.post(endpoint, payload, {
|
|
1430
1344
|
headers: {
|
|
1431
1345
|
'Kks-Bv-Token': token
|
|
1432
1346
|
}
|
|
@@ -1439,6 +1353,12 @@ var eventHeartbeat$1 = eventHeartbeat;
|
|
|
1439
1353
|
|
|
1440
1354
|
/* eslint-disable camelcase */
|
|
1441
1355
|
|
|
1356
|
+
const axios = {
|
|
1357
|
+
post: (...args) => {
|
|
1358
|
+
console.log(args);
|
|
1359
|
+
}
|
|
1360
|
+
}; // TODO
|
|
1361
|
+
|
|
1442
1362
|
const getDeviceInfo = () => {
|
|
1443
1363
|
const browser = getBrowser();
|
|
1444
1364
|
return {
|
|
@@ -1493,7 +1413,7 @@ const createAnalytics = ({
|
|
|
1493
1413
|
const logTarget = mapLogEvents({
|
|
1494
1414
|
video,
|
|
1495
1415
|
playerName: 'shaka',
|
|
1496
|
-
version: "2.25.0-canary.
|
|
1416
|
+
version: "2.25.0-canary.10"
|
|
1497
1417
|
});
|
|
1498
1418
|
logTarget.all((type, data) => {
|
|
1499
1419
|
const payload = {
|
|
@@ -1550,6 +1470,113 @@ const createAnalytics = ({
|
|
|
1550
1470
|
};
|
|
1551
1471
|
};
|
|
1552
1472
|
|
|
1473
|
+
const timeoutError = () => new Error('request timeout');
|
|
1474
|
+
/**
|
|
1475
|
+
* @param {URL|RequestInfo} url
|
|
1476
|
+
* @param {RequestInit} options
|
|
1477
|
+
* @param {{responseType: 'json'|'text'}}
|
|
1478
|
+
*/
|
|
1479
|
+
|
|
1480
|
+
|
|
1481
|
+
const retryRequest = (url, options = {}, {
|
|
1482
|
+
responseType = 'json',
|
|
1483
|
+
timeout = 6,
|
|
1484
|
+
retryTimes = 6
|
|
1485
|
+
} = {}) => new Promise((resolve, reject) => {
|
|
1486
|
+
setTimeout(() => reject(timeoutError()), timeout * 1000);
|
|
1487
|
+
fetch(url, options).then(response => {
|
|
1488
|
+
var _response$responseTyp;
|
|
1489
|
+
|
|
1490
|
+
return resolve(((_response$responseTyp = response[responseType]) === null || _response$responseTyp === void 0 ? void 0 : _response$responseTyp.call(response)) || response);
|
|
1491
|
+
}).catch(reject);
|
|
1492
|
+
}).catch(error => {
|
|
1493
|
+
console.log(error);
|
|
1494
|
+
|
|
1495
|
+
if (retryTimes > 0) {
|
|
1496
|
+
return retryRequest(url, options, {
|
|
1497
|
+
timeout,
|
|
1498
|
+
retryTimes: retryTimes - 1
|
|
1499
|
+
});
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
return error;
|
|
1503
|
+
});
|
|
1504
|
+
|
|
1505
|
+
/* eslint-disable no-param-reassign */
|
|
1506
|
+
|
|
1507
|
+
const matchAll = (input, pattern) => {
|
|
1508
|
+
const flags = [pattern.global && 'g', pattern.ignoreCase && 'i', pattern.multiline && 'm'].filter(Boolean).join('');
|
|
1509
|
+
const clone = new RegExp(pattern, flags);
|
|
1510
|
+
return Array.from(function* () {
|
|
1511
|
+
let matched = true;
|
|
1512
|
+
|
|
1513
|
+
while (1) {
|
|
1514
|
+
matched = clone.exec(input);
|
|
1515
|
+
|
|
1516
|
+
if (!matched) {
|
|
1517
|
+
return;
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
yield matched;
|
|
1521
|
+
}
|
|
1522
|
+
}());
|
|
1523
|
+
};
|
|
1524
|
+
|
|
1525
|
+
const rewriteUrls = (manifest, sourceUrl) => manifest.replace(/((#EXT-X-MEDIA:.*URI=")([^"]*))|((#EXT-X-STREAM-INF.*\n)(.*)(?=\n))/g, (...matches) => [matches[2], matches[5], new URL(matches[3] || matches[6], sourceUrl)].filter(Boolean).join(''));
|
|
1526
|
+
|
|
1527
|
+
const filterHlsManifestQualities = (originalManifest, filter) => {
|
|
1528
|
+
if (!filter) {
|
|
1529
|
+
return;
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
const manifest = `${originalManifest}\n`;
|
|
1533
|
+
const profiles = matchAll(manifest, /RESOLUTION=(\d+)x(\d+)/g).map(([, width, height]) => ({
|
|
1534
|
+
width: +width,
|
|
1535
|
+
height: +height
|
|
1536
|
+
}));
|
|
1537
|
+
const allowed = filter(profiles) || profiles;
|
|
1538
|
+
const newManifest = manifest.replace(/#EXT-X-STREAM-INF.*RESOLUTION=(\d+)x(\d+).*\n.*\n/g, (item, width, height) => allowed.some(p => p.width === +width && p.height === +height) ? item : '');
|
|
1539
|
+
return newManifest !== manifest && newManifest;
|
|
1540
|
+
};
|
|
1541
|
+
|
|
1542
|
+
const meetRestriction = (quality, {
|
|
1543
|
+
minHeight,
|
|
1544
|
+
maxHeight
|
|
1545
|
+
} = {}) => !(quality.height < minHeight || quality.height > maxHeight);
|
|
1546
|
+
|
|
1547
|
+
const selectHlsQualities = async (source, restrictions = {}) => {
|
|
1548
|
+
if (!isSafari() || !(restrictions.minHeight || restrictions.maxHeight)) {
|
|
1549
|
+
return source;
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
const selected = getSource(source, {
|
|
1553
|
+
preferManifestType: 'hls'
|
|
1554
|
+
});
|
|
1555
|
+
|
|
1556
|
+
if (!((selected === null || selected === void 0 ? void 0 : selected.type.toLowerCase()) === mimeTypes.hls)) {
|
|
1557
|
+
return source;
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
const filtered = filterHlsManifestQualities(await retryRequest(selected.src, {}, {
|
|
1561
|
+
responseType: 'text'
|
|
1562
|
+
}), items => items.filter(item => meetRestriction(item, restrictions)));
|
|
1563
|
+
|
|
1564
|
+
if (filtered) {
|
|
1565
|
+
return { ...selected,
|
|
1566
|
+
|
|
1567
|
+
/*
|
|
1568
|
+
Native Safari couldn't support blob .m3u8. and will throw MediaError: 4
|
|
1569
|
+
We find the hacky method: dataURI.
|
|
1570
|
+
By the way, bitmovin also use this form even user gives the blob URI.
|
|
1571
|
+
*/
|
|
1572
|
+
src: `data:application/x-mpegURL,${encodeURI(rewriteUrls(filtered, selected.src))}`
|
|
1573
|
+
};
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
return source;
|
|
1577
|
+
};
|
|
1578
|
+
// for unit test
|
|
1579
|
+
|
|
1553
1580
|
/* eslint-disable no-empty */
|
|
1554
1581
|
const storageKey = 'playcraft-tab-lock';
|
|
1555
1582
|
const lockRenewTime = 3000;
|
package/dist/plugins.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import mitt from 'mitt';
|
|
2
|
-
import axios from 'axios';
|
|
3
2
|
import UAParser from 'ua-parser-js';
|
|
4
3
|
|
|
5
4
|
/** @param {string} m3u8Manifest */
|
|
@@ -487,13 +486,13 @@ const snapback = ({
|
|
|
487
486
|
}
|
|
488
487
|
};
|
|
489
488
|
|
|
489
|
+
const axios = () => {};
|
|
490
|
+
|
|
490
491
|
const addFetchPolyfill = () => {
|
|
491
492
|
window.fetch = async (url, {
|
|
492
493
|
method
|
|
493
494
|
} = {}) => {
|
|
494
|
-
const result = await axios(
|
|
495
|
-
method
|
|
496
|
-
});
|
|
495
|
+
const result = await axios();
|
|
497
496
|
return Promise.resolve({
|
|
498
497
|
json: () => result.data
|
|
499
498
|
});
|