mirror of
https://github.com/ThaUnknown/miru.git
synced 2026-04-19 20:02:05 +00:00
offscreen canvas rendering implementation
This commit is contained in:
parent
c010b6459e
commit
7e675bc1e6
4 changed files with 9639 additions and 67 deletions
|
|
@ -44,7 +44,7 @@ async function renderSubs(trackNumber) {
|
|||
video: video,
|
||||
targetFps: await playerData.fps,
|
||||
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,
|
||||
renderMode: "offscreenCanvas",
|
||||
fonts: playerData.fonts?.length != 0 ? playerData.fonts : ["https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fBBc4.woff2"],
|
||||
workerUrl: 'js/subtitles-octopus-worker.js',
|
||||
timeOffset: 0
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -135,52 +135,69 @@ var SubtitlesOctopus = function (options) {
|
|||
renderOnDemand: self.renderAhead > 0,
|
||||
dropAllAnimations: self.dropAllAnimations
|
||||
});
|
||||
if (self.renderMode === "offscreenCanvas") {
|
||||
self.pushOffscreenCanvas()
|
||||
self.initDone = true
|
||||
}
|
||||
};
|
||||
self.pushOffscreenCanvas = function () {
|
||||
let canvasControl = self.canvas.transferControlToOffscreen()
|
||||
self.worker.postMessage({
|
||||
target: 'offscreenCanvas',
|
||||
canvas: canvasControl
|
||||
}, [canvasControl])
|
||||
}
|
||||
|
||||
self.createCanvas = function () {
|
||||
if (!self.canvas) {
|
||||
if (self.video) {
|
||||
self.isOurCanvas = true;
|
||||
self.canvas = document.createElement('canvas');
|
||||
self.canvas.className = 'libassjs-canvas';
|
||||
self.canvas.style.display = 'none';
|
||||
if (self.video) {
|
||||
self.isOurCanvas = true;
|
||||
self.canvas = document.createElement('canvas');
|
||||
self.canvas.className = 'libassjs-canvas';
|
||||
self.canvas.style.display = 'none';
|
||||
|
||||
self.canvasParent = document.createElement('div');
|
||||
self.canvasParent.className = 'libassjs-canvas-parent';
|
||||
self.canvasParent.appendChild(self.canvas);
|
||||
self.canvasParent = document.createElement('div');
|
||||
self.canvasParent.className = 'libassjs-canvas-parent';
|
||||
self.canvasParent.appendChild(self.canvas);
|
||||
|
||||
if (self.video.nextSibling) {
|
||||
self.video.parentNode.insertBefore(self.canvasParent, self.video.nextSibling);
|
||||
}
|
||||
else {
|
||||
self.video.parentNode.appendChild(self.canvasParent);
|
||||
}
|
||||
if (self.video.nextSibling) {
|
||||
self.video.parentNode.insertBefore(self.canvasParent, self.video.nextSibling);
|
||||
}
|
||||
else {
|
||||
if (!self.canvas) {
|
||||
self.workerError('Don\'t know where to render: you should give video or canvas in options.');
|
||||
}
|
||||
self.video.parentNode.appendChild(self.canvasParent);
|
||||
}
|
||||
}
|
||||
self.ctx = self.canvas.getContext('2d');
|
||||
self.bufferCanvas = document.createElement('canvas');
|
||||
self.bufferCanvasCtx = self.bufferCanvas.getContext('2d');
|
||||
else {
|
||||
if (!self.canvas) {
|
||||
self.workerError('Don\'t know where to render: you should give video or canvas in options.');
|
||||
}
|
||||
}
|
||||
if (!self.renderMode === "offscreenCanvas") {
|
||||
self.ctx = self.canvas.getContext('2d');
|
||||
}
|
||||
if (!typeof self.hasAlphaBug == "boolean") {
|
||||
self.bufferCanvas = document.createElement('canvas');
|
||||
self.bufferCanvasCtx = self.bufferCanvas.getContext('2d');
|
||||
self.bufferCanvas2 = document.createElement('canvas');
|
||||
self.bufferCanvasCtx2 = self.bufferCanvas.getContext('2d');
|
||||
|
||||
// test for alpha bug, where e.g. WebKit can render a transparent pixel
|
||||
// (with alpha == 0) as non-black which then leads to visual artifacts
|
||||
self.bufferCanvas.width = 1;
|
||||
self.bufferCanvas.height = 1;
|
||||
var testBuf = new Uint8ClampedArray([0, 255, 0, 0]);
|
||||
var testImage = new ImageData(testBuf, 1, 1);
|
||||
self.bufferCanvasCtx.clearRect(0, 0, 1, 1);
|
||||
self.ctx.clearRect(0, 0, 1, 1);
|
||||
var prePut = self.ctx.getImageData(0, 0, 1, 1).data;
|
||||
self.bufferCanvasCtx.putImageData(testImage, 0, 0);
|
||||
self.ctx.drawImage(self.bufferCanvas, 0, 0);
|
||||
var postPut = self.ctx.getImageData(0, 0, 1, 1).data;
|
||||
self.hasAlphaBug = prePut[1] != postPut[1];
|
||||
if (self.hasAlphaBug) {
|
||||
console.log("Detected a browser having issue with transparent pixels, applying workaround");
|
||||
// test for alpha bug, where e.g. WebKit can render a transparent pixel
|
||||
// (with alpha == 0) as non-black which then leads to visual artifacts
|
||||
self.bufferCanvas.width = 1;
|
||||
self.bufferCanvas.height = 1;
|
||||
self.bufferCanvas2.width = 1;
|
||||
self.bufferCanvas2.height = 1;
|
||||
var testBuf = new Uint8ClampedArray([0, 255, 0, 0]);
|
||||
var testImage = new ImageData(testBuf, 1, 1);
|
||||
self.bufferCanvasCtx.clearRect(0, 0, 1, 1);
|
||||
self.bufferCanvasCtx2.clearRect(0, 0, 1, 1);
|
||||
var prePut = self.bufferCanvasCtx2.getImageData(0, 0, 1, 1).data;
|
||||
self.bufferCanvasCtx.putImageData(testImage, 0, 0);
|
||||
self.bufferCanvasCtx2.drawImage(self.bufferCanvas, 0, 0);
|
||||
var postPut = self.bufferCanvasCtx2.getImageData(0, 0, 1, 1).data;
|
||||
self.hasAlphaBug = prePut[1] != postPut[1];
|
||||
if (self.hasAlphaBug) {
|
||||
console.log("Detected a browser having issue with transparent pixels, applying workaround");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -544,7 +561,7 @@ var SubtitlesOctopus = function (options) {
|
|||
case 'canvas': {
|
||||
switch (data.op) {
|
||||
case 'getContext': {
|
||||
self.ctx = self.canvas.getContext(data.type, data.attributes);
|
||||
if (!self.renderMode === "offscreenCanvas") self.ctx = self.canvas.getContext(data.type, data.attributes);
|
||||
break;
|
||||
}
|
||||
case 'resize': {
|
||||
|
|
@ -754,6 +771,10 @@ var SubtitlesOctopus = function (options) {
|
|||
self.canvas.style.left != left
|
||||
) {
|
||||
|
||||
if (self.renderMode == "offscreenCanvas" && self.initDone) {
|
||||
self.canvasParent.remove()
|
||||
self.createCanvas()
|
||||
}
|
||||
if (videoSize != null) {
|
||||
self.canvasParent.style.position = 'relative';
|
||||
self.canvas.style.display = 'block';
|
||||
|
|
@ -770,6 +791,9 @@ var SubtitlesOctopus = function (options) {
|
|||
self.canvas.style.width = videoSize.width + 'px';
|
||||
self.canvas.style.height = videoSize.height + 'px';
|
||||
}
|
||||
if (self.renderMode == "offscreenCanvas" && self.initDone) {
|
||||
self.pushOffscreenCanvas()
|
||||
}
|
||||
self.worker.postMessage({
|
||||
target: 'canvas',
|
||||
width: self.canvas.width,
|
||||
|
|
|
|||
|
|
@ -6,42 +6,47 @@ Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour,
|
|||
Style: Default,Roboto Medium,26,&H00FFFFFF,&H000000FF,&H00020713,&H00000000,0,0,0,0,100,100,0,0,1,1.3,0,2,20,20,23,1`
|
||||
let options = {
|
||||
video: video,
|
||||
lossyRender: true,
|
||||
fonts: ["https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fBBc4.woff2"],
|
||||
workerUrl: 'js/subtitles-octopus-worker.js',
|
||||
subContent: header,
|
||||
renderMode: "offscreenCanvas",
|
||||
onReady: ready,
|
||||
debug: true,
|
||||
onError: console.log
|
||||
};
|
||||
let octopusInstance = new SubtitlesOctopus(options);
|
||||
let octopusInstance
|
||||
setTimeout(() => {
|
||||
octopusInstance = new SubtitlesOctopus(options);
|
||||
}, 1000)
|
||||
|
||||
function ready() {
|
||||
octopusInstance.createEvent({
|
||||
Duration: 2960,
|
||||
Effect: "",
|
||||
Layer: 100,
|
||||
MarginL: 0,
|
||||
MarginR: 0,
|
||||
MarginV: 0,
|
||||
Name: "",
|
||||
ReadOrder: 0,
|
||||
Start: 180,
|
||||
Style: 1,
|
||||
Text: "Miss Kobayashi's Dragon Something!",
|
||||
})
|
||||
octopusInstance.createEvent({
|
||||
Duration: 1750,
|
||||
Effect: "",
|
||||
Layer: 100,
|
||||
MarginL: 0,
|
||||
MarginR: 0,
|
||||
MarginV: 0,
|
||||
Name: "",
|
||||
ReadOrder: 1,
|
||||
Start: 1940,
|
||||
Style: 1,
|
||||
Text: "What's with the "
|
||||
})
|
||||
setTimeout(() => {
|
||||
octopusInstance.createEvent({
|
||||
Duration: 2960,
|
||||
Effect: "",
|
||||
Layer: 100,
|
||||
MarginL: 0,
|
||||
MarginR: 0,
|
||||
MarginV: 0,
|
||||
Name: "",
|
||||
ReadOrder: 0,
|
||||
Start: 180,
|
||||
Style: 1,
|
||||
Text: "Miss Kobayashi's Dragon Something!",
|
||||
})
|
||||
octopusInstance.createEvent({
|
||||
Duration: 1750,
|
||||
Effect: "",
|
||||
Layer: 100,
|
||||
MarginL: 0,
|
||||
MarginR: 0,
|
||||
MarginV: 0,
|
||||
Name: "",
|
||||
ReadOrder: 1,
|
||||
Start: 1940,
|
||||
Style: 1,
|
||||
Text: "What's with the "
|
||||
})
|
||||
}, 1000)
|
||||
}
|
||||
</script>
|
||||
Loading…
Reference in a new issue