hls.js 1.5.8-0.canary.10153 → 1.5.8-0.canary.10155

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 (41) hide show
  1. package/dist/hls.js +764 -517
  2. package/dist/hls.js.map +1 -1
  3. package/dist/hls.light.js +585 -351
  4. package/dist/hls.light.js.map +1 -1
  5. package/dist/hls.light.min.js +1 -1
  6. package/dist/hls.light.min.js.map +1 -1
  7. package/dist/hls.light.mjs +580 -352
  8. package/dist/hls.light.mjs.map +1 -1
  9. package/dist/hls.min.js +1 -1
  10. package/dist/hls.min.js.map +1 -1
  11. package/dist/hls.mjs +789 -548
  12. package/dist/hls.mjs.map +1 -1
  13. package/dist/hls.worker.js +1 -1
  14. package/dist/hls.worker.js.map +1 -1
  15. package/package.json +1 -1
  16. package/src/controller/base-playlist-controller.ts +7 -2
  17. package/src/controller/cmcd-controller.ts +1 -1
  18. package/src/controller/eme-controller.ts +1 -1
  19. package/src/controller/id3-track-controller.ts +4 -3
  20. package/src/controller/level-controller.ts +1 -1
  21. package/src/demux/audio/aacdemuxer.ts +2 -2
  22. package/src/demux/audio/ac3-demuxer.ts +4 -3
  23. package/src/demux/audio/base-audio-demuxer.ts +16 -14
  24. package/src/demux/audio/mp3demuxer.ts +4 -3
  25. package/src/demux/audio/mpegaudio.ts +1 -1
  26. package/src/demux/mp4demuxer.ts +7 -7
  27. package/src/demux/video/hevc-video-parser.ts +4 -1
  28. package/src/events.ts +1 -1
  29. package/src/exports-named.ts +1 -1
  30. package/src/loader/fragment-loader.ts +1 -1
  31. package/src/loader/key-loader.ts +1 -1
  32. package/src/remux/mp4-remuxer.ts +1 -1
  33. package/src/types/component-api.ts +1 -1
  34. package/src/types/remuxer.ts +1 -1
  35. package/src/utils/fetch-loader.ts +1 -1
  36. package/src/utils/imsc1-ttml-parser.ts +1 -1
  37. package/src/utils/keysystem-util.ts +1 -6
  38. package/src/utils/mp4-tools.ts +1 -1
  39. package/src/utils/utf8-utils.ts +18 -0
  40. package/src/utils/webvtt-parser.ts +1 -1
  41. package/src/demux/id3.ts +0 -411
package/dist/hls.js CHANGED
@@ -637,7 +637,7 @@
637
637
  // Some browsers don't allow to use bind on console object anyway
638
638
  // fallback to default if needed
639
639
  try {
640
- newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.8-0.canary.10153");
640
+ newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.8-0.canary.10155");
641
641
  } catch (e) {
642
642
  /* log fn threw an exception. All logger methods are no-ops. */
643
643
  return createLogger();
@@ -1209,6 +1209,24 @@
1209
1209
  });
1210
1210
  }
1211
1211
 
1212
+ // breaking up those two types in order to clarify what is happening in the decoding path.
1213
+
1214
+ // http://stackoverflow.com/questions/8936984/uint8array-to-string-in-javascript/22373197
1215
+ // http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
1216
+ /* utf.js - UTF-8 <=> UTF-16 convertion
1217
+ *
1218
+ * Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>
1219
+ * Version: 1.0
1220
+ * LastModified: Dec 25 1999
1221
+ * This library is free. You can redistribute it and/or modify it.
1222
+ */
1223
+
1224
+ function strToUtf8array(str) {
1225
+ return Uint8Array.from(unescape(encodeURIComponent(str)), function (c) {
1226
+ return c.charCodeAt(0);
1227
+ });
1228
+ }
1229
+
1212
1230
  function getKeyIdBytes(str) {
1213
1231
  var keyIdbytes = strToUtf8array(str).subarray(0, 16);
1214
1232
  var paddedkeyIdbytes = new Uint8Array(16);
@@ -1246,11 +1264,6 @@
1246
1264
  }
1247
1265
  return keydata;
1248
1266
  }
1249
- function strToUtf8array(str) {
1250
- return Uint8Array.from(unescape(encodeURIComponent(str)), function (c) {
1251
- return c.charCodeAt(0);
1252
- });
1253
- }
1254
1267
 
1255
1268
  var DecrypterAesMode = {
1256
1269
  cbc: 0,
@@ -1400,387 +1413,118 @@
1400
1413
  return Uint8Array.prototype.slice ? array.slice(start, end) : new Uint8Array(Array.prototype.slice.call(array, start, end));
1401
1414
  }
1402
1415
 
1403
- // breaking up those two types in order to clarify what is happening in the decoding path.
1404
-
1405
- /**
1406
- * Returns true if an ID3 header can be found at offset in data
1407
- * @param data - The data to search
1408
- * @param offset - The offset at which to start searching
1416
+ // http://stackoverflow.com/questions/8936984/uint8array-to-string-in-javascript/22373197
1417
+ // http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
1418
+ /* utf.js - UTF-8 <=> UTF-16 convertion
1419
+ *
1420
+ * Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>
1421
+ * Version: 1.0
1422
+ * LastModified: Dec 25 1999
1423
+ * This library is free. You can redistribute it and/or modify it.
1409
1424
  */
1410
- var isHeader$2 = function isHeader(data, offset) {
1411
- /*
1412
- * http://id3.org/id3v2.3.0
1413
- * [0] = 'I'
1414
- * [1] = 'D'
1415
- * [2] = '3'
1416
- * [3,4] = {Version}
1417
- * [5] = {Flags}
1418
- * [6-9] = {ID3 Size}
1419
- *
1420
- * An ID3v2 tag can be detected with the following pattern:
1421
- * $49 44 33 yy yy xx zz zz zz zz
1422
- * Where yy is less than $FF, xx is the 'flags' byte and zz is less than $80
1423
- */
1424
- if (offset + 10 <= data.length) {
1425
- // look for 'ID3' identifier
1426
- if (data[offset] === 0x49 && data[offset + 1] === 0x44 && data[offset + 2] === 0x33) {
1427
- // check version is within range
1428
- if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {
1429
- // check size is within range
1430
- if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
1431
- return true;
1432
- }
1433
- }
1434
- }
1435
- }
1436
- return false;
1437
- };
1438
-
1439
1425
  /**
1440
- * Returns true if an ID3 footer can be found at offset in data
1441
- * @param data - The data to search
1442
- * @param offset - The offset at which to start searching
1426
+ * Converts a UTF-8 array to a string.
1427
+ *
1428
+ * @param array - The UTF-8 array to convert
1429
+ *
1430
+ * @returns The string
1431
+ *
1432
+ * @group Utils
1433
+ *
1434
+ * @beta
1443
1435
  */
