From 8d9edc8c99f6a9588eeb455ced5416c5f5ce97ef Mon Sep 17 00:00:00 2001 From: ThaUnknown Date: Mon, 26 Oct 2020 20:22:14 +0100 Subject: [PATCH] Lastest releases doesnt re-build if the feed hasnt changed, subtitle renderer now uses embedded fonts, only create missing thumbnails, hardsubbed PiP, minor fixes --- app/css/player.css | 9 ++++-- app/index.html | 10 +++++-- app/js/animeHandler.js | 48 +++++++++++++++-------------- app/js/playerHandler.js | 63 ++++++++++++++++++++++++++++++++++++--- app/js/settingsHandler.js | 2 ++ app/js/subtitleOctopus.js | 7 +++-- app/js/torrentHandler.js | 46 ++++++++++++++++------------ 7 files changed, 134 insertions(+), 51 deletions(-) diff --git a/app/css/player.css b/app/css/player.css index 989394b..3777b51 100644 --- a/app/css/player.css +++ b/app/css/player.css @@ -58,6 +58,9 @@ #player:target .player { display: flex !important } +#player.pip{ + background: #000 +} .controls { background: linear-gradient(to top, rgba(0, 0, 0, .8), rgba(0, 0, 0, .4) 25%, rgba(0, 0, 0, .2) 50%, rgba(0, 0, 0, .1) 75%, transparent); @@ -212,8 +215,10 @@ #player:fullscreen #btheatre, #player:target>a, #progress+img[src=" "], -video[src=""] { - display: none +video[src=""], +#player.pip video, +#player.pip canvas { + display: none !important } video::cue { diff --git a/app/index.html b/app/index.html index 0704425..dcc0154 100644 --- a/app/index.html +++ b/app/index.html @@ -304,11 +304,17 @@ -
+
+
+ + +

