mirror of
https://github.com/ThaUnknown/miru.git
synced 2026-04-06 22:09:30 +00:00
115 lines
No EOL
6.3 KiB
JavaScript
115 lines
No EOL
6.3 KiB
JavaScript
const { SubtitleStream } = MatroskaSubtitles
|
|
const { SubtitleParser } = MatroskaSubtitles
|
|
// this entire thing needs to go
|
|
function subStream(stream) { // subtitle parsing with seeking support
|
|
if (video.src.endsWith(".mkv") || video.src.endsWith(".webm")) {
|
|
if (playerData.subtitleStream) {
|
|
playerData.subtitleStream = new SubtitleStream(playerData.subtitleStream)
|
|
} else {
|
|
playerData.subtitleStream = new SubtitleStream()
|
|
playerData.subtitleStream.once('tracks', pTracks => {
|
|
bcap.removeAttribute("disabled")
|
|
pTracks.forEach(track => {
|
|
if (track.type == "ass") {
|
|
if (!playerData.headers) {
|
|
playerData.headers = []
|
|
}
|
|
playerData.headers[track.number] = track
|
|
playerData.subtitles[track.number] = new Set()
|
|
playerData.selectedHeader = 3
|
|
} else { //fallback for VTT, needs to go!!!!
|
|
playerData.tracks[track.number] = video.addTextTrack('captions', track.type, track.language);
|
|
let spacerCue = new VTTCue(0.1, 9999, " ")
|
|
spacerCue.line = -1
|
|
playerData.tracks[track.number].addCue(spacerCue)
|
|
}
|
|
})
|
|
if (video.textTracks[0]) {
|
|
video.textTracks[0].mode = "showing"
|
|
}
|
|
})
|
|
}
|
|
playerData.subtitleStream.on('subtitle', (subtitle, trackNumber) => {
|
|
console.log(subtitle)
|
|
if (!playerData.parsed) {
|
|
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].has(formatSub)) {
|
|
playerData.subtitles[trackNumber].add(formatSub)
|
|
if (playerData.selectedHeader == trackNumber)
|
|
renderSubs.call(null, trackNumber)
|
|
}
|
|
} else { //fallback for VTT, needs to go!!!!
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
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)
|
|
}
|
|
}
|
|
function renderSubs(trackNumber) {
|
|
if (!playerData.octopusInstance) {
|
|
let options = {
|
|
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: settings.subtitle2,
|
|
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);
|
|
} else {
|
|
pushSub(trackNumber)
|
|
}
|
|
}
|
|
// these 2 really need to go into a single function....
|
|
let octopusTimeout
|
|
function pushSub(trackNumber) {
|
|
if (!octopusTimeout && playerData.octopusInstance) {
|
|
octopusTimeout = setTimeout(() => {
|
|
octopusTimeout = undefined
|
|
playerData.octopusInstance.setTrack(trackNumber ? playerData.headers[trackNumber].header.slice(0, -1) + Array.from(playerData.subtitles[trackNumber]).join("\n") : playerData.headers[3].header.slice(0, -1))
|
|
}, 1000)
|
|
}
|
|
}
|
|
function postDownload(file) { // parse subtitles fully after a download is finished
|
|
if (playerData.subtitleStream) {
|
|
let parser = new SubtitleParser(),
|
|
subtitles = []
|
|
parser.once('tracks', pTracks => {
|
|
pTracks.forEach(track => {
|
|
subtitles[track.number] = new Set()
|
|
})
|
|
})
|
|
parser.on('subtitle', (subtitle, trackNumber) => {
|
|
if (playerData.headers) {
|
|
subtitles[trackNumber].add("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
|
|
playerData.parsed = 1
|
|
renderSubs.call(null, playerData.selectedHeader)
|
|
if (settings.player9) { // render the video to a blob for faster playback and seeking, F RAM
|
|
file.getBlobURL((err, url) => {
|
|
setTimeout(() => {
|
|
let time = video.currentTime,
|
|
playState = !video.paused
|
|
video.src = url
|
|
video.currentTime = time
|
|
playState ? video.play() : ""
|
|
}, 5000);
|
|
})
|
|
}
|
|
});
|
|
file.createReadStream().pipe(parser)
|
|
}
|
|
} |