bigbluebutton-Github/export-annotations/workers/collector.js
2022-06-29 14:07:28 +02:00

111 lines
3.6 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const Logger = require('../lib/utils/logger');
const config = require('../config');
const fs = require('fs');
const redis = require('redis');
const { Worker, workerData, parentPort } = require('worker_threads');
const path = require('path');
const probe = require('probe-image-size');
const { execSync } = require("child_process");
const jobId = workerData;
const logger = new Logger('presAnn Collector');
logger.info("Collecting job " + jobId);
const kickOffProcessWorker = (jobId) => {
return new Promise((resolve, reject) => {
const worker = new Worker('./workers/process.js', { workerData: jobId });
worker.on('message', resolve);
worker.on('error', reject);
worker.on('exit', (code) => {
if (code !== 0)
reject(new Error(`PresAnn Process Worker stopped with exit code ${code}`));
})
})
}
const dropbox = path.join(config.shared.presAnnDropboxDir, jobId);
// Takes the Job from the dropbox
let job = fs.readFileSync(path.join(dropbox, 'job'));
let exportJob = JSON.parse(job);
// Collect the annotations from Redis
(async () => {
const client = redis.createClient({
host: config.redis.host,
port: config.redis.port,
password: config.redis.password
});
client.on('error', (err) => logger.info('Redis Client Error', err));
await client.connect();
let presAnn = await client.hGetAll(exportJob.jobId);
// Remove annotations from Redis
await client.DEL(jobId);
client.disconnect();
let annotations = JSON.stringify(presAnn);
let whiteboard = JSON.parse(annotations);
let pages = JSON.parse(whiteboard.pages);
fs.writeFile(path.join(dropbox, 'whiteboard'), annotations, function(err) {
if(err) { return logger.error(err); }
});
// Collect the Presentation Page files (PDF / PNG / JPEG) from the presentation directory
let presentationFile = path.join(exportJob.presLocation, exportJob.presId);
let pdfFile = `${presentationFile}.pdf`
if (fs.existsSync(pdfFile)) {
for (let p of pages) {
let pageNumber = p.page;
let svgFile = path.join(exportJob.presLocation, 'svgs', `slide${pageNumber}.svg`)
let outputFile = path.join(dropbox, `slide${pageNumber}`);
// CairoSVG doesn't handle transparent SVG and PNG embeds properly, e.g., in rasterized text.
// So textboxes may get a black background when downloading/exporting repeatedly.
// To avoid that, we take slides from the uploaded file, but later probe the dimensions from the SVG
// so it matches what was shown in the browser -- Tldraw unfortunately uses absolute coordinates.
let extract_png_from_pdf = [
'pdftocairo',
'-png',
'-f', pageNumber,
'-l', pageNumber,
'-r', config.collector.backgroundSlidePPI,
'-singlefile',
'-cropbox',
pdfFile, outputFile,
].join(' ')
execSync(extract_png_from_pdf);
fs.copyFileSync(svgFile, path.join(dropbox, `slide${pageNumber}.svg`));
}
}
// If PNG file already available
else if (fs.existsSync(`${presentationFile}.png`)) {
fs.copyFileSync(`${presentationFile}.png`, path.join(dropbox, 'slide1.png'));
}
// If JPEG file available
else if (fs.existsSync(`${presentationFile}.jpeg`)) {
fs.copyFileSync(`${presentationFile}.jpeg`, path.join(dropbox, 'slide1.jpeg'));
}
else {
return logger.error(`Could not find whiteboard presentation file for job ${exportJob.jobId}`);
}
kickOffProcessWorker(exportJob.jobId);
})()
parentPort.postMessage({ message: workerData })