@@ -360,7 +366,7 @@ - + diff --git a/app/js/animeHandler.js b/app/js/animeHandler.js index e5f2262..5dc5058 100644 --- a/app/js/animeHandler.js +++ b/app/js/animeHandler.js @@ -319,41 +319,45 @@ async function nyaaRss(url) { const regex = /((?:\[[^\]]*\])*)?\s*((?:[^\d\[\.](?!S\d))*)?\s*((?:S\d+[^\w\[]*E?)?[\d\-]*)\s*(.*)?/i, eregex = /(\[.*\]\ ?)?(.+?(?=\ \–\ \d))?(\ \–\ )?(\d+)?/i, plsregex = /(\[.[^\]]*\]\ ?)?(.+?(?=\ \-\ \d))?(\ \-\ )?(\d+)?(.*)?/i -let store = {}; +let store = {}, + lastResult async function hsRss() { if (document.location.href.endsWith("#releases")) { let frag = document.createDocumentFragment(), releases = document.querySelector(".releases"), url = settings.torrent4 == "https://miru.kirdow.com/request/?url=https://www.erai-raws.info/rss-" ? settings.torrent4 + settings.torrent1 + "-magnet" : settings.torrent4 + settings.torrent1 - releases.textContent = ''; - releases.appendChild(skeletonCard) res = await fetch(url) await res.text().then(async (xmlTxt) => { try { let doc = DOMPARSER(xmlTxt, "text/xml") - let items = doc.querySelectorAll("item") - for (let item of items) { - let i = item.querySelector.bind(item), - regexParse = plsregex.exec(i("title").textContent) - if (!store.hasOwnProperty(regexParse[2]) && !alResponse.data.Page.media.some(media => (Object.values(media.title).concat(media.synonyms).filter(name => name != null).includes(regexParse[2]) && ((store[regexParse[2]] = media) && true)))) { - //shit not found, lookup - let res = await alRequest(regexParse[2], 1) - if (!res.data.Page.media[0]) { - res = await alRequest(regexParse[2].replace(" (TV)", "").replace(` (${new Date().getFullYear()})`, ""), 1) + if (lastResult != doc) { + releases.textContent = ''; + releases.appendChild(skeletonCard) + lastResult = doc + let items = doc.querySelectorAll("item") + for (let item of items) { + let i = item.querySelector.bind(item), + regexParse = plsregex.exec(i("title").textContent) + if (!store.hasOwnProperty(regexParse[2]) && !alResponse.data.Page.media.some(media => (Object.values(media.title).concat(media.synonyms).filter(name => name != null).includes(regexParse[2]) && ((store[regexParse[2]] = media) && true)))) { + //shit not found, lookup + let res = await alRequest(regexParse[2], 1) + if (!res.data.Page.media[0]) { + res = await alRequest(regexParse[2].replace(" (TV)", "").replace(` (${new Date().getFullYear()})`, ""), 1) + } + store[regexParse[2]] = res.data.Page.media[0] } - store[regexParse[2]] = res.data.Page.media[0] + let media = store[regexParse[2]], + template = cardCreator(media, regexParse) + template.onclick = () => { + playerData.selected = [regexParse[2], regexParse[4]] + addTorrent(i('link').textContent) + } + frag.appendChild(template) } - let media = store[regexParse[2]], - template = cardCreator(media, regexParse) - template.onclick = () => { - playerData.selected = [regexParse[2], regexParse[4]] - addTorrent(i('link').textContent) - } - frag.appendChild(template) + releases.textContent = ''; + releases.appendChild(frag) } - releases.textContent = ''; - releases.appendChild(frag) } catch (e) { console.error(e) } diff --git a/app/js/playerHandler.js b/app/js/playerHandler.js index 6ae7718..6bd2cb3 100644 --- a/app/js/playerHandler.js +++ b/app/js/playerHandler.js @@ -24,6 +24,9 @@ let playerData = { function resetVideo() { !!playerData.octopusInstance ? playerData.octopusInstance.dispose() : "" + !!playerData.fonts ? playerData.fonts.forEach(file => { + URL.revokeObjectURL(file) + }) : "" playerData = { tracks: [], headers: undefined, @@ -31,6 +34,7 @@ function resetVideo() { subtitles: [], subtitleStream: undefined, octopusInstance: undefined, + fonts: [], nowPlaying: undefined, selected: undefined, thumbnails: [] @@ -132,7 +136,8 @@ function createThumbnail(vid) { function finishThumbnails(url) { if (settings.player5 && settings.player8) { - let thumbVid = document.createElement("video") + let thumbVid = document.createElement("video"), + index = 0 thumbVid.src = url thumbVid.addEventListener('loadeddata', () => { @@ -145,11 +150,15 @@ function finishThumbnails(url) { }) function loadTime() { + while (playerData.thumbnails[index] && index <= Math.floor(thumbVid.duration / 5)) { + index++ + } if (thumbVid.currentTime != thumbVid.duration) { - thumbVid.currentTime = thumbVid.currentTime + 5; + thumbVid.currentTime = index * 5 } else { thumbVid.remove() } + index++ } } } @@ -276,7 +285,53 @@ updateVolume(parseInt(settings.player1)) // PiP async function btnpip() { - video !== document.pictureInPictureElement ? await video.requestPictureInPicture() : await document.exitPictureInPicture(); + if (!playerData.octopusInstance) { + video !== document.pictureInPictureElement ? await video.requestPictureInPicture() : await document.exitPictureInPicture(); + } else { + if (document.pictureInPictureElement) { + await document.exitPictureInPicture() + } else { + let canvas = document.createElement("canvas"), + subtitleCanvas = document.querySelector(".libassjs-canvas"), + canvasVideo = document.createElement("video"), + context = canvas.getContext("2d", { alpha: false }), + running = true + canvas.width = subtitleCanvas.width + canvas.height = subtitleCanvas.height + player.classList.add("pip") + + function renderFrame() { + if (running) { + context.drawImage(video, 0, 0, canvas.width, canvas.height) + context.drawImage(subtitleCanvas, 0, 0) + window.requestAnimationFrame(renderFrame) + } + } + window.requestAnimationFrame(renderFrame) + canvasVideo.srcObject = canvas.captureStream() + canvasVideo.onloadeddata = async function () { + canvasVideo.play() + await canvasVideo.requestPictureInPicture() + } + canvasVideo.onleavepictureinpicture = () => { + running = false + canvasVideo.remove() + canvas.remove() + player.classList.remove("pip") + } + } + } +} + +function hardSub() { + let c1 = document.createElement("canvas"), + sub = document.querySelector(".libassjs-canvas") + c1.width = sub.width + c1.height = sub.height + let ctx1 = c1.getContext("2d") + ctx1.drawImage(video, 0, 0, c1.width, c1.height) + ctx1.drawImage(sub, 0, 0) + console.log(c1.toDataURL("image/jpeg")) } //miniplayer @@ -422,7 +477,7 @@ function selPlaying(sel) { } function updatePositionState() { - if ('setPositionState' in navigator.mediaSession) { + if ('setPositionState' in navigator.mediaSession && video.duration) { navigator.mediaSession.setPositionState({ duration: video.duration || 0, playbackRate: video.playbackRate || 0, diff --git a/app/js/settingsHandler.js b/app/js/settingsHandler.js index b00b174..b438349 100644 --- a/app/js/settingsHandler.js +++ b/app/js/settingsHandler.js @@ -9,6 +9,7 @@ const settingsElements = { player8: player8, subtitle1: subtitle1, subtitle2: subtitle2, + subtitle3: subtitle3, torrent1: torrent1, torrent2: torrent2, torrent3: torrent3, @@ -28,6 +29,7 @@ function restoreDefaults() { player8: true, subtitle1: "'Open Sans', sans-serif", subtitle2: true, + subtitle3: true, torrent1: "1080", torrent2: false, torrent3: true, diff --git a/app/js/subtitleOctopus.js b/app/js/subtitleOctopus.js index 3dd2ea7..0f764a1 100644 --- a/app/js/subtitleOctopus.js +++ b/app/js/subtitleOctopus.js @@ -27,7 +27,7 @@ function subStream(stream) { } }) } - playerData.subtitleStream.on('subtitle', function (subtitle, trackNumber) { + playerData.subtitleStream.on('subtitle', (subtitle, trackNumber) => { if (playerData.headers) { let formatSub = "Dialogue: " + subtitle.layer + "," + new Date(subtitle.time).toISOString().slice(12, -1).slice(0, -1) + "," + new Date(subtitle.time + subtitle.duration).toISOString().slice(12, -1).slice(0, -1) + "," + subtitle.style + "," + subtitle.name + "," + subtitle.marginL + "," + subtitle.marginR + "," + subtitle.marginV + "," + subtitle.effect + "," + subtitle.text if (!playerData.subtitles[trackNumber].includes(formatSub)) { @@ -41,6 +41,9 @@ function subStream(stream) { } } }) + playerData.subtitleStream.on('file', file => { + file.mimetype == ("application/x-truetype-font" || "application/font-woff") ? playerData.fonts.push(window.URL.createObjectURL(new Blob([file.data],{type: file.mimetype}))) : "" + }) stream.pipe(playerData.subtitleStream) } } @@ -51,7 +54,7 @@ function renderSubs(trackNumber) { video: video, subContent: trackContent, lossyRender: settings.subtitle2, - fonts: ["https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fBBc4.woff2"], + fonts: playerData.fonts.length == 0 ? ["https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fBBc4.woff2"] : playerData.fonts, workerUrl: 'js/subtitles-octopus-worker.js' }; playerData.octopusInstance = new SubtitlesOctopus(options); diff --git a/app/js/torrentHandler.js b/app/js/torrentHandler.js index df971da..66b261c 100644 --- a/app/js/torrentHandler.js +++ b/app/js/torrentHandler.js @@ -99,31 +99,39 @@ async function addTorrent(magnet) { } function postDownload(url, file) { if (settings.player8) { - let parser = new SubtitleParser(), - subtitles = [] - parser.once('tracks', pTracks => { - pTracks.forEach(track => { - subtitles[track.number] = [] + if (playerData.subtitleStream) { + let parser = new SubtitleParser(), + subtitles = [] + parser.once('tracks', pTracks => { + pTracks.forEach(track => { + subtitles[track.number] = [] + }) }) - }) - parser.on('subtitle', function (subtitle, trackNumber) { - if (playerData.headers) { - subtitles[trackNumber].push("Dialogue: " + subtitle.layer + "," + new Date(subtitle.time).toISOString().slice(12, -1).slice(0, -1) + "," + new Date(subtitle.time + subtitle.duration).toISOString().slice(12, -1).slice(0, -1) + "," + subtitle.style + "," + subtitle.name + "," + subtitle.marginL + "," + subtitle.marginR + "," + subtitle.marginV + "," + subtitle.effect + "," + subtitle.text) - } else if (!Object.values(playerData.tracks[trackNumber].cues).some(c => c.text == subtitle.text && c.startTime == subtitle.time / 1000 && c.endTime == (subtitle.time + subtitle.duration) / 1000)) { - let cue = new VTTCue(subtitle.time / 1000, (subtitle.time + subtitle.duration) / 1000, subtitle.text) - playerData.tracks[trackNumber].addCue(cue) - } - }) - parser.on('finish', () => { - playerData.subtitles = subtitles - renderSubs.call(null, 3) + parser.on('subtitle', function (subtitle, trackNumber) { + if (playerData.headers) { + subtitles[trackNumber].push("Dialogue: " + subtitle.layer + "," + new Date(subtitle.time).toISOString().slice(12, -1).slice(0, -1) + "," + new Date(subtitle.time + subtitle.duration).toISOString().slice(12, -1).slice(0, -1) + "," + subtitle.style + "," + subtitle.name + "," + subtitle.marginL + "," + subtitle.marginR + "," + subtitle.marginV + "," + subtitle.effect + "," + subtitle.text) + } else if (!Object.values(playerData.tracks[trackNumber].cues).some(c => c.text == subtitle.text && c.startTime == subtitle.time / 1000 && c.endTime == (subtitle.time + subtitle.duration) / 1000)) { + let cue = new VTTCue(subtitle.time / 1000, (subtitle.time + subtitle.duration) / 1000, subtitle.text) + playerData.tracks[trackNumber].addCue(cue) + } + }) + parser.on('finish', () => { + playerData.subtitles = subtitles + renderSubs.call(null, 3) + let time = video.currentTime, + playState = !video.paused + video.src = url + video.currentTime = time + playState ? video.play() : "" + }); + file.createReadStream().pipe(parser) + } else { let time = video.currentTime, playState = !video.paused video.src = url video.currentTime = time playState ? video.play() : "" - }); - file.createReadStream().pipe(parser) + } } } function onProgress() {