ppvm_player.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3-or-Later
  2. function setup_playback(description) {
  3. document.getElementById("no-script").classList.remove("noscript");
  4. document.getElementById("controls").classList.add("javascript");
  5. video_manifest = description;
  6. console.log(description);
  7. player = document.getElementById("player");
  8. player.addEventListener("pause", (event) => playStateChanged(false));
  9. player.addEventListener("playing", (event) => playStateChanged(true));
  10. filteredOptions = description.entries.filter(o => shouldOfferStream(o, description.entries));
  11. if(filteredOptions.length == 0){
  12. player.src = "invalid://invalid";
  13. document.getElementById("unplayable-modal").showModal();
  14. return;
  15. }
  16. player.src = filteredOptions[0].path;
  17. qualitySelector = document.getElementById("quality-selector");
  18. filteredOptions.forEach(option => {
  19. opt = document.createElement("option")
  20. opt.value = option.path;
  21. opt.innerHTML = option.label;
  22. qualitySelector.appendChild(opt);
  23. });
  24. startRes = findOptimalOptionForScreen(filteredOptions);
  25. qualitySelector.value = startRes.path
  26. qualitySelected();
  27. doSpeedTest(startRes, filteredOptions);
  28. }
  29. function qualitySelected() {
  30. qualitySelector = document.getElementById("quality-selector");
  31. player = document.getElementById("player");
  32. paused = player.paused;
  33. time = player.currentTime;
  34. player.src = qualitySelector.value;
  35. player.load();
  36. player.currentTime = time;
  37. if(!paused) {
  38. player.play();
  39. }
  40. }
  41. function canPlayStream(stream) {
  42. if(stream.type !== "video") {
  43. return false;
  44. }
  45. player = document.getElementById("player");
  46. return player.canPlayType(`${stream.mimetype}; codecs="${stream.metadata.codecs}"`);
  47. }
  48. function shouldOfferStream(stream, streams) {
  49. if(!canPlayStream(stream)) {
  50. return false;
  51. }
  52. if(stream.metadata.alternative_to == undefined) {
  53. return true;
  54. }
  55. return !hasHigherUsableAlternative(stream, streams);
  56. }
  57. function hasHigherUsableAlternative(stream, streams) {
  58. if(stream.metadata.alternative_to == undefined) {
  59. return false;
  60. }
  61. parent = streams.find(s => s.label == stream.metadata.alternative_to);
  62. if(canPlayStream(parent)) {
  63. return true;
  64. }
  65. return hasHigherUsableAlternative(parent, streams);
  66. }
  67. function findOptimalOptionForScreen(options) {
  68. screenSize = Math.max(window.screen.width, window.screen.height);
  69. screenSize = screenSize * window.devicePixelRatio
  70. filtered = options.filter(o => o.type === "video" && Math.max(o.metadata.size.split("x")[0], o.metadata.size.split("x")[1]) <= screenSize);
  71. console.log(filtered);
  72. if(filtered.length == 0){
  73. return options[options.length - 1];
  74. }
  75. return filtered[0];
  76. }
  77. function downloadVideo() {
  78. document.getElementById("download-modal").showModal();
  79. }
  80. function showInfo() {
  81. document.getElementById("info-modal").showModal();
  82. }
  83. function shareVideo() {
  84. document.getElementById("share-modal").showModal();
  85. }
  86. function playStateChanged(playing) {
  87. controls = document.getElementById("controls")
  88. if(playing) {
  89. controls.classList.remove("paused")
  90. }
  91. else {
  92. controls.classList.add("paused")
  93. }
  94. }
  95. function doSpeedTest(currentOption, options) {
  96. startTime = window.performance.now();
  97. request = new XMLHttpRequest();
  98. request.onreadystatechange = function() {
  99. if(request.readyState === 2) {
  100. // Reset start time, headers received.
  101. startTime = window.performance.now();
  102. }
  103. if(request.readyState === 4 && (request.status === 200 || request.status === 206)) {
  104. endTime = window.performance.now();
  105. size = request.response.size;
  106. rate = size / ((endTime - startTime) / 1000)
  107. console.log(`Detected connection rate: ${rate} bytes/sec`);
  108. filtered = options.filter(o => o.type === "video" && o.byterate < rate);
  109. if(filtered.length == 0) {
  110. filtered = [options[options.length - 1]];
  111. }
  112. optimal = findOptimalOptionForScreen(filtered);
  113. if(optimal !== currentOption) {
  114. qualitySelector.value = optimal.path
  115. console.log("Switched res");
  116. qualitySelected();
  117. }
  118. else {
  119. console.log("Got it right first try B)");
  120. }
  121. }
  122. }
  123. requestSize = Math.min(options[0].filesize, Math.round(options[0].byterate));
  124. request.open("GET", options[0].path);
  125. request.responseType = "blob";
  126. request.setRequestHeader("Range", `bytes=0-${requestSize}`);
  127. request.send();
  128. }
  129. // @license-end