1444
- var isFooter = function isFooter(data, offset) {
1445
- /*
1446
- * The footer is a copy of the header, but with a different identifier
1447
- */
1448
- if (offset + 10 <= data.length) {
1449
- // look for '3DI' identifier
1450
- if (data[offset] === 0x33 && data[offset + 1] === 0x44 && data[offset + 2] === 0x49) {
1451
- // check version is within range
1452
- if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {
1453
- // check size is within range
1454
- if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
1455
- return true;
1456
- }
1457
- }
1458
- }
1436
+ function utf8ArrayToStr(array, exitOnNull) {
1437
+ if (exitOnNull === void 0) {
1438
+ exitOnNull = false;
1459
1439
  }
1460
- return false;
1461
- };
1462
-
1463
- /**
1464
- * Returns any adjacent ID3 tags found in data starting at offset, as one block of data
1465
- * @param data - The data to search in
1466
- * @param offset - The offset at which to start searching
1467
- * @returns the block of data containing any ID3 tags found
1468
- * or *undefined* if no header is found at the starting offset
1469
- */
1470
- var getID3Data = function getID3Data(data, offset) {
1471
- var front = offset;
1472
- var length = 0;
1473
- while (isHeader$2(data, offset)) {
1474
- // ID3 header is 10 bytes
1475
- length += 10;
1476
- var size = readSize(data, offset + 6);
1477
- length += size;
1478
- if (isFooter(data, offset + 10)) {
1479
- // ID3 footer is 10 bytes
1480
- length += 10;
1440
+ if (typeof TextDecoder !== 'undefined') {
1441
+ var decoder = new TextDecoder('utf-8');
1442
+ var decoded = decoder.decode(array);
1443
+ if (exitOnNull) {
1444
+ // grab up to the first null
1445
+ var idx = decoded.indexOf('\0');
1446
+ return idx !== -1 ? decoded.substring(0, idx) : decoded;
1481
1447
  }
1482
- offset += length;
1483
- }
1484
- if (length > 0) {
1485
- return data.subarray(front, front + length);
1448
+ // remove any null characters
1449
+ return decoded.replace(/\0/g, '');
1486
1450
  }
1487
- return undefined;
1488
- };
1489
- var readSize = function readSize(data, offset) {
1490
- var size = 0;
1491
- size = (data[offset] & 0x7f) << 21;
1492
- size |= (data[offset + 1] & 0x7f) << 14;
1493
- size |= (data[offset + 2] & 0x7f) << 7;
1494
- size |= data[offset + 3] & 0x7f;
1495
- return size;
1496
- };
1497
- var canParse$2 = function canParse(data, offset) {
1498
- return isHeader$2(data, offset) && readSize(data, offset + 6) + 10 <= data.length - offset;
1499
- };
1500
-
1501
- /**
1502
- * Searches for the Elementary Stream timestamp found in the ID3 data chunk
1503
- * @param data - Block of data containing one or more ID3 tags
1504
- */
1505
- var getTimeStamp = function getTimeStamp(data) {
1506
- var frames = getID3Frames(data);
1507
- for (var i = 0; i < frames.length; i++) {
1508
- var frame = frames[i];
1509
- if (isTimeStampFrame(frame)) {
1510
- return readTimeStamp(frame);
1451
+ var len = array.length;
1452
+ var c;
1453
+ var char2;
1454
+ var char3;
1455
+ var out = '';
1456
+ var i = 0;
1457
+ while (i < len) {
1458
+ c = array[i++];
1459
+ if (c === 0x00 && exitOnNull) {
1460
+ return out;
1461
+ } else if (c === 0x00 || c === 0x03) {
1462
+ // If the character is 3 (END_OF_TEXT) or 0 (NULL) then skip it
1463
+ continue;
1464
+ }
1465
+ switch (c >> 4) {
1466
+ case 0:
1467
+ case 1:
1468
+ case 2:
1469
+ case 3:
1470
+ case 4:
1471
+ case 5:
1472
+ case 6:
1473
+ case 7:
1474
+ // 0xxxxxxx
1475
+ out += String.fromCharCode(c);
1476
+ break;
1477
+ case 12:
1478
+ case 13:
1479
+ // 110x xxxx 10xx xxxx
1480
+ char2 = array[i++];
1481
+ out += String.fromCharCode((c & 0x1f) << 6 | char2 & 0x3f);
1482
+ break;
1483
+ case 14:
1484
+ // 1110 xxxx 10xx xxxx 10xx xxxx
1485
+ char2 = array[i++];
1486
+ char3 = array[i++];
1487
+ out += String.fromCharCode((c & 0x0f) << 12 | (char2 & 0x3f) << 6 | (char3 & 0x3f) << 0);
1488
+ break;
1511
1489
  }
1512
1490
  }
1513
- return undefined;
1514
- };
1491
+ return out;
1492
+ }
1515
1493
 
1516
1494
  /**
1517
- * Returns true if the ID3 frame is an Elementary Stream timestamp frame
1495
+ * hex dump helper class
1518
1496
  */
1519
- var isTimeStampFrame = function isTimeStampFrame(frame) {
1520
- return frame && frame.key === 'PRIV' && frame.info === 'com.apple.streaming.transportStreamTimestamp';
1521
- };
1522
- var getFrameData = function getFrameData(data) {
1523
- /*
1524
- Frame ID $xx xx xx xx (four characters)
1525
- Size $xx xx xx xx
1526
- Flags $xx xx
1527
- */
1528
- var type = String.fromCharCode(data[0], data[1], data[2], data[3]);
1529
- var size = readSize(data, 4);
1530
-
1531
- // skip frame id, size, and flags
1532
- var offset = 10;
1533
- return {
1534
- type: type,
1535
- size: size,
1536
- data: data.subarray(offset, offset + size)
1537
- };
1538
- };
1539
1497
 
1540
- /**
1541
- * Returns an array of ID3 frames found in all the ID3 tags in the id3Data
1542
- * @param id3Data - The ID3 data containing one or more ID3 tags
1543
- */
1544
- var getID3Frames = function getID3Frames(id3Data) {
1545
- var offset = 0;
1546
- var frames = [];
1547
- while (isHeader$2(id3Data, offset)) {
1548
- var size = readSize(id3Data, offset + 6);
1549
- // skip past ID3 header
1550
- offset += 10;
1551
- var end = offset + size;
1552
- // loop through frames in the ID3 tag
1553
- while (offset + 8 < end) {
1554
- var frameData = getFrameData(id3Data.subarray(offset));
1555
- var frame = decodeFrame(frameData);
1556
- if (frame) {
1557
- frames.push(frame);
1498
+ var Hex = {
1499
+ hexDump: function hexDump(array) {
1500
+ var str = '';
1501
+ for (var i = 0; i < array.length; i++) {
1502
+ var h = array[i].toString(16);
1503
+ if (h.length < 2) {
1504
+ h = '0' + h;
1558
1505
  }
1559
-
1560
- // skip frame header and frame data
1561
- offset += frameData.size + 10;
1562
- }
1563
- if (isFooter(id3Data, offset)) {
1564
- offset += 10;
1506
+ str += h;
1565
1507
  }
1508
+ return str;
1566
1509
  }
1567
- return frames;
1568
- };
1569
- var decodeFrame = function decodeFrame(frame) {
1570
- if (frame.type === 'PRIV') {
1571
- return decodePrivFrame(frame);
1572
- } else if (frame.type[0] === 'W') {
1573
- return decodeURLFrame(frame);
1574
- }
1575
- return decodeTextFrame(frame);
1576
1510
  };
1577
- var decodePrivFrame = function decodePrivFrame(frame) {
1578
- /*
1579
- Format: <text string>\0<binary data>
1580
- */
1581
- if (frame.size < 2) {
1582
- return undefined;
1583
- }
1584
- var owner = utf8ArrayToStr(frame.data, true);
1585
- var privateData = new Uint8Array(frame.data.subarray(owner.length + 1));
1586
- return {
1587
- key: frame.type,
1588
- info: owner,
1589
- data: privateData.buffer
1590
- };
1591
- };
1592
- var decodeTextFrame = function decodeTextFrame(frame) {
1593
- if (frame.size < 2) {
1594
- return undefined;
1595
- }
1596
- if (frame.type === 'TXXX') {
1597
- /*
1598
- Format:
1599
- [0] = {Text Encoding}
1600
- [1-?] = {Description}\0{Value}
1601
- */
1602
- var index = 1;
1603
- var description = utf8ArrayToStr(frame.data.subarray(index), true);
1604
- index += description.length + 1;
1605
- var value = utf8ArrayToStr(frame.data.subarray(index));
1606
- return {
1607
- key: frame.type,
1608
- info: description,
1609
- data: value
1610
- };
1611
- }
1612
- /*
1613
- Format:
1614
- [0] = {Text Encoding}
1615
- [1-?] = {Value}
1616
- */
1617
- var text = utf8ArrayToStr(frame.data.subarray(1));
1618
- return {
1619
- key: frame.type,
1620
- data: text
1621
- };
1622
- };
1623
- var decodeURLFrame = function decodeURLFrame(frame) {
1624
- if (frame.type === 'WXXX') {
1625
- /*
1626
- Format:
1627
- [0] = {Text Encoding}
1628
- [1-?] = {Description}\0{URL}
1629
- */
1630
- if (frame.size < 2) {
1631
- return undefined;
1632
- }
1633
- var index = 1;
1634
- var description = utf8ArrayToStr(frame.data.subarray(index), true);
1635
- index += description.length + 1;
1636
- var value = utf8ArrayToStr(frame.data.subarray(index));
1637
- return {
1638
- key: frame.type,
1639
- info: description,
1640
- data: value
1641
- };
1642
- }
1643
- /*
1644
- Format:
1645
- [0-?] = {URL}
1646
- */
1647
- var url = utf8ArrayToStr(frame.data);
1648
- return {
1649
- key: frame.type,
1650
- data: url
1651
- };
1652
- };
1653
- var readTimeStamp = function readTimeStamp(timeStampFrame) {
1654
- if (timeStampFrame.data.byteLength === 8) {
1655
- var data = new Uint8Array(timeStampFrame.data);
1656
- // timestamp is 33 bit expressed as a big-endian eight-octet number,
1657
- // with the upper 31 bits set to zero.
1658
- var pts33Bit = data[3] & 0x1;
1659
- var timestamp = (data[4] << 23) + (data[5] << 15) + (data[6] << 7) + data[7];
1660
- timestamp /= 45;
1661
- if (pts33Bit) {
1662
- timestamp += 47721858.84;
1663
- } // 2^32 / 90
1664
-
1665
- return Math.round(timestamp);
1666
- }
1667
- return undefined;
1668
- };
1669
-
1670
- // http://stackoverflow.com/questions/8936984/uint8array-to-string-in-javascript/22373197
1671
- // http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
1672
- /* utf.js - UTF-8 <=> UTF-16 convertion
1673
- *
1674
- * Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>
1675
- * Version: 1.0
1676
- * LastModified: Dec 25 1999
1677
- * This library is free. You can redistribute it and/or modify it.
1678
- */
1679
- var utf8ArrayToStr = function utf8ArrayToStr(array, exitOnNull) {
1680
- if (exitOnNull === void 0) {
1681
- exitOnNull = false;
1682
- }
1683
- var decoder = getTextDecoder();
1684
- if (decoder) {
1685
- var decoded = decoder.decode(array);
1686
- if (exitOnNull) {
1687
- // grab up to the first null
1688
- var idx = decoded.indexOf('\0');
1689
- return idx !== -1 ? decoded.substring(0, idx) : decoded;
1690
- }
1691
-
1692
- // remove any null characters
1693
- return decoded.replace(/\0/g, '');
1694
- }
1695
- var len = array.length;
1696
- var c;
1697
- var char2;
1698
- var char3;
1699
- var out = '';
1700
- var i = 0;
1701
- while (i < len) {
1702
- c = array[i++];
1703
- if (c === 0x00 && exitOnNull) {
1704
- return out;
1705
- } else if (c === 0x00 || c === 0x03) {
1706
- // If the character is 3 (END_OF_TEXT) or 0 (NULL) then skip it
1707
- continue;
1708
- }
1709
- switch (c >> 4) {
1710
- case 0:
1711
- case 1:
1712
- case 2:
1713
- case 3:
1714
- case 4:
1715
- case 5:
1716
- case 6:
1717
- case 7:
1718
- // 0xxxxxxx
1719
- out += String.fromCharCode(c);
1720
- break;
1721
- case 12:
1722
- case 13:
1723
- // 110x xxxx 10xx xxxx
1724
- char2 = array[i++];
1725
- out += String.fromCharCode((c & 0x1f) << 6 | char2 & 0x3f);
1726
- break;
1727
- case 14:
1728
- // 1110 xxxx 10xx xxxx 10xx xxxx
1729
- char2 = array[i++];
1730
- char3 = array[i++];
1731
- out += String.fromCharCode((c & 0x0f) << 12 | (char2 & 0x3f) << 6 | (char3 & 0x3f) << 0);
1732
- break;
1733
- }
1734
- }
1735
- return out;
1736
- };
1737
- var decoder;
1738
- function getTextDecoder() {
1739
- // On Play Station 4, TextDecoder is defined but partially implemented.
1740
- // Manual decoding option is preferable
1741
- if (navigator.userAgent.includes('PlayStation 4')) {
1742
- return;
1743
- }
1744
- if (!decoder && typeof self.TextDecoder !== 'undefined') {
1745
- decoder = new self.TextDecoder('utf-8');
1746
- }
1747
- return decoder;
1748
- }
1749
-
1750
- /**
1751
- * hex dump helper class
1752
- */
1753
-
1754
- var Hex = {
1755
- hexDump: function hexDump(array) {
1756
- var str = '';
1757
- for (var i = 0; i < array.length; i++) {
1758
- var h = array[i].toString(16);
1759
- if (h.length < 2) {
1760
- h = '0' + h;
1761
- }
1762
- str += h;
1763
- }
1764
- return str;
1765
- }
1766
- };
1767
-
1768
- var UINT32_MAX$1 = Math.pow(2, 32) - 1;
1769
- var push = [].push;
1770
-
1771
- // We are using fixed track IDs for driving the MP4 remuxer
1772
- // instead of following the TS PIDs.
1773
- // There is no reason not to do this and some browsers/SourceBuffer-demuxers
1774
- // may not like if there are TrackID "switches"
1775
- // See https://github.com/video-dev/hls.js/issues/1331
1776
- // Here we are mapping our internal track types to constant MP4 track IDs
1777
- // With MSE currently one can only have one track of each, and we are muxing
1778
- // whatever video/audio rendition in them.
1779
- var RemuxerTrackIdConfig = {
1780
- video: 1,
1781
- audio: 2,
1782
- id3: 3,
1783
- text: 4
1511
+
1512
+ var UINT32_MAX$1 = Math.pow(2, 32) - 1;
1513
+ var push = [].push;
1514
+
1515
+ // We are using fixed track IDs for driving the MP4 remuxer
1516
+ // instead of following the TS PIDs.
1517
+ // There is no reason not to do this and some browsers/SourceBuffer-demuxers
1518
+ // may not like if there are TrackID "switches"
1519
+ // See https://github.com/video-dev/hls.js/issues/1331
1520
+ // Here we are mapping our internal track types to constant MP4 track IDs
1521
+ // With MSE currently one can only have one track of each, and we are muxing
1522
+ // whatever video/audio rendition in them.
1523
+ var RemuxerTrackIdConfig = {
1524
+ video: 1,
1525
+ audio: 2,
1526
+ id3: 3,
1527
+ text: 4
1784
1528
  };
1785
1529
  function bin2str(data) {
1786
1530
  return String.fromCharCode.apply(null, data);
@@ -4637,42 +4381,551 @@
4637
4381
  return mid;
4638
4382
  }
4639
4383
  }
4640
- // At this point, left and right have swapped.
4641
- // No direct match was found, left or right element must be the closest. Check which one has the smallest diff.
4642
- return cues[left].startTime - time < time - cues[right].startTime ? left : right;
4384
+ // At this point, left and right have swapped.
4385
+ // No direct match was found, left or right element must be the closest. Check which one has the smallest diff.
4386
+ return cues[left].startTime - time < time - cues[right].startTime ? left : right;
4387
+ }
4388
+ function getCuesInRange(cues, start, end) {
4389
+ var cuesFound = [];
4390
+ var firstCueInRange = getFirstCueIndexAfterTime(cues, start);
4391
+ if (firstCueInRange > -1) {
4392
+ for (var i = firstCueInRange, len = cues.length; i < len; i++) {
4393
+ var _cue = cues[i];
4394
+ if (_cue.startTime >= start && _cue.endTime <= end) {
4395
+ cuesFound.push(_cue);
4396
+ } else if (_cue.startTime > end) {
4397
+ return cuesFound;
4398
+ }
4399
+ }
4400
+ }
4401
+ return cuesFound;
4402
+ }
4403
+ function filterSubtitleTracks(textTrackList) {
4404
+ var tracks = [];
4405
+ for (var i = 0; i < textTrackList.length; i++) {
4406
+ var track = textTrackList[i];
4407
+ // Edge adds a track without a label; we don't want to use it
4408
+ if ((track.kind === 'subtitles' || track.kind === 'captions') && track.label) {
4409
+ tracks.push(textTrackList[i]);
4410
+ }
4411
+ }
4412
+ return tracks;
4413
+ }
4414
+
4415
+ var MetadataSchema = {
4416
+ audioId3: "org.id3",
4417
+ dateRange: "com.apple.quicktime.HLS",
4418
+ emsg: "https://aomedia.org/emsg/ID3"
4419
+ };
4420
+
4421
+ /**
4422
+ * Decode an ID3 PRIV frame.
4423
+ *
4424
+ * @param frame - the ID3 PRIV frame
4425
+ *
4426
+ * @returns The decoded ID3 PRIV frame
4427
+ *
4428
+ * @internal
4429
+ *
4430
+ * @group ID3
4431
+ */
4432
+ function decodeId3PrivFrame(frame) {
4433
+ /*
4434
+ Format: <text string>\0<binary data>
4435
+ */
4436
+ if (frame.size < 2) {
4437
+ return undefined;
4438
+ }
4439
+ var owner = utf8ArrayToStr(frame.data, true);
4440
+ var privateData = new Uint8Array(frame.data.subarray(owner.length + 1));
4441
+ return {
4442
+ key: frame.type,
4443
+ info: owner,
4444
+ data: privateData.buffer
4445
+ };
4446
+ }
4447
+
4448
+ /**
4449
+ * Decodes an ID3 text frame
4450
+ *
4451
+ * @param frame - the ID3 text frame
4452
+ *
4453
+ * @returns The decoded ID3 text frame
4454
+ *
4455
+ * @internal
4456
+ *
4457
+ * @group ID3
4458
+ */
4459
+ function decodeId3TextFrame(frame) {
4460
+ if (frame.size < 2) {
4461
+ return undefined;
4462
+ }
4463
+ if (frame.type === 'TXXX') {
4464
+ /*
4465
+ Format:
4466
+ [0] = {Text Encoding}
4467
+ [1-?] = {Description}\0{Value}
4468
+ */
4469
+ var index = 1;
4470
+ var description = utf8ArrayToStr(frame.data.subarray(index), true);
4471
+ index += description.length + 1;
4472
+ var value = utf8ArrayToStr(frame.data.subarray(index));
4473
+ return {
4474
+ key: frame.type,
4475
+ info: description,
4476
+ data: value
4477
+ };
4478
+ }
4479
+ /*
4480
+ Format:
4481
+ [0] = {Text Encoding}
4482
+ [1-?] = {Value}
4483
+ */
4484
+ var text = utf8ArrayToStr(frame.data.subarray(1));
4485
+ return {
4486
+ key: frame.type,
4487
+ info: '',
4488
+ data: text
4489
+ };
4490
+ }
4491
+
4492
+ /**
4493
+ * Decode a URL frame
4494
+ *
4495
+ * @param frame - the ID3 URL frame
4496
+ *
4497
+ * @returns The decoded ID3 URL frame
4498
+ *
4499
+ * @internal
4500
+ *
4501
+ * @group ID3
4502
+ */
4503
+ function decodeId3UrlFrame(frame) {
4504
+ if (frame.type === 'WXXX') {
4505
+ /*
4506
+ Format:
4507
+ [0] = {Text Encoding}
4508
+ [1-?] = {Description}\0{URL}
4509
+ */
4510
+ if (frame.size < 2) {
4511
+ return undefined;
4512
+ }
4513
+ var index = 1;
4514
+ var description = utf8ArrayToStr(frame.data.subarray(index), true);
4515
+ index += description.length + 1;
4516
+ var value = utf8ArrayToStr(frame.data.subarray(index));
4517
+ return {
4518
+ key: frame.type,
4519
+ info: description,
4520
+ data: value
4521
+ };
4522
+ }
4523
+ /*
4524
+ Format:
4525
+ [0-?] = {URL}
4526
+ */
4527
+ var url = utf8ArrayToStr(frame.data);
4528
+ return {
4529
+ key: frame.type,
4530
+ info: '',
4531
+ data: url
4532
+ };
4533
+ }
4534
+
4535
+ function toUint8(data, offset, length) {
4536
+ if (offset === void 0) {
4537
+ offset = 0;
4538
+ }
4539
+ if (length === void 0) {
4540
+ length = Infinity;
4541
+ }
4542
+ return view(data, offset, length, Uint8Array);
4543
+ }
4544
+ function view(data, offset, length, Type) {
4545
+ var buffer = unsafeGetArrayBuffer(data);
4546
+ var bytesPerElement = 1;
4547
+ if ('BYTES_PER_ELEMENT' in Type) {
4548
+ bytesPerElement = Type.BYTES_PER_ELEMENT;
4549
+ }
4550
+ // Absolute end of the |data| view within |buffer|.
4551
+ var dataOffset = isArrayBufferView(data) ? data.byteOffset : 0;
4552
+ var dataEnd = (dataOffset + data.byteLength) / bytesPerElement;
4553
+ // Absolute start of the result within |buffer|.
4554
+ var rawStart = (dataOffset + offset) / bytesPerElement;
4555
+ var start = Math.floor(Math.max(0, Math.min(rawStart, dataEnd)));
4556
+ // Absolute end of the result within |buffer|.
4557
+ var end = Math.floor(Math.min(start + Math.max(length, 0), dataEnd));
4558
+ return new Type(buffer, start, end - start);
4559
+ }
4560
+ function unsafeGetArrayBuffer(view) {
4561
+ if (view instanceof ArrayBuffer) {
4562
+ return view;
4563
+ } else {
4564
+ return view.buffer;
4565
+ }
4566
+ }
4567
+ function isArrayBufferView(obj) {
4568
+ return obj && obj.buffer instanceof ArrayBuffer && obj.byteLength !== undefined && obj.byteOffset !== undefined;
4569
+ }
4570
+
4571
+ function toArrayBuffer(view) {
4572
+ if (view instanceof ArrayBuffer) {
4573
+ return view;
4574
+ } else {
4575
+ if (view.byteOffset == 0 && view.byteLength == view.buffer.byteLength) {
4576
+ // This is a TypedArray over the whole buffer.
4577
+ return view.buffer;
4578
+ }
4579
+ // This is a 'view' on the buffer. Create a new buffer that only contains
4580
+ // the data. Note that since this isn't an ArrayBuffer, the 'new' call
4581
+ // will allocate a new buffer to hold the copy.
4582
+ return new Uint8Array(view).buffer;
4583
+ }
4584
+ }
4585
+
4586
+ /**
4587
+ * Encodes binary data to base64
4588
+ *
4589
+ * @param binary - The binary data to encode
4590
+ * @returns The base64 encoded string
4591
+ *
4592
+ * @group Utils
4593
+ *
4594
+ * @beta
4595
+ */
4596
+ function base64encode(binary) {
4597
+ return btoa(String.fromCharCode.apply(String, binary));
4598
+ }
4599
+
4600
+ /**
4601
+ * This implements the rounding procedure described in step 2 of the "Serializing a Decimal" specification.
4602
+ * This rounding style is known as "even rounding", "banker's rounding", or "commercial rounding".
4603
+ *
4604
+ * @param value - The value to round
4605
+ * @param precision - The number of decimal places to round to
4606
+ * @returns The rounded value
4607
+ *
4608
+ * @group Utils
4609
+ *
4610
+ * @beta
4611
+ */
4612
+ function roundToEven(value, precision) {
4613
+ if (value < 0) {
4614
+ return -roundToEven(-value, precision);
4615
+ }
4616
+ var decimalShift = Math.pow(10, precision);
4617
+ var isEquidistant = Math.abs(value * decimalShift % 1 - 0.5) < Number.EPSILON;
4618
+ if (isEquidistant) {
4619
+ // If the tail of the decimal place is 'equidistant' we round to the nearest even value
4620
+ var flooredValue = Math.floor(value * decimalShift);
4621
+ return (flooredValue % 2 === 0 ? flooredValue : flooredValue + 1) / decimalShift;
4622
+ } else {
4623
+ // Otherwise, proceed as normal
4624
+ return Math.round(value * decimalShift) / decimalShift;
4625
+ }
4626
+ }
4627
+
4628
+ /**
4629
+ * Constructs a relative path from a URL.
4630
+ *
4631
+ * @param url - The destination URL
4632
+ * @param base - The base URL
4633
+ * @returns The relative path
4634
+ *
4635
+ * @group Utils
4636
+ *
4637
+ * @beta
4638
+ */
4639
+ function urlToRelativePath(url, base) {
4640
+ var to = new URL(url);
4641
+ var from = new URL(base);
4642
+ if (to.origin !== from.origin) {
4643
+ return url;
4644
+ }
4645
+ var toPath = to.pathname.split('/').slice(1);
4646
+ var fromPath = from.pathname.split('/').slice(1, -1);
4647
+ // remove common parents
4648
+ while (toPath[0] === fromPath[0]) {
4649
+ toPath.shift();
4650
+ fromPath.shift();
4651
+ }
4652
+ // add back paths
4653
+ while (fromPath.length) {
4654
+ fromPath.shift();
4655
+ toPath.unshift('..');
4656
+ }
4657
+ return toPath.join('/');
4658
+ }
4659
+
4660
+ /**
4661
+ * Generate a random v4 UUID
4662
+ *
4663
+ * @returns A random v4 UUID
4664
+ *
4665
+ * @group Utils
4666
+ *
4667
+ * @beta
4668
+ */
4669
+ function uuid() {
4670
+ try {
4671
+ return crypto.randomUUID();
4672
+ } catch (error) {
4673
+ try {
4674
+ var url = URL.createObjectURL(new Blob());
4675
+ var _uuid = url.toString();
4676
+ URL.revokeObjectURL(url);
4677
+ return _uuid.slice(_uuid.lastIndexOf('/') + 1);
4678
+ } catch (error) {
4679
+ var dt = new Date().getTime();
4680
+ var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
4681
+ var r = (dt + Math.random() * 16) % 16 | 0;
4682
+ dt = Math.floor(dt / 16);
4683
+ return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
4684
+ });
4685
+ return _uuid2;
4686
+ }
4687
+ }
4688
+ }
4689
+
4690
+ function decodeId3ImageFrame(frame) {
4691
+ var metadataFrame = {
4692
+ key: frame.type,
4693
+ description: '',
4694
+ data: '',
4695
+ mimeType: null,
4696
+ pictureType: null
4697
+ };
4698
+ var utf8Encoding = 0x03;
4699
+ if (frame.size < 2) {
4700
+ return undefined;
4701
+ }
4702
+ if (frame.data[0] !== utf8Encoding) {
4703
+ console.log('Ignore frame with unrecognized character ' + 'encoding');
4704
+ return undefined;
4705
+ }
4706
+ var mimeTypeEndIndex = frame.data.subarray(1).indexOf(0);
4707
+ if (mimeTypeEndIndex === -1) {
4708
+ return undefined;
4709
+ }
4710
+ var mimeType = utf8ArrayToStr(toUint8(frame.data, 1, mimeTypeEndIndex));
4711
+ var pictureType = frame.data[2 + mimeTypeEndIndex];
4712
+ var descriptionEndIndex = frame.data.subarray(3 + mimeTypeEndIndex).indexOf(0);
4713
+ if (descriptionEndIndex === -1) {
4714
+ return undefined;
4715
+ }
4716
+ var description = utf8ArrayToStr(toUint8(frame.data, 3 + mimeTypeEndIndex, descriptionEndIndex));
4717
+ var data;
4718
+ if (mimeType === '-->') {
4719
+ data = utf8ArrayToStr(toUint8(frame.data, 4 + mimeTypeEndIndex + descriptionEndIndex));
4720
+ } else {
4721
+ data = toArrayBuffer(frame.data.subarray(4 + mimeTypeEndIndex + descriptionEndIndex));
4722
+ }
4723
+ metadataFrame.mimeType = mimeType;
4724
+ metadataFrame.pictureType = pictureType;
4725
+ metadataFrame.description = description;
4726
+ metadataFrame.data = data;
4727
+ return metadataFrame;
4728
+ }
4729
+
4730
+ /**
4731
+ * Decode an ID3 frame.
4732
+ *
4733
+ * @param frame - the ID3 frame
4734
+ *
4735
+ * @returns The decoded ID3 frame
4736
+ *
4737
+ * @internal
4738
+ *
4739
+ * @group ID3
4740
+ */
4741
+ function decodeId3Frame(frame) {
4742
+ if (frame.type === 'PRIV') {
4743
+ return decodeId3PrivFrame(frame);
4744
+ } else if (frame.type[0] === 'W') {
4745
+ return decodeId3UrlFrame(frame);
4746
+ } else if (frame.type === 'APIC') {
4747
+ return decodeId3ImageFrame(frame);
4748
+ }
4749
+ return decodeId3TextFrame(frame);
4750
+ }
4751
+
4752
+ /**
4753
+ * Read ID3 size
4754
+ *
4755
+ * @param data - The data to read from
4756
+ * @param offset - The offset at which to start reading
4757
+ *
4758
+ * @returns The size
4759
+ *
4760
+ * @internal
4761
+ *
4762
+ * @group ID3
4763
+ */
4764
+ function readId3Size(data, offset) {
4765
+ var size = 0;
4766
+ size = (data[offset] & 0x7f) << 21;
4767
+ size |= (data[offset + 1] & 0x7f) << 14;
4768
+ size |= (data[offset + 2] & 0x7f) << 7;
4769
+ size |= data[offset + 3] & 0x7f;
4770
+ return size;
4771
+ }
4772
+
4773
+ /**
4774
+ * Returns the data of an ID3 frame.
4775
+ *
4776
+ * @param data - The data to read from
4777
+ *
4778
+ * @returns The data of the ID3 frame
4779
+ *
4780
+ * @internal
4781
+ *
4782
+ * @group ID3
4783
+ */
4784
+ function getId3FrameData(data) {
4785
+ /*
4786
+ Frame ID $xx xx xx xx (four characters)
4787
+ Size $xx xx xx xx
4788
+ Flags $xx xx
4789
+ */
4790
+ var type = String.fromCharCode(data[0], data[1], data[2], data[3]);
4791
+ var size = readId3Size(data, 4);
4792
+ // skip frame id, size, and flags
4793
+ var offset = 10;
4794
+ return {
4795
+ type: type,
4796
+ size: size,
4797
+ data: data.subarray(offset, offset + size)
4798
+ };
4799
+ }
4800
+
4801
+ /**
4802
+ * Returns true if an ID3 footer can be found at offset in data
4803
+ *
4804
+ * @param data - The data to search in
4805
+ * @param offset - The offset at which to start searching
4806
+ *
4807
+ * @returns `true` if an ID3 footer is found
4808
+ *
4809
+ * @internal
4810
+ *
4811
+ * @group ID3
4812
+ */
4813
+ function isId3Footer(data, offset) {
4814
+ /*
4815
+ * The footer is a copy of the header, but with a different identifier
4816
+ */
4817
+ if (offset + 10 <= data.length) {
4818
+ // look for '3DI' identifier
4819
+ if (data[offset] === 0x33 && data[offset + 1] === 0x44 && data[offset + 2] === 0x49) {
4820
+ // check version is within range
4821
+ if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {
4822
+ // check size is within range
4823
+ if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
4824
+ return true;
4825
+ }
4826
+ }
4827
+ }
4828
+ }
4829
+ return false;
4830
+ }
4831
+
4832
+ /**
4833
+ * Returns true if an ID3 header can be found at offset in data
4834
+ *
4835
+ * @param data - The data to search in
4836
+ * @param offset - The offset at which to start searching
4837
+ *
4838
+ * @returns `true` if an ID3 header is found
4839
+ *
4840
+ * @internal
4841
+ *
4842
+ * @group ID3
4843
+ */
4844
+ function isId3Header(data, offset) {
4845
+ /*
4846
+ * http://id3.org/id3v2.3.0
4847
+ * [0] = 'I'
4848
+ * [1] = 'D'
4849
+ * [2] = '3'
4850
+ * [3,4] = {Version}
4851
+ * [5] = {Flags}
4852
+ * [6-9] = {ID3 Size}
4853
+ *
4854
+ * An ID3v2 tag can be detected with the following pattern:
4855
+ * $49 44 33 yy yy xx zz zz zz zz
4856
+ * Where yy is less than $FF, xx is the 'flags' byte and zz is less than $80
4857
+ */
4858
+ if (offset + 10 <= data.length) {
4859
+ // look for 'ID3' identifier
4860
+ if (data[offset] === 0x49 && data[offset + 1] === 0x44 && data[offset + 2] === 0x33) {
4861
+ // check version is within range
4862
+ if (data[offset + 3] < 0xff && data[offset + 4] < 0xff) {
4863
+ // check size is within range
4864
+ if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
4865
+ return true;
4866
+ }
4867
+ }
4868
+ }
4869
+ }
4870
+ return false;
4643
4871
  }
4644
- function getCuesInRange(cues, start, end) {
4645
- var cuesFound = [];
4646
- var firstCueInRange = getFirstCueIndexAfterTime(cues, start);
4647
- if (firstCueInRange > -1) {
4648
- for (var i = firstCueInRange, len = cues.length; i < len; i++) {
4649
- var _cue = cues[i];
4650
- if (_cue.startTime >= start && _cue.endTime <= end) {
4651
- cuesFound.push(_cue);
4652
- } else if (_cue.startTime > end) {
4653
- return cuesFound;
4872
+
4873
+ var HEADER_FOOTER_SIZE = 10;
4874
+ var FRAME_SIZE = 10;
4875
+ /**
4876
+ * Returns an array of ID3 frames found in all the ID3 tags in the id3Data
4877
+ *
4878
+ * @param id3Data - The ID3 data containing one or more ID3 tags
4879
+ *
4880
+ * @returns Array of ID3 frame objects
4881
+ *
4882
+ * @group ID3
4883
+ *
4884
+ * @beta
4885
+ */
4886
+ function getId3Frames(id3Data) {
4887
+ var offset = 0;
4888
+ var frames = [];
4889
+ while (isId3Header(id3Data, offset)) {
4890
+ var size = readId3Size(id3Data, offset + 6);
4891
+ if (id3Data[offset + 5] >> 6 & 1) {
4892
+ // skip extended header
4893
+ offset += HEADER_FOOTER_SIZE;
4894
+ }
4895
+ // skip past ID3 header
4896
+ offset += HEADER_FOOTER_SIZE;
4897
+ var end = offset + size;
4898
+ // loop through frames in the ID3 tag
4899
+ while (offset + FRAME_SIZE < end) {
4900
+ var frameData = getId3FrameData(id3Data.subarray(offset));
4901
+ var frame = decodeId3Frame(frameData);
4902
+ if (frame) {
4903
+ frames.push(frame);
4654
4904
  }
4905
+ // skip frame header and frame data
4906
+ offset += frameData.size + HEADER_FOOTER_SIZE;
4655
4907
  }
4656
- }
4657
- return cuesFound;
4658
- }
4659
- function filterSubtitleTracks(textTrackList) {
4660
- var tracks = [];
4661
- for (var i = 0; i < textTrackList.length; i++) {
4662
- var track = textTrackList[i];
4663
- // Edge adds a track without a label; we don't want to use it
4664
- if ((track.kind === 'subtitles' || track.kind === 'captions') && track.label) {
4665
- tracks.push(textTrackList[i]);
4908
+ if (isId3Footer(id3Data, offset)) {
4909
+ offset += HEADER_FOOTER_SIZE;
4666
4910
  }
4667
4911
  }
4668
- return tracks;
4912
+ return frames;
4669
4913
  }
4670
4914
 
4671
- var MetadataSchema = {
4672
- audioId3: "org.id3",
4673
- dateRange: "com.apple.quicktime.HLS",
4674
- emsg: "https://aomedia.org/emsg/ID3"
4675
- };
4915
+ /**
4916
+ * Returns true if the ID3 frame is an Elementary Stream timestamp frame
4917
+ *
4918
+ * @param frame - the ID3 frame
4919
+ *
4920
+ * @returns `true` if the ID3 frame is an Elementary Stream timestamp frame
4921
+ *
4922
+ * @internal
4923
+ *
4924
+ * @group ID3
4925
+ */
4926
+ function isId3TimestampFrame(frame) {
4927
+ return frame && frame.key === 'PRIV' && frame.info === 'com.apple.streaming.transportStreamTimestamp';
4928
+ }
4676
4929
 
4677
4930
  var MIN_CUE_DURATION = 0.25;
4678
4931
  function getCueClass() {
@@ -4809,7 +5062,7 @@
4809
5062
  if (type === MetadataSchema.emsg && !enableEmsgMetadataCues || !enableID3MetadataCues) {
4810
5063
  continue;
4811
5064
  }
4812
- var frames = getID3Frames(samples[i].data);
5065
+ var frames = getId3Frames(samples[i].data);
4813
5066
  if (frames) {
4814
5067
  var startTime = samples[i].pts;
4815
5068
  var endTime = startTime + samples[i].duration;
@@ -4823,7 +5076,7 @@
4823
5076
  for (var j = 0; j < frames.length; j++) {
4824
5077
  var frame = frames[j];
4825
5078
  // Safari doesn't put the timestamp frame in the TextTrack
4826
- if (!isTimeStampFrame(frame)) {
5079
+ if (!isId3TimestampFrame(frame)) {
4827
5080
  // add a bounds to any unbounded cues
4828
5081
  this.updateId3CueEnds(startTime, type);
4829
5082
  var cue = createCueWithDataFields(Cue, startTime, endTime, frame, type);
@@ -10900,6 +11153,104 @@
10900
11153
  };
10901
11154
  }
10902
11155
 
11156
+ /**
11157
+ * Returns any adjacent ID3 tags found in data starting at offset, as one block of data
11158
+ *
11159
+ * @param data - The data to search in
11160
+ * @param offset - The offset at which to start searching
11161
+ *
11162
+ * @returns The block of data containing any ID3 tags found
11163
+ * or `undefined` if no header is found at the starting offset
11164
+ *
11165
+ * @internal
11166
+ *
11167
+ * @group ID3
11168
+ */
11169
+ function getId3Data(data, offset) {
11170
+ var front = offset;
11171
+ var length = 0;
11172
+ while (isId3Header(data, offset)) {
11173
+ // ID3 header is 10 bytes
11174
+ length += 10;
11175
+ var size = readId3Size(data, offset + 6);
11176
+ length += size;
11177
+ if (isId3Footer(data, offset + 10)) {
11178
+ // ID3 footer is 10 bytes
11179
+ length += 10;
11180
+ }
11181
+ offset += length;
11182
+ }
11183
+ if (length > 0) {
11184
+ return data.subarray(front, front + length);
11185
+ }
11186
+ return undefined;
11187
+ }
11188
+
11189
+ /**
11190
+ * Read a 33 bit timestamp from an ID3 frame.
11191
+ *
11192
+ * @param timeStampFrame - the ID3 frame
11193
+ *
11194
+ * @returns The timestamp
11195
+ *
11196
+ * @internal
11197
+ *
11198
+ * @group ID3
11199
+ */
11200
+ function readId3Timestamp(timeStampFrame) {
11201
+ if (timeStampFrame.data.byteLength === 8) {
11202
+ var data = new Uint8Array(timeStampFrame.data);
11203
+ // timestamp is 33 bit expressed as a big-endian eight-octet number,
11204
+ // with the upper 31 bits set to zero.
11205
+ var pts33Bit = data[3] & 0x1;
11206
+ var timestamp = (data[4] << 23) + (data[5] << 15) + (data[6] << 7) + data[7];
11207
+ timestamp /= 45;
11208
+ if (pts33Bit) {
11209
+ timestamp += 47721858.84;
11210
+ } // 2^32 / 90
11211
+ return Math.round(timestamp);
11212
+ }
11213
+ return undefined;
11214
+ }
11215
+
11216
+ /**
11217
+ * Searches for the Elementary Stream timestamp found in the ID3 data chunk
11218
+ *
11219
+ * @param data - Block of data containing one or more ID3 tags
11220
+ *
11221
+ * @returns The timestamp
11222
+ *
11223
+ * @group ID3
11224
+ *
11225
+ * @beta
11226
+ */
11227
+ function getId3Timestamp(data) {
11228
+ var frames = getId3Frames(data);
11229
+ for (var i = 0; i < frames.length; i++) {
11230
+ var frame = frames[i];
11231
+ if (isId3TimestampFrame(frame)) {
11232
+ return readId3Timestamp(frame);
11233
+ }
11234
+ }
11235
+ return undefined;
11236
+ }
11237
+
11238
+ /**
11239
+ * Checks if the given data contains an ID3 tag.
11240
+ *
11241
+ * @param data - The data to check
11242
+ * @param offset - The offset at which to start checking
11243
+ *
11244
+ * @returns `true` if an ID3 tag is found
11245
+ *
11246
+ * @group ID3
11247
+ *
11248
+ * @beta
11249
+ */
11250
+ function canParseId3(data, offset) {
11251
+ return isId3Header(data, offset) && readId3Size(data, offset + 6) + 10 <= data.length - offset;
11252
+ }
11253
+
10903
11254
  var BaseAudioDemuxer = /*#__PURE__*/function () {
10904
11255
  function BaseAudioDemuxer() {
10905
11256
  this._audioTrack = void 0;
@@ -10943,12 +11294,12 @@
10943
11294
  data = appendUint8Array(this.cachedData, data);
10944
11295
  this.cachedData = null;
10945
11296
  }
10946
- var id3Data = getID3Data(data, 0);
11297
+ var id3Data = getId3Data(data, 0);
10947
11298
  var offset = id3Data ? id3Data.length : 0;
10948
11299
  var lastDataIndex;
10949
11300
  var track = this._audioTrack;
10950
11301
  var id3Track = this._id3Track;
10951
- var timestamp = id3Data ? getTimeStamp(id3Data) : undefined;
11302
+ var timestamp = id3Data ? getId3Timestamp(id3Data) : undefined;
10952
11303
  var length = data.length;
10953
11304
  if (this.basePTS === null || this.frameIndex === 0 && isFiniteNumber(timestamp)) {
10954
11305
  this.basePTS = initPTSFn(timestamp, timeOffset, this.initPTS);
@@ -10979,9 +11330,9 @@
10979
11330
  } else {
10980
11331
  offset = length;
10981
11332
  }
10982
- } else if (canParse$2(data, offset)) {
10983
- // after a ID3.canParse, a call to ID3.getID3Data *should* always returns some data
10984
- id3Data = getID3Data(data, offset);
11333
+ } else if (canParseId3(data, offset)) {
11334
+ // after a canParse, a call to getId3Data *should* always returns some data
11335
+ id3Data = getId3Data(data, offset);
10985
11336
  id3Track.samples.push({
10986
11337
  pts: this.lastPTS,
10987
11338
  dts: this.lastPTS,
@@ -11475,7 +11826,7 @@
11475
11826
  // Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1
11476
11827
  // Layer bits (position 14 and 15) in header should be always 0 for ADTS
11477
11828
  // More info https://wiki.multimedia.cx/index.php?title=ADTS
11478
- var id3Data = getID3Data(data, 0);
11829
+ var id3Data = getId3Data(data, 0);
11479
11830
  var offset = (id3Data == null ? void 0 : id3Data.length) || 0;
11480
11831
  if (probe(data, offset)) {
11481
11832
  return false;
@@ -11698,14 +12049,14 @@
11698
12049
  if (!data) {
11699
12050
  return false;
11700
12051
  }
11701
- var id3Data = getID3Data(data, 0);
12052
+ var id3Data = getId3Data(data, 0);
11702
12053
  if (!id3Data) {
11703
12054
  return false;
11704
12055
  }
11705
12056
 
11706
12057
  // look for the ac-3 sync bytes
11707
12058
  var offset = id3Data.length;
11708
- if (data[offset] === 0x0b && data[offset + 1] === 0x77 && getTimeStamp(id3Data) !== undefined &&
12059
+ if (data[offset] === 0x0b && data[offset + 1] === 0x77 && getId3Timestamp(id3Data) !== undefined &&
11709
12060
  // check the bsid to confirm ac-3
11710
12061
  getAudioBSID(data, offset) < 16) {
11711
12062
  return true;
@@ -14002,11 +14353,11 @@
14002
14353
  // Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1
14003
14354
  // Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III)
14004
14355
  // More info http://www.mp3-tech.org/programmer/frame_header.html
14005
- var id3Data = getID3Data(data, 0);
14356
+ var id3Data = getId3Data(data, 0);
14006
14357
  var offset = (id3Data == null ? void 0 : id3Data.length) || 0;
14007
14358
 
14008
14359
  // Check for ac-3|ec-3 sync bytes and return false if present
14009
- if (id3Data && data[offset] === 0x0b && data[offset + 1] === 0x77 && getTimeStamp(id3Data) !== undefined &&
14360
+ if (id3Data && data[offset] === 0x0b && data[offset + 1] === 0x77 && getId3Timestamp(id3Data) !== undefined &&
14010
14361
  // check the bsid to confirm ac-3 or ec-3 (not mp3)
14011
14362
  getAudioBSID(data, offset) <= 16) {
14012
14363
  return false;
@@ -24531,20 +24882,6 @@
24531
24882
  return value ? '?1' : '?0';
24532
24883
  }
24533
24884
 
24534
- /**
24535
- * Encodes binary data to base64
24536
- *
24537
- * @param binary - The binary data to encode
24538
- * @returns The base64 encoded string
24539
- *
24540
- * @group Utils
24541
- *
24542
- * @beta
24543
- */
24544
- function base64encode(binary) {
24545
- return btoa(String.fromCharCode.apply(String, binary));
24546
- }
24547
-
24548
24885
  var BYTES = 'Byte Sequence';
24549
24886
 
24550
24887
  // 4.1.8. Serializing a Byte Sequence
@@ -24621,34 +24958,6 @@
24621
24958
  return "@" + serializeInteger(value.getTime() / 1000);
24622
24959
  }
24623
24960
 
24624
- /**
24625
- * This implements the rounding procedure described in step 2 of the "Serializing a Decimal" specification.
24626
- * This rounding style is known as "even rounding", "banker's rounding", or "commercial rounding".
24627
- *
24628
- * @param value - The value to round
24629
- * @param precision - The number of decimal places to round to
24630
- * @returns The rounded value
24631
- *
24632
- * @group Utils
24633
- *
24634
- * @beta
24635
- */
24636
- function roundToEven(value, precision) {
24637
- if (value < 0) {
24638
- return -roundToEven(-value, precision);
24639
- }
24640
- var decimalShift = Math.pow(10, precision);
24641
- var isEquidistant = Math.abs(value * decimalShift % 1 - 0.5) < Number.EPSILON;
24642
- if (isEquidistant) {
24643
- // If the tail of the decimal place is 'equidistant' we round to the nearest even value
24644
- var flooredValue = Math.floor(value * decimalShift);
24645
- return (flooredValue % 2 === 0 ? flooredValue : flooredValue + 1) / decimalShift;
24646
- } else {
24647
- // Otherwise, proceed as normal
24648
- return Math.round(value * decimalShift) / decimalShift;
24649
- }
24650
- }
24651
-
24652
24961
  var DECIMAL = 'Decimal';
24653
24962
 
24654
24963
  // 4.1.5. Serializing a Decimal
@@ -25040,38 +25349,6 @@
25040
25349
  return value != null && value !== '' && value !== false;
25041
25350
  };
25042
25351
 
25043
- /**
25044
- * Constructs a relative path from a URL.
25045
- *
25046
- * @param url - The destination URL
25047
- * @param base - The base URL
25048
- * @returns The relative path
25049
- *
25050
- * @group Utils
25051
- *
25052
- * @beta
25053
- */
25054
- function urlToRelativePath(url, base) {
25055
- var to = new URL(url);
25056
- var from = new URL(base);
25057
- if (to.origin !== from.origin) {
25058
- return url;
25059
- }
25060
- var toPath = to.pathname.split('/').slice(1);
25061
- var fromPath = from.pathname.split('/').slice(1, -1);
25062
- // remove common parents
25063
- while (toPath[0] === fromPath[0]) {
25064
- toPath.shift();
25065
- fromPath.shift();
25066
- }
25067
- // add back paths
25068
- while (fromPath.length) {
25069
- fromPath.shift();
25070
- toPath.unshift('..');
25071
- }
25072
- return toPath.join('/');
25073
- }
25074
-
25075
25352
  var toRounded = function toRounded(value) {
25076
25353
  return Math.round(value);
25077
25354
  };
@@ -25315,36 +25592,6 @@
25315
25592
  return "" + url + separator + query;
25316
25593
  }
25317
25594
 
25318
- /**
25319
- * Generate a random v4 UUID
25320
- *
25321
- * @returns A random v4 UUID
25322
- *
25323
- * @group Utils
25324
- *
25325
- * @beta
25326
- */
25327
- function uuid() {
25328
- try {
25329
- return crypto.randomUUID();
25330
- } catch (error) {
25331
- try {
25332
- var url = URL.createObjectURL(new Blob());
25333
- var _uuid = url.toString();
25334
- URL.revokeObjectURL(url);
25335
- return _uuid.slice(_uuid.lastIndexOf('/') + 1);
25336
- } catch (error) {
25337
- var dt = new Date().getTime();
25338
- var _uuid2 = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
25339
- var r = (dt + Math.random() * 16) % 16 | 0;
25340
- dt = Math.floor(dt / 16);
25341
- return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
25342
- });
25343
- return _uuid2;
25344
- }
25345
- }
25346
- }
25347
-
25348
25595
  /**
25349
25596
  * Controller to deal with Common Media Client Data (CMCD)
25350
25597
  * @see https://cdn.cta.tech/cta/media/media/resources/standards/pdfs/cta-5004-final.pdf
@@ -30211,7 +30458,7 @@
30211
30458
  * Get the video-dev/hls.js package version.
30212
30459
  */
30213
30460
  function get() {
30214
- return "1.5.8-0.canary.10153";
30461
+ return "1.5.8-0.canary.10155";
30215
30462
  }
30216
30463
  }, {
30217
30464
  key: "Events",