애니플러스 스트리밍 문제해결
- Tampermonkey 설치: https://tampermonkey.net/
- 문제해결 스크립트 설치: https://gist.github.com/saschanaz/a5e00b559da591b1a4bd59361778b9fa/raw/aniplus-patch.user.js
애니플러스 스트리밍 문제해결
// ==UserScript== | |
// @name ANIPLUS HLS fix | |
// @namespace https://saschanaz.github.io/ | |
// @version 0.2.4 | |
// @description Fix bandwidth to match the actual maximum observed bitrate 95726 kbps | |
// @author Kagami Sascha Rosylight | |
// @match http://www.aniplustv.com/tv/program_player_html5.asp?* | |
// @grant none | |
// @run-at document-start | |
// ==/UserScript== | |
/* jshint esversion: 6 */ | |
"use strict"; | |
(() => { | |
console.log("Starting ANIPLUS autoSetup fix"); | |
const o = new MutationObserver(mutations => { | |
for (const mutation of mutations) { | |
for (const node of Array.from(mutation.addedNodes)) { | |
if (node.nodeType === 1 && node.id === "aniplusVideo" && node.tagName === "VIDEO") { | |
console.log("Removing data-setup to prevent videojs autoSetup(), which may cause race condition with ANIPLUS ajax success handler and then HLS error."); | |
node.removeAttribute("data-setup"); | |
} | |
} | |
} | |
}); | |
o.observe(document.documentElement, { childList: true, subtree: true }); | |
})(); | |
(async () => { | |
if (!document.createElement("video").canPlayType('application/x-mpegURL')) { | |
console.log("Skipping ANIPLUS bandwidth fix as this browser doesn't have native HLS support"); | |
return; | |
} | |
console.log("Starting ANIPLUS bandwidth fix"); | |
const threshold = 128 * 1024 ** 2; | |
if (!await tryModification()) { | |
startMutationObserver(); | |
} | |
async function tryModification() { | |
if (!window.aniplusVideo_html5_api) { | |
return false; | |
} | |
return fixVideo(aniplusVideo_html5_api); | |
} | |
function startMutationObserver() { | |
const observer = new MutationObserver(async (mutations) => { | |
for (const mutation of mutations) { | |
for (const node of Array.from(mutation.addedNodes)) { | |
if (node.nodeType === 1 && node.id === "aniplusVideo_html5_api") { | |
await fixVideo(node); | |
} | |
} | |
} | |
}); | |
observer.observe(document.documentElement, { | |
subtree: true, | |
childList: true | |
}); | |
return observer; | |
} | |
async function fixVideo(video) { | |
const source = video.getElementsByTagName("source")[0]; | |
if (!source.src.includes("playlist.m3u8")) { | |
return false; | |
} | |
video.src = URL.createObjectURL(await fixPlaylist(source.src)); | |
video.setAttribute("x-aniplus-fix", true); | |
} | |
async function fixPlaylist(path) { | |
const directory = path.match(/^.*\//); | |
const response = await fetch(path); | |
const text = await response.text(); | |
console.log(`ANIPLUS HLS original:\n\n${text}`); | |
const fixed = text | |
.replace(/BANDWIDTH=([0-9]+)/, ($0, $1) => `BANDWIDTH=${Math.max(+$1, threshold)}`) | |
.replace("chunklist", `${directory}chunklist`); | |
console.log(`ANIPLUS HLS fix:\n\n${fixed}`); | |
return new Blob([fixed], { type: "application/vnd.apple.mpegurl" }); | |
} | |
})().catch(console.error); |