DASH Video Player Optimizer(视频协议优化DASH篇)

Optimize DASH video playback on web pages with enhanced performance and ABR management

  1. // ==UserScript==
  2. // @name DASH Video Player Optimizer(视频协议优化DASH篇)
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.1
  5. // @description Optimize DASH video playback on web pages with enhanced performance and ABR management
  6. // @author KiwiFruit
  7. // @match *://*/*
  8. // @grant none
  9. // @license MIT
  10. // ==/UserScript==
  11. (function() {
  12. 'use strict';
  13.  
  14. // Helper function to fetch the first segment of the DASH manifest
  15. function fetchFirstSegment(mpdUrl) {
  16. return fetch(mpdUrl)
  17. .then(response => response.text())
  18. .then(text => {
  19. const parser = new DOMParser();
  20. const xmlDoc = parser.parseFromString(text, "text/xml");
  21. // Find the first Representation and SegmentTemplate/BaseURL
  22. const representation = xmlDoc.querySelector('Representation');
  23. const segmentTemplate = representation.querySelector('SegmentTemplate');
  24. if (segmentTemplate) {
  25. const initialization = segmentTemplate.getAttribute('initialization');
  26. const baseUrl = xmlDoc.querySelector('BaseURL').textContent;
  27. return `${baseUrl}${initialization}`;
  28. } else {
  29. console.error('Failed to find the first segment URL.');
  30. return null;
  31. }
  32. })
  33. .catch(error => console.error('Error fetching first segment:', error));
  34. }
  35.  
  36. // Preload the first segment of the video using dash.js
  37. function preloadFirstSegment(videoElement, player) {
  38. const source = videoElement.querySelector('source');
  39. if (source && source.src.endsWith('.mpd')) {
  40. fetchFirstSegment(source.src).then(segmentUrl => {
  41. if (segmentUrl) {
  42. player.initialize(videoElement, source.src, true);
  43. }
  44. });
  45. }
  46. }
  47.  
  48. // Buffer strategy optimization
  49. function optimizeBufferStrategy(player) {
  50. player.on(dashjs.MediaPlayer.events.BUFFER_EMPTY, () => {
  51. console.log('Buffer empty, pausing playback.');
  52. player.pause();
  53. // Dynamic buffer time based on average throughput
  54. const bufferTime = player.getAverageThroughput() < 1000000 ? 3000 : 2000; // Adjust buffer time based on average throughput
  55. setTimeout(() => {
  56. player.play();
  57. }, bufferTime);
  58. });
  59.  
  60. player.on(dashjs.MediaPlayer.events.BUFFER_LOADED, () => {
  61. console.log('Buffer loaded, resuming playback.');
  62. player.play();
  63. });
  64. }
  65.  
  66. // Helper function to dynamically load external scripts
  67. function loadExternalScript(url, callback) {
  68. var script = document.createElement('script');
  69. script.src = url;
  70. script.onload = function() {
  71. console.log(url + ' loaded successfully.');
  72. if (callback) callback();
  73. };
  74. script.onerror = function() {
  75. console.error('Failed to load script: ' + url);
  76. };
  77. document.head.appendChild(script);
  78. }
  79.  
  80. // Main function to initialize optimizations
  81. function initializeOptimizations() {
  82. try {
  83. const videoElement = document.querySelector('video');
  84. if (!videoElement || !videoElement.querySelector('source[src$=".mpd"]')) return;
  85.  
  86. // Dynamically load dashjs
  87. loadExternalScript('https://cdn.jsdelivr.net/npm/dashjs@latest/dist/dash.all.min.js', () => {
  88. const player = dashjs.MediaPlayer().create();
  89. preloadFirstSegment(videoElement, player);
  90. optimizeBufferStrategy(player);
  91. });
  92. } catch (error) {
  93. console.error('Error initializing optimizations:', error);
  94. }
  95. }
  96.  
  97. // Run the initialization when the page loads
  98. window.addEventListener('load', initializeOptimizations);
  99.  
  100. // Compatibility check
  101. if ('MediaSource' in window && MediaSource.isTypeSupported('video/mp4; codecs="avc1.42E01E, mp4a.40.2"')) {
  102. initializeOptimizations();
  103. } else {
  104. console.warn('Your browser does not support DASH or MSE.');
  105. }
  106. })();