mirror of
https://github.com/ThaUnknown/miru.git
synced 2026-03-31 10:48:33 +00:00
full offline video playback, VTT subtitle fixes, post-download improvements, minor fixes
This commit is contained in:
parent
a2367f0c7e
commit
afffffbfe5
6 changed files with 28 additions and 21 deletions
|
|
@ -665,12 +665,8 @@
|
|||
<input id="subtitle1" type="text" list="subtitle1list" class="form-control"
|
||||
autocomplete="off" value="SubsPlease">
|
||||
<datalist id="subtitle1list">
|
||||
<option value="SubsPlease">Roboto
|
||||
Medium,26,&H00FFFFFF,&H000000FF,&H00020713,&H00000000,0,0,0,0,100,100,0,0,1,1.3,0,2,20,20,23,1
|
||||
</option>
|
||||
<option value="Erai-raws">Open Sans
|
||||
Semibold,45,&H00FFFFFF,&H000000FF,&H00020713,&H00000000,-1,0,0,0,100,100,0,0,1,1.7,0,2,10,10,25,1
|
||||
</option>
|
||||
<option value="SubsPlease">Roboto Medium,26,&H00FFFFFF,&H000000FF,&H00020713,&H00000000,0,0,0,0,100,100,0,0,1,1.3,0,2,20,20,23,1</option>
|
||||
<option value="Erai-raws">Open Sans Semibold,45,&H00FFFFFF,&H000000FF,&H00020713,&H00000000,-1,0,0,0,100,100,0,0,1,1.7,0,2,10,10,25,1</option>
|
||||
</datalist>
|
||||
</div>
|
||||
<div class="custom-switch mb-20" data-toggle="tooltip" data-placement="top" data-title="Displays Subtitles In PiP And ChromeCast, Requires chrome://flags/#disable-accelerated-2d-canvas Set To
|
||||
|
|
@ -778,10 +774,10 @@
|
|||
</div>
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/gh/halfmoonui/halfmoon@1.1.1/js/halfmoon.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/webtorrent@latest/webtorrent.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/matroska-subtitles@latest/dist/matroska-subtitles.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/indexeddb-chunk-store@latest/idbchunkstore.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/anitomyscript@2.0.4/dist/anitomyscript.bundle.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/webtorrent@latest/webtorrent.min.js"></script>
|
||||
<script src="js/settingsHandler.js"></script>
|
||||
<script src="js/rangeParser.js"></script>
|
||||
<script src="js/util.js"></script>
|
||||
|
|
|
|||
|
|
@ -625,11 +625,11 @@ async function resolveFileMedia(opts) {
|
|||
tempMedia = opts.media.relations.edges.filter(edge => edge.relationType == "SEQUEL" && (edge.node.format == "TV" || "TV_SHORT"))[0].node
|
||||
increment = true
|
||||
}
|
||||
if (tempMedia.episodes && epMax - (opts.offset + tempMedia.episodes) > (media.episodes || media.nextAiringEpisode.episode)) {
|
||||
if (tempMedia?.episodes && epMax - (opts.offset + tempMedia.episodes) > (media.episodes || media.nextAiringEpisode.episode)) {
|
||||
// episode is still out of bounds
|
||||
let nextEdge = await alRequest({ method: "SearchIDSingle", id: tempMedia.id })
|
||||
await resolveSeason({ media: nextEdge.data.Media, episode: opts.episode, offset: opts.offset + nextEdge.data.Media.episodes, increment: increment })
|
||||
} else if (tempMedia.episodes && epMax - (opts.offset + tempMedia.episodes) < (media.episodes || media.nextAiringEpisode.episode) && epMin - (opts.offset + tempMedia.episodes) > 0) {
|
||||
} else if (tempMedia?.episodes && epMax - (opts.offset + tempMedia.episodes) < (media.episodes || media.nextAiringEpisode.episode) && epMin - (opts.offset + tempMedia.episodes) > 0) {
|
||||
// episode is in range, seems good! overwriting media to count up "seasons"
|
||||
if (opts.episode.constructor == Array) {
|
||||
episode = `${elems.episode_number[0] - (opts.offset + tempMedia.episodes)} - ${elems.episode_number[elems.episode_number.length - 1] - (opts.offset + tempMedia.episodes)}`
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ async function buildVideo(torrent, opts) { // sets video source and creates a bu
|
|||
if (playerData.nowPlaying[0].streamingEpisodes.length >= Number(playerData.nowPlaying[1])) {
|
||||
let streamingEpisode = playerData.nowPlaying[0].streamingEpisodes.filter(episode => episodeRx.exec(episode.title) && episodeRx.exec(episode.title)[1] == Number(playerData.nowPlaying[1]))[0]
|
||||
video.poster = streamingEpisode.thumbnail
|
||||
document.title = `${playerData.nowPlaying[0].title.userPreferred} - ${Number(playerData.nowPlaying[1])} - EP ${episodeRx.exec(streamingEpisode.title)[2]} - Miru`
|
||||
document.title = `${playerData.nowPlaying[0].title.userPreferred} - EP ${Number(playerData.nowPlaying[1])} - ${episodeRx.exec(streamingEpisode.title)[2]} - Miru`
|
||||
mediaMetadata.artist = `Episode ${Number(playerData.nowPlaying[1])} - ${episodeRx.exec(streamingEpisode.title)[2]}`
|
||||
mediaMetadata.artwork = [{
|
||||
src: streamingEpisode.thumbnail,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ function subStream(stream) { // subtitle parsing with seeking support
|
|||
track.header = `[V4+ Styles]
|
||||
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
|
||||
Style: Default,${Object.values(subtitle1list.options).filter(item => item.value == settings.subtitle1)[0].innerText}
|
||||
[Events]
|
||||
|
||||
`
|
||||
}
|
||||
playerData.headers[track.number] = track
|
||||
|
|
@ -28,8 +30,7 @@ Style: Default,${Object.values(subtitle1list.options).filter(item => item.value
|
|||
let formatSub = "Dialogue: " + (subtitle.layer || 0) + "," + 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 || "Default") + "," + (subtitle.name || "") + "," + (subtitle.marginL || "0") + "," + (subtitle.marginR || "0") + "," + (subtitle.marginV || "0") + "," + (subtitle.effect || "") + "," + subtitle.text
|
||||
if (!playerData.subtitles[trackNumber].has(formatSub)) {
|
||||
playerData.subtitles[trackNumber].add(formatSub)
|
||||
if (playerData.selectedHeader == trackNumber)
|
||||
renderSubs.call(null, trackNumber)
|
||||
if (playerData.selectedHeader == trackNumber) renderSubs(trackNumber)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -46,7 +47,7 @@ function renderSubs(trackNumber) {
|
|||
video: video,
|
||||
subContent: trackNumber ? playerData.headers[trackNumber].header.slice(0, -1) + Array.from(playerData.subtitles[trackNumber]).join("\n") : playerData.headers[3].header.slice(0, -1),
|
||||
lossyRender: true,
|
||||
fonts: playerData.fonts.length == 0 ? ["https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fBBc4.woff2"] : playerData.fonts,
|
||||
fonts: playerData.fonts?.length != 0 ? playerData.fonts : ["https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fBBc4.woff2"] ,
|
||||
workerUrl: 'js/subtitles-octopus-worker.js',
|
||||
timeOffset: 0
|
||||
};
|
||||
|
|
@ -84,6 +85,8 @@ function postDownload(file) { // parse subtitles fully after a download is finis
|
|||
track.header = `[V4+ Styles]
|
||||
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
|
||||
Style: Default,${Object.values(subtitle1list.options).filter(item => item.value == settings.subtitle1)[0].innerText}
|
||||
[Events]
|
||||
|
||||
`
|
||||
}
|
||||
headers[track.number] = track
|
||||
|
|
@ -99,8 +102,10 @@ Style: Default,${Object.values(subtitle1list.options).filter(item => item.value
|
|||
playerData.headers = headers
|
||||
playerData.parsed = 1
|
||||
playerData.subtitleStream = undefined
|
||||
renderSubs.call(null, playerData.selectedHeader)
|
||||
renderSubs(playerData.selectedHeader)
|
||||
parser = undefined
|
||||
video.pause();
|
||||
playVideo();
|
||||
});
|
||||
file.createReadStream().pipe(parser)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ var SubtitlesOctopus = function (options) {
|
|||
self.dropAllAnimations = options.dropAllAnimations || false;
|
||||
self.libassMemoryLimit = options.libassMemoryLimit || 0; // set libass bitmap cache memory limit in MiB (approximate)
|
||||
self.libassGlyphLimit = options.libassGlyphLimit || 0; // set libass glyph cache memory limit in MiB (approximate)
|
||||
self.targetFps = options.targetFps || 60;
|
||||
self.targetFps = options.targetFps || 30;
|
||||
self.prescaleTradeoff = options.prescaleTradeoff || null; // render subtitles less than viewport when less than 1.0 to improve speed, render to more than 1.0 to improve quality; set to null to disable scaling
|
||||
self.softHeightLimit = options.softHeightLimit || 1080; // don't apply prescaleTradeoff < 1 when viewport height is less that this limit
|
||||
self.hardHeightLimit = options.hardHeightLimit || 2160; // don't ever go above this limit
|
||||
|
|
|
|||
|
|
@ -55,8 +55,8 @@ function t(a) {
|
|||
// offline storage initial load
|
||||
let offlineTorrents
|
||||
async function loadOfflineStorage() {
|
||||
offlineTorrents = new Set([...await indexedDB.databases()].map(object => { return object.name }));
|
||||
[...offlineTorrents].forEach(torrentID => offlineDownload(torrentID, true)) // adds all offline store torrents to the client
|
||||
offlineTorrents = JSON.parse(localStorage.getItem("offlineTorrents")) || {};
|
||||
Object.values(offlineTorrents).forEach(torrentID => offlineDownload(new Blob([new Uint8Array(torrentID)]), true)) // adds all offline store torrents to the client
|
||||
}
|
||||
|
||||
// add torrent for offline download
|
||||
|
|
@ -66,12 +66,16 @@ function offlineDownload(torrentID, skipVerify) {
|
|||
skipVerify: skipVerify
|
||||
})
|
||||
torrent.on("metadata", async () => {
|
||||
offlineTorrents.add(torrent.infoHash)
|
||||
console.log(torrent)
|
||||
if (!offlineTorrents[torrent.infoHash]) {
|
||||
offlineTorrents[torrent.infoHash] = Array.from(torrent.torrentFile);
|
||||
localStorage.setItem("offlineTorrents", JSON.stringify(offlineTorrents))
|
||||
}
|
||||
let mediaInformation = await resolveFileMedia({ fileName: torrent.name, method: "SearchName" })
|
||||
template = cardCreator(mediaInformation)
|
||||
template.onclick = async () => {
|
||||
addTorrent(torrent, { media: mediaInformation.media, episode: mediaInformation.parseObject.episode })
|
||||
store[mediaInformation.parseObject.anime_title] = await alRequest({ id: mediaInformation.media?.id, method: "SearchIDSingle" }).then(res => res.data.Media)
|
||||
store[mediaInformation.parseObject.anime_title] = await alRequest({ id: mediaInformation.media?.id, method: "SearchIDSingle" }).then(res => res.data.Media)
|
||||
// force updates entry data on play in case its outdated, needs to be made cleaner and somewhere else...
|
||||
}
|
||||
document.querySelector(".downloads").appendChild(template)
|
||||
|
|
@ -83,7 +87,7 @@ loadOfflineStorage()
|
|||
// cleanup torrent and store
|
||||
function cleanupTorrents() {
|
||||
client.torrents.filter(torrent => {
|
||||
return !offlineTorrents.has(torrent.infoHash) || torrent.progress != 1 // creates an array of all non-offline store torrents and removes them
|
||||
return !(offlineTorrents[torrent.infoHash] || torrent.progress == 1) // creates an array of all non-offline store torrents and removes them
|
||||
}).forEach(torrent => torrent.destroy({ destroyStore: true }))
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +126,9 @@ function addTorrent(torrentID, opts) {
|
|||
document.location.hash = "#player"
|
||||
cleanupVideo()
|
||||
cleanupTorrents()
|
||||
if (client.get(torrentID)) {
|
||||
if (torrentID instanceof Object) {
|
||||
playTorrent(torrentID, opts)
|
||||
} else if (client.get(torrentID)) {
|
||||
playTorrent(client.get(torrentID), opts)
|
||||
} else {
|
||||
client.add(torrentID, settings.torrent5 ? { store: IdbChunkStore } : {}, function (torrent) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue