Commit 2a90ab81 by ramdayalmunda

transfered and adjucted code from server to jobs

parent e2e52f84
node_modules/
temporary/
logs/
\ No newline at end of file
module.exports.CONFIG = {
PORT: process.env.PORT || 5000,
S3_ACCESS_KEY: process.env.S3_ACCESS_KEY,
S3_SECRET_KEY: process.env.S3_SECRET_KEY,
S3_BUCKET_NAME: process.env.S3_BUCKET_NAME,
S3_REGION: process.env.S3_REGION,
}
\ No newline at end of file
const { STATUS_CODE } = require("../helper/constants")
const { generateCanvas, mergeImages } = require("../helper/tutor-shot")
const path = require('path')
const sharp = require('sharp')
const fs = require('fs')
const { createVideoFromImages } = require("../helper/ffmpeg-helper")
const { deleteFile } = require("../helper/utilities")
module.exports.generateVideo = async function(req, res){
module.exports.generateVideo = async function (req, res) {
console.log('generate Video', req.body)
try{
try {
let tutorShotData = req.body.tutorShotData;
let videoPath = req.body.videoPath
let thumbnailPath = req.body.thumbnailPath
let fileName = req.body.fileName
let thumbnailName = req.body.thumbnailName
if (tutorShotData) {
let imageDir = path.join(__dirname, '..', 'temporary', 'images')
let imagePathString = path.join(imageDir, `${tutorShotData._id}_%d.png`)
// // this is to generate each individual images and get their buffers
let frameNumber = 1;
let imageArr = []
for (let i = 0; i < tutorShotData.segments.length; i++) {
if (tutorShotData.segments[i].imageUrl) tutorShotData.segments[i].signedImageUrl = await generatePreSignedGetUrl(tutorShotData.segments[i].imageUrl)
// if (tutorShotData.segments[i].thumbnailUrl) tutorShotData.segments[i].signedThumbnailUrl = await generatePreSignedGetUrl(tutorShotData.segments[i].thumbnailUrl)
let CE = generateCanvas(tutorShotData.segments[i], { dimension: tutorShotData.segments[i].dimension })
let mergedImage = await mergeImages(
[
{ url: tutorShotData.segments[i].signedImageUrl },
{ buffer: await CE.getBuffer() }
],
{
// outputType: "buffer",
return: "Buffer",
}
)
let limit = 24 * ((tutorShotData.segments[i]?.duration) ? (tutorShotData.segments[i].duration) : 2);
let frameNum = 0
do {
let fileName = path.join(imageDir, `${tutorShotData._id}_${frameNumber++}.png`)
imageArr.push(fileName)
await sharp(mergedImage).toFile(fileName)
} while (++frameNum < limit)
if (i == 0 && thumbnailPath) {
const imageBase64 = Buffer.from(mergedImage, 'base64'); // Replace 'your_image_buffer_data_here' with your actual image buffer data
// Write the buffer data to the file
await fs.writeFile(thumbnailPath, imageBase64);
}
}
let options = {
outputFilePath: path.dirname(videoPath),
outputFileName: path.parse(videoPath).name,
outputFormat: path.extname(videoPath).slice(1),
frameRate: 24,
imagePathString: imagePathString,
deleteImages: true,// default is true
}
await createVideoFromImages([], options)
// to delete the individual frames that were generated and the thumbnail
!(async function () {
deleteFile(imageArr)
})()
return videoPath
}
let remotePath = path.join(CONFIG.S3_PATH.TUTOR_SHOT, fileName)
let remoteThumbnailPath = path.join(CONFIG.S3_PATH.TUTOR_SHOT, thumbnailName)
await uploadToAwsS3(videoPath, remotePath)
await uploadToAwsS3(thumbnailPath, remoteThumbnailPath)
res.status(STATUS_CODE.OK).json()
}catch(err){
} catch (err) {
console.log(err)
res.status(STATUS_CODE.ERROR).json()
}
......
let isModule = (typeof module != 'undefined') ? true : false
var CanvasEditor = function () {
if (isModule) var { createCanvas, Image: cImage } = require('canvas')
var uniqueCounter = 1;
var canvas;
var container;
var elements = []
var handleElements = [
{ name: "left-middle", points: [{ x: -1, y: -1 }, { x: -1, y: -1 }, { x: -1, y: -1 }, { x: -1, y: -1 }], oppositeIndex: 1, position: { left: -1, top: -1 }, horizontal: 1, vertical: 0 },
{ name: "right-middle", points: [{ x: -1, y: -1 }, { x: -1, y: -1 }, { x: -1, y: -1 }, { x: -1, y: -1 }], oppositeIndex: 0, position: { left: -1, top: -1 }, horizontal: -1, vertical: 0 },
{ name: "rotate", points: [{ x: -1, y: -1 }, { x: -1, y: -1 }, { x: -1, y: -1 }, { x: -1, y: -1 }], oppositeIndex: -1, position: { left: -1, top: -1 } },
{ name: "top-middle", points: [{ x: -1, y: -1 }, { x: -1, y: -1 }, { x: -1, y: -1 }, { x: -1, y: -1 }], oppositeIndex: 4, position: { left: -1, top: -1 }, horizontal: 0, vertical: 1 },
{ name: "bottom-middle", points: [{ x: -1, y: -1 }, { x: -1, y: -1 }, { x: -1, y: -1 }, { x: -1, y: -1 }], oppositeIndex: 3, position: { left: -1, top: -1 }, horizontal: 0, vertical: -1 },
{ name: "top-left", points: [{ x: -1, y: -1 }, { x: -1, y: -1 }, { x: -1, y: -1 }, { x: -1, y: -1 }], oppositeIndex: 8, position: { left: -1, top: -1 } },
{ name: "top-right", points: [{ x: -1, y: -1 }, { x: -1, y: -1 }, { x: -1, y: -1 }, { x: -1, y: -1 }], oppositeIndex: 7, position: { left: -1, top: -1 } },
{ name: "bottom-left", points: [{ x: -1, y: -1 }, { x: -1, y: -1 }, { x: -1, y: -1 }, { x: -1, y: -1 }], oppositeIndex: 6, position: { left: -1, top: -1 } },
{ name: "bottom-right", points: [{ x: -1, y: -1 }, { x: -1, y: -1 }, { x: -1, y: -1 }, { x: -1, y: -1 }], oppositeIndex: 5, position: { left: -1, top: -1 } },
]
let images = []
let assetsToLoad = 0;
let callbackAfterLoading = null
var configuration = { angleSnap: [0, 90, 180, 270, 360], angleSnapRange: 5, env: "dev" }
var hoverElement = null;
var selectedElement = null;
var isAction = null; // set to 'dragging' // 'resizing' // 'rotating'
var actionData = {
clickCounter: 0,
}
var hoverHandle = null;
var selectedHandle = null;
var oppositeHandle = null;
var constants = {
handleLineWidth: 4,
handleStrokeStyle: "#8bfff9",
fillStyle: "#fff",
handleWidth: 25,
}
var historyIndex = -1; // -1 indicates; no more undo possible
var initialData = []; // the last undo option
var history = []
function init() {
if (isModule) {
canvas = new createCanvas(configuration.dimension.width, configuration.dimension.height)
} else {
canvas = document.createElement('canvas')
canvas.setAttribute('id', `my-canvas-${new Date().getTime()}`);
canvas.setAttribute('style', `position:absolute; top:0; left:0; width:100%;`)
canvas.height = configuration.dimension.height
canvas.width = configuration.dimension.width
container.append(canvas)
canvas.addEventListener('mousedown', mouseDown)
canvas.addEventListener('mouseleave', mouseLeave)
canvas.addEventListener('mouseup', mouseUp)
canvas.addEventListener('mousemove', mouseMove)
canvas.addEventListener('wheel', printMousePos)
}
}
function mouseLeave(e) {
if (actionData.actionType != 'dragging') {
isAction = null;
actionData.actionType = null
}
}
function printMousePos(e) {
}
function getMousePos(evt) {
var clx, cly
if (evt.type == "touchstart" || evt.type == "touchmove") {
clx = evt.touches[0].clientX;
cly = evt.touches[0].clientY;
} else {
clx = evt.clientX;
cly = evt.clientY;
}
var boundingRect = canvas.getBoundingClientRect();
return {
x: (clx - boundingRect.left) * canvas.width / canvas.clientWidth,
y: (cly - boundingRect.top) * canvas.height / canvas.clientHeight
};
}
function finalizeAction() {
let changeObj = {}
if (actionData.actionType == 'dragging') {
selectedElement.position.top + (actionData.to.y - actionData.from.y)
changeObj.position = {
left: selectedElement.position.left + (actionData.to.x - actionData.from.x),
top: selectedElement.position.top + (actionData.to.y - actionData.from.y)
}
}
else if (actionData.actionType == 'resizing') {
changeObj.position = {
left: actionData.to.left,
top: actionData.to.top
}
changeObj.dimension = {
width: actionData.to.width,
height: actionData.to.height,
}
}
else if (actionData.actionType == 'rotating') {
changeObj.transform = { angle: actionData.to.angle }
}
// else if (actionData.type == 'formatting') {
// selectedElement.font.family = actionData.to.family
// selectedElement.font.size = actionData.to.size
// selectedElement.font.color = actionData.to.color
// selectedElement.font.bold = actionData.to.boldy
// selectedElement.font.italic = actionData.to.italic
// changeObj.font = { ...selectedElement.font }
// selectedElement.format.backgroundColor = actionData.to.backgroundColor
// selectedElement.format.borderColor = actionData.to.borderColor
// selectedElement.format.borderWidth = actionData.to.borderWidth
// changeObj.format = { ...selectedElement.format }
// }
if (['dragging', 'resizing', 'rotating'].includes(actionData.actionType)) modifySelected(changeObj, { toRender: false, isHistory: false })
delete actionData.from
delete actionData.to
}
function mouseMove(e) {
// Draw the quadrilateral
let pos = getMousePos(e)
if (isAction && selectedElement) {
let oldCenter = { x: actionData.from.centerX, y: actionData.from.centerY }
if (isAction == 'dragging') {
actionData.to = pos
actionData.actionType = isAction
}
else if (isAction == 'resizing') {
actionData.actionType = isAction
actionData.to = pos
actionData.to.y = actionData.from.y
pos = getMousePos(e)
let newPoint = getPerpendicular(
{ x: oppositeHandle.position.left, y: oppositeHandle.position.top },
{ x: selectedHandle.position.left, y: selectedHandle.position.top },
pos,
)
if (selectedHandle.horizontal && selectedHandle.vertical) {
} else {
let oppositeDistance = Math.sqrt(((oppositeHandle.position.left - newPoint.x) ** 2) + ((oppositeHandle.position.top - newPoint.y) ** 2))
let newCenter = { ...oldCenter }
if (selectedHandle.horizontal) {
newCenter.x = actionData.from.centerX + (selectedHandle.horizontal) * (selectedElement.dimension.width - oppositeDistance) / 2
let finalCenter = rotatePoint([newCenter.x, newCenter.y], [oldCenter.x, oldCenter.y], -selectedElement.transform.angle)
actionData.to.left = finalCenter.x - oppositeDistance / 2
actionData.to.top = finalCenter.y - selectedElement.dimension.height / 2
actionData.to.width = oppositeDistance
actionData.to.height = selectedElement.dimension.height
} else {
newCenter.y = actionData.from.centerY + (selectedHandle.vertical) * (selectedElement.dimension.height - oppositeDistance) / 2
let finalCenter = rotatePoint([newCenter.x, newCenter.y], [oldCenter.x, oldCenter.y], -selectedElement.transform.angle)
actionData.to.left = finalCenter.x - selectedElement.dimension.width / 2
actionData.to.top = finalCenter.y - oppositeDistance / 2
actionData.to.width = selectedElement.dimension.width
actionData.to.height = oppositeDistance
}
}
}
else if (isAction == 'rotating') {
let angle = Math.atan2((pos.y - oldCenter.y), (pos.x - oldCenter.x)) * 180 / Math.PI
angle += 90; // oue all elemtents have off by 90 always
angle = (angle % 360 + 360) % 360; // this is to resolve negative and >360 values
if (configuration.angleSnap) {
for (let i = 0; i < configuration.angleSnap.length; i++) {
let snapAngle = configuration.angleSnap[i]
let abs = Math.abs(angle - snapAngle)
if (abs <= configuration.angleSnapRange) {
angle = snapAngle
break
}
}
}
actionData.to = { angle: angle }
actionData.actionType = isAction
}
reRenderCanvas()
} else {
let found = false;
// check handles
for (let i = 0; i < handleElements.length; i++) {
var points = handleElements[i].points
let isInside = isPointInTriangle(pos, points[0], points[1], points[2]) || isPointInTriangle(pos, points[0], points[3], points[2])
if (isInside) {
found = true;
hoverHandle = handleElements[i]
break;
}
}
if (!found) {
hoverHandle = null
// then check element
for (let i = elements.length - 1; i >= 0; i--) {
let points = elements[i].points
if (points?.length && points.length == 4) {
var isInside = isPointInTriangle(pos, points[0], points[1], points[2]) || isPointInTriangle(pos, points[0], points[3], points[2])
if (isInside) {
hoverElement = elements[i]
found = true
break;
}
}
}
}
if (!found) hoverElement = null;
}
}
function getPerpendicular(p1, p2, p3) {
let slopeP1 = (p2.y - p1.y) / (p2.x - p1.x)
let slopeP2 = -1 / slopeP1
slopeP2 = Math.round(slopeP2 * 1000) / 1000
let p4 = { x: NaN, y: NaN }
if (slopeP1 == 0) {
p4.x = p3.x
p4.y = p1.y
}
else if (slopeP2 == 0) {
p4.x = p1.x
p4.y = p3.y
}
else {
p4.x = (p3.y - p1.y + slopeP1 * p1.x - slopeP2 * p3.x) / (slopeP1 - slopeP2);
p4.y = p1.y + slopeP1 * p4.x - slopeP1 * p1.x
}
return p4
}
function fillCanvas(color) {
let ctx = canvas.getContext('2d')
ctx.save()
ctx.fillStyle = color;
ctx.fillRect(0, 0, canvas.width, canvas.height)
ctx.restore()
}
function reRenderCanvas() {
let ctx = canvas.getContext('2d')
ctx.save()
ctx.clearRect(0, 0, canvas.width, canvas.height)
// loop and check overlays and draw data
for (let i = 0; i < elements.length; i++) {
if (elements[i].type == 'overlay') {
fillCanvas(elements[i].format.backgroundColor)
}
}
for (let i = 0; i < elements.length; i++) {
let tempElemData = elements[i]
if (tempElemData.id == selectedElement?.id) {
continue
}
renderElement(tempElemData)
}
// render the handles if selectedItem is Present
if (selectedElement) {
let tempElemData = selectedElement
if (actionData.actionType == 'dragging') {
tempElemData = JSON.parse(JSON.stringify(selectedElement))
tempElemData.position.left += (actionData.to.x - actionData.from.x)
tempElemData.position.top += (actionData.to.y - actionData.from.y)
}
if (actionData.actionType == 'resizing') {
tempElemData = JSON.parse(JSON.stringify(selectedElement))
tempElemData.position.left = actionData.to.left
tempElemData.position.top = actionData.to.top
tempElemData.dimension.width = actionData.to.width
tempElemData.dimension.height = actionData.to.height
}
if (actionData.actionType == 'rotating') {
tempElemData = JSON.parse(JSON.stringify(selectedElement))
tempElemData.transform.angle = actionData.to.angle
}
// this is element
renderElement(tempElemData)
// this is border
insertHandles({
...tempElemData,
position: {
left: tempElemData.position.left,
top: tempElemData.position.top,
},
format: {
backgroundColor: "#00000000",
borderColor: "#6bffd9",
borderWidth: 2,
}
})
}
ctx.restore()
if (assetsToLoad == 0 && callbackAfterLoading) {
callbackAfterLoading()
}
}
function mouseDown(e) {
if (e.button == 2) {
mouseUp(e)
return
}
let pos = getMousePos(e)
actionData.clickCounter++
if (selectedElement) {
actionData.from = pos
actionData.from.left = selectedElement.position.left
actionData.from.top = selectedElement.position.top
actionData.from.centerX = selectedElement.position.left + selectedElement.dimension.width / 2
actionData.from.centerY = selectedElement.position.top + selectedElement.dimension.height / 2
actionData.from.height = selectedElement.dimension.height
actionData.from.width = selectedElement.dimension.width
actionData.from.angle = selectedElement.transform.angle
}
if (hoverHandle && selectedElement) {
selectedHandle = hoverHandle
oppositeHandle = handleElements[selectedHandle.oppositeIndex]
isAction = selectedHandle.name == 'rotate' ? 'rotating' : 'resizing'
} else {
selectedHandle = null
selectedElement = hoverElement
if (selectedElement) {
isAction = 'dragging'
actionData.from = pos
} else {
isAction = null;
}
}
reRenderCanvas()
}
function mouseUp(e) {
if (isAction) {
finalizeAction(actionData)
actionData.actionType = null
reRenderCanvas()
}
isAction = null;
actionData.actionType = isAction
}
function isPointInTriangle(p0, p1, p2, p3) {
// Calculate the area of the main triangle
var area = 0.5 * (-p2.y * p3.x + p1.y * (-p2.x + p3.x) + p1.x * (p2.y - p3.y) + p2.x * p3.y);
// Calculate the barycentric coordinates
var s = (1 / (2 * area)) * (p1.y * p3.x - p1.x * p3.y + (p3.y - p1.y) * p0.x + (p1.x - p3.x) * p0.y);
var t = (1 / (2 * area)) * (p1.x * p2.y - p1.y * p2.x + (p1.y - p2.y) * p0.x + (p2.x - p1.x) * p0.y);
// Check if the point is inside the triangle
return s > 0 && t > 0 && 1 - s - t > 0;
}
function rotatePoint(point, fixedPoint, angleDegrees) {
// Convert angle from degrees to radians
var angleRadians = -angleDegrees * Math.PI / 180;
// Compute new coordinates
var new_x = fixedPoint[0] + (point[0] - fixedPoint[0]) * Math.cos(angleRadians) - (point[1] - fixedPoint[1]) * Math.sin(angleRadians);
var new_y = fixedPoint[1] + (point[0] - fixedPoint[0]) * Math.sin(angleRadians) + (point[1] - fixedPoint[1]) * Math.cos(angleRadians);
// Return new coordinates
return { x: new_x, y: new_y };
}
function insertText(elemData) {
const ctx = canvas.getContext('2d');
ctx.save()
// Set the maximum width for the text
const wrapWidth = elemData.dimension.width;
// Define the text to be displayed
const text = elemData.text;
// // Rotate the canvas by 45 degrees
ctx.font = `${elemData.font.italic ? 'italic ' : ''}${elemData.font.bold ? 'bold ' : ''}${elemData.font.size}px ${elemData.font.family}`;
ctx.fillStyle = `${elemData.font.color}`;
// Set the initial position for the text
let x = 0;
let y = 0;
let lineHeight = elemData.font.lineHeight ? elemData.font.lineHeight : elemData.font.size;
// Split the text into words
const words = text.split(' ');
let line = '';
let linesArr = []
for (let i = 0; i < words.length; i++) {
let testWidth = ctx.measureText(line + words[i]).width
if (testWidth < wrapWidth) {
line += words[i] + ' '
} else {
let wordWidth = ctx.measureText(words[i]).width
if (wordWidth < wrapWidth) {
linesArr.push([line, x, y])
line = words[i] + ' '
y += lineHeight
} else {
linesArr.push([line, 0, y])
let lineWidth = ctx.measureText(line).width
line = ""
let letters = ""
for (let l = 0; l < words[i].length; l++) {
let widthWithLetters = ctx.measureText(letters + words[i][l]).width
if ((widthWithLetters + lineWidth) < wrapWidth) {
letters += words[i][l]
} else {
linesArr.push([letters, lineWidth, y])
y += lineHeight
words.splice(i + 1, 0, words[i].slice(letters.length))
words[i] = letters
letters = ''
line = ""
break
}
}
}
}
}
linesArr.push([line, x, y])
let oldCenter = [elemData.position.left + elemData.dimension.width / 2, elemData.position.top + elemData.dimension.height / 2]
elemData.dimension.height = y + elemData.font.size + elemData.font.size / 3
let newCenter = [elemData.position.left + elemData.dimension.width / 2, elemData.position.top + elemData.dimension.height / 2]
let finalCenter = rotatePoint(newCenter, oldCenter, -elemData.transform.angle)
elemData.position.left = finalCenter.x - elemData.dimension.width / 2
elemData.position.top = finalCenter.y - elemData.dimension.height / 2
ctx.restore()
insertBlock(elemData)
ctx.save()
let left = elemData.position.left + elemData.dimension.width / 2
let top = elemData.position.top + (elemData.dimension.height / 2)
// // Rotate the canvas by 45 degrees
ctx.font = `${elemData.font.italic ? 'italic ' : ''}${elemData.font.bold ? 'bold ' : ''}${elemData.font.size}px ${elemData.font.family}`;
ctx.fillStyle = `${elemData.font.color}`;
// now generate the text over it
let angle = elemData.transform.angle
ctx.translate(left, top)
ctx.rotate(angle * Math.PI / 180);
let horizontalPadding = elemData.font.size / 5
let verticalPadding = elemData.font.size
for (let i = 0; i < linesArr.length; i++) {
ctx.fillText(
linesArr[i][0],
linesArr[i][1] - elemData.dimension.width / 2 + horizontalPadding,
linesArr[i][2] - elemData.dimension.height / 2 + verticalPadding
)
}
ctx.restore()
}
function insertBlock(elemData) {
elemData.points = []
let centerPoint = [elemData.position.left + elemData.dimension.width / 2, elemData.position.top + elemData.dimension.height / 2]
elemData.points.push(rotatePoint([elemData.position.left, elemData.position.top], centerPoint, -elemData.transform.angle))
elemData.points.push(rotatePoint([elemData.position.left + elemData.dimension.width, elemData.position.top], centerPoint, -elemData.transform.angle))
elemData.points.push(rotatePoint([elemData.position.left + elemData.dimension.width, elemData.position.top + elemData.dimension.height], centerPoint, -elemData.transform.angle))
elemData.points.push(rotatePoint([elemData.position.left, elemData.position.top + elemData.dimension.height], centerPoint, -elemData.transform.angle))
const ctx = canvas.getContext('2d');
ctx.save()
let width = elemData.dimension.width
let height = elemData.dimension.height
let x = -elemData.dimension.width / 2;
let y = -elemData.dimension.height / 2;
let cornerRadius = elemData?.format?.borderRadius ? elemData.format.borderRadius : 0
let radians = elemData.transform.angle * Math.PI / 180
ctx.translate(elemData.position.left + elemData.dimension.width / 2, elemData.position.top + elemData.dimension.height / 2)
ctx.rotate(radians)
if (elemData.format.borderWidth) {
ctx.lineWidth = elemData.format.borderWidth;
ctx.strokeStyle = elemData.format.borderColor;
}
ctx.beginPath();
ctx.moveTo(x + cornerRadius, y);
ctx.arcTo(x + width, y, x + width, y + height, cornerRadius);
ctx.arcTo(x + width, y + height, x, y + height, cornerRadius);
ctx.arcTo(x, y + height, x, y, cornerRadius);
ctx.arcTo(x, y, x + width, y, cornerRadius);
ctx.closePath();
ctx.fillStyle = elemData.format.backgroundColor
ctx.fill();
if (elemData.format.borderWidth) ctx.stroke();
ctx.restore()
}
function renderElement(elemData) {
if (elemData.type == 'text') {
insertText(elemData)
}
else if (elemData.type == 'block') {
insertBlock(elemData)
}
else if (elemData.type == 'overlay') {
insertOverlay(elemData)
}
else if (elemData.type == 'image') {
insertImage(elemData)
}
}
function insertHandles(elemData) {
insertBlock(elemData)
let ctx = canvas.getContext('2d')
ctx.save()
let centerPoint = [elemData.position.left + elemData.dimension.width / 2, elemData.position.top + elemData.dimension.height / 2]
let rotateHandleMinHeight = 50
ctx.lineWidth = elemData.format.borderWidth;
ctx.strokeStyle = elemData.format.borderColor;
ctx.beginPath();
ctx.translate(centerPoint[0], centerPoint[1])
ctx.rotate(elemData.transform.angle * Math.PI / 180)
ctx.moveTo(0, -elemData.dimension.height / 2);
ctx.lineTo(0, -rotateHandleMinHeight - elemData.dimension.height / 2);
ctx.closePath();
ctx.stroke();
ctx.restore()
ctx = canvas.getContext('2d')
ctx.save()
ctx.beginPath();
ctx.lineWidth = constants.handleLineWidth;
ctx.strokeStyle = constants.handleStrokeStyle;
ctx.fillStyle = constants.fillStyle
ctx.translate(elemData.position.left + elemData.dimension.width / 2, elemData.position.top + elemData.dimension.height / 2)
ctx.rotate(elemData.transform.angle * Math.PI / 180)
function drawHandle(handleIndex, handleName, point) {
ctx.moveTo(startPos.x, startPos.y);
ctx.lineTo(startPos.x + constants.handleWidth, startPos.y);
ctx.lineTo(startPos.x + constants.handleWidth, startPos.y + constants.handleWidth);
ctx.lineTo(startPos.x, startPos.y + constants.handleWidth);
ctx.lineTo(startPos.x, startPos.y - constants.handleLineWidth / 2);
if (point) {
let points = [
rotatePoint([point.x - constants.handleWidth / 2, point.y - constants.handleWidth / 2], centerPoint, -elemData.transform.angle),
rotatePoint([point.x + constants.handleWidth / 2, point.y - constants.handleWidth / 2], centerPoint, -elemData.transform.angle),
rotatePoint([point.x + constants.handleWidth / 2, point.y + constants.handleWidth / 2], centerPoint, -elemData.transform.angle),
rotatePoint([point.x - constants.handleWidth / 2, point.y + constants.handleWidth / 2], centerPoint, -elemData.transform.angle),
]
let basePoint = rotatePoint([point.x, point.y], centerPoint, -elemData.transform.angle)
handleElements[handleIndex] = {
name: handleName,
...handleElements[handleIndex], points,
position: { left: basePoint.x, top: basePoint.y }
}
}
}
// left middle handle
let startPos = { x: -(elemData.dimension.width / 2) - constants.handleWidth / 2, y: -constants.handleWidth / 2 }
drawHandle(0, 'left-middle', { x: elemData.position.left, y: elemData.position.top + elemData.dimension.height / 2 })
// right middle handle
startPos = { x: (elemData.dimension.width / 2) - constants.handleWidth / 2, y: -constants.handleWidth / 2 }
drawHandle(1, 'right-middle', { x: elemData.position.left + elemData.dimension.width, y: elemData.position.top + elemData.dimension.height / 2 })
// rotate handle
startPos = { x: -constants.handleWidth / 2, y: -rotateHandleMinHeight + (-elemData.dimension.height - constants.handleWidth) / 2 }
drawHandle(2, 'rotate', { x: elemData.position.left + elemData.dimension.width / 2, y: elemData.position.top - rotateHandleMinHeight })
if (!(elemData.type == 'text')) {
// top middle handle
startPos = { x: - constants.handleWidth / 2, y: -(constants.handleWidth + elemData.dimension.height) / 2 }
drawHandle(3, 'top-middle', { x: elemData.position.left + elemData.dimension.width / 2, y: elemData.position.top })
// bottom middle handle
startPos = { x: - constants.handleWidth / 2, y: (elemData.dimension.height - constants.handleWidth) / 2 }
drawHandle(4, 'bottom-middle', { x: elemData.position.left + elemData.dimension.width / 2, y: elemData.position.top + elemData.dimension.height })
// // top left handle
// startPos = { x: - (constants.handleWidth + elemData.dimension.width) / 2, y: -(elemData.dimension.height + constants.handleWidth) / 2 }
// drawHandle(5, 'top-left', { x: elemData.position.left, y: elemData.position.top })
// // top right handle
// startPos = { x: (elemData.dimension.width - constants.handleWidth) / 2, y: -(elemData.dimension.height + constants.handleWidth) / 2 }
// drawHandle(6, 'top-right', { x: elemData.position.left + elemData.dimension.width, y: elemData.position.top })
// // bottom left handle
// startPos = { x: (-elemData.dimension.width - constants.handleWidth) / 2, y: (elemData.dimension.height - constants.handleWidth) / 2 }
// drawHandle(7, 'bottom-left', { x: elemData.position.left, y: elemData.position.top + elemData.dimension.height })
// // bottom right handle
// startPos = { x: (elemData.dimension.width - constants.handleWidth) / 2, y: (elemData.dimension.height - constants.handleWidth) / 2 }
// drawHandle(8, 'bottom-right', { x: elemData.position.left + elemData.dimension.width, y: elemData.position.top + elemData.dimension.height })
}
ctx.stroke()
ctx.fill()
ctx.restore()
}
function insertOverlay(elemData) {
let ctx = canvas.getContext('2d')
ctx.save()
elemData.points = []
let centerPoint = [elemData.position.left + elemData.dimension.width / 2, elemData.position.top + elemData.dimension.height / 2]
elemData.points.push(rotatePoint([elemData.position.left, elemData.position.top], centerPoint, -elemData.transform.angle))
elemData.points.push(rotatePoint([elemData.position.left + elemData.dimension.width, elemData.position.top], centerPoint, -elemData.transform.angle))
elemData.points.push(rotatePoint([elemData.position.left + elemData.dimension.width, elemData.position.top + elemData.dimension.height], centerPoint, -elemData.transform.angle))
elemData.points.push(rotatePoint([elemData.position.left, elemData.position.top + elemData.dimension.height], centerPoint, -elemData.transform.angle))
let width = elemData.dimension.width
let height = elemData.dimension.height
let x = -elemData.dimension.width / 2;
let y = -elemData.dimension.height / 2;
let cornerRadius = elemData?.format?.borderRadius ? elemData.format.borderRadius : 0
let radians = elemData.transform.angle * Math.PI / 180
ctx.translate(elemData.position.left + elemData.dimension.width / 2, elemData.position.top + elemData.dimension.height / 2)
ctx.rotate(radians)
// remove the rectangular area
ctx.beginPath();
ctx.globalCompositeOperation = 'destination-out'
ctx.moveTo(x + cornerRadius, y);
ctx.arcTo(x + width, y, x + width, y + height, cornerRadius);
ctx.arcTo(x + width, y + height, x, y + height, cornerRadius);
ctx.arcTo(x, y + height, x, y, cornerRadius);
ctx.arcTo(x, y, x + width, y, cornerRadius);
ctx.closePath();
ctx.fillStyle = "white"
ctx.fill();
// add The border
ctx.beginPath();
ctx.globalCompositeOperation = 'source-over'
ctx.moveTo(x + cornerRadius, y);
ctx.arcTo(x + width, y, x + width, y + height, cornerRadius);
ctx.arcTo(x + width, y + height, x, y + height, cornerRadius);
ctx.arcTo(x, y + height, x, y, cornerRadius);
ctx.arcTo(x, y, x + width, y, cornerRadius);
ctx.closePath();
ctx.fillStyle = "#00000000"
ctx.fill();
if (elemData.format.borderWidth) {
ctx.lineWidth = elemData.format.borderWidth;
ctx.strokeStyle = elemData.format.borderColor;
}
ctx.stroke();
ctx.restore()
}
function insertImage(elemData) {
// to background and border if required
let tempObj = JSON.parse(JSON.stringify(elemData))
insertBlock(tempObj)
if (elemData.image) {
if (elemData.image.id && !elemData.image.loading) {
elemData.image.loading = false
let imageObj = images.find(item => item.id == elemData.image.id)
if (imageObj?.el) {
let ctx = canvas.getContext('2d')
ctx.save()
elemData.points = []
let centerPoint = [elemData.position.left + elemData.dimension.width / 2, elemData.position.top + elemData.dimension.height / 2]
elemData.points.push(rotatePoint([elemData.position.left, elemData.position.top], centerPoint, -elemData.transform.angle))
elemData.points.push(rotatePoint([elemData.position.left + elemData.dimension.width, elemData.position.top], centerPoint, -elemData.transform.angle))
elemData.points.push(rotatePoint([elemData.position.left + elemData.dimension.width, elemData.position.top + elemData.dimension.height], centerPoint, -elemData.transform.angle))
elemData.points.push(rotatePoint([elemData.position.left, elemData.position.top + elemData.dimension.height], centerPoint, -elemData.transform.angle))
let width = elemData.dimension.width
let height = elemData.dimension.height
let x = -elemData.dimension.width / 2;
let y = -elemData.dimension.height / 2;
let cornerRadius = elemData?.format?.borderRadius ? elemData.format.borderRadius : 0
let radians = elemData.transform.angle * Math.PI / 180
ctx.translate(elemData.position.left + elemData.dimension.width / 2, elemData.position.top + elemData.dimension.height / 2)
ctx.rotate(radians)
ctx.scale((elemData.transform.xFlip ? -1 : 1), (elemData.transform.yFlip ? -1 : 1))
ctx.drawImage(imageObj.el, x, y, width, height)
ctx.restore()
} else {
loadImage(elemData)
}
} else if (!elemData.image.loading) {
loadImage(elemData)
}
}
}
function loadImage(elemData) {
++assetsToLoad
elemData.image.loading = true
let img = null;
if (isModule) img = new cImage
else img = new Image
img.onload = function () {
elemData.image.id = `img-${uniqueCounter++}`
images.push({
id: elemData.image.id,
el: img,
})
elemData.image.loading = false
--assetsToLoad
reRenderCanvas()
}
img.onerror = err => { console.error(err) }
img.src = elemData.image.src
}
function modifySelected(obj, option = { isHistory: false, toRender: true }) {
let historyObj = {}
let elementToModify = option.isHistory ? obj.selectedElement : selectedElement
if (elementToModify && obj) {
historyObj.selectedElement = JSON.parse(JSON.stringify(elementToModify))
elementToModify = elements.find(item => item.id == elementToModify.id)
if (obj.hasOwnProperty('text')) {
elementToModify.text = obj.text
historyObj.text = elementToModify.text
}
if (obj?.font) {
historyObj.font = {}
if (obj.font.hasOwnProperty('color')) {
elementToModify.font.color = obj.font.color
historyObj.font.color = elementToModify.font.color
}
if (obj.font.hasOwnProperty('size')) {
elementToModify.font.size = obj?.font?.size
historyObj.font.size = elementToModify.font.size
}
if (obj.font.hasOwnProperty('family')) {
elementToModify.font.family = obj?.font?.family
historyObj.font.family = elementToModify.font.family
}
if (obj.font.hasOwnProperty('familyUrl')) {
elementToModify.font.familyUrl = obj?.font
historyObj.font.familyUrl = elementToModify.font.familyUrl
}
if (obj.font.hasOwnProperty('bold')) {
elementToModify.font.bold = obj?.font?.bold ? true : false
historyObj.font.bold = elementToModify.font.bold
}
if (obj.font.hasOwnProperty('italic')) {
elementToModify.font.italic = obj?.font?.italic ? true : false
historyObj.font.italic = elementToModify.font.italic
}
}
if (obj?.position) {
historyObj.position = {}
if (obj.position.hasOwnProperty('top')) {
elementToModify.position.top = obj.position.top
historyObj.position.top = elementToModify.position.top
}
if (obj.position.hasOwnProperty('left')) {
elementToModify.position.left = obj.position.left
historyObj.position.left = elementToModify.position.left
}
}
if (obj?.dimension) {
historyObj.dimension = {}
if (obj.dimension.hasOwnProperty('width')) {
elementToModify.dimension.width = obj.dimension.width
historyObj.dimension.width = elementToModify.dimension.width
}
if (obj.dimension.hasOwnProperty('height')) {
elementToModify.dimension.height = obj.dimension.height
historyObj.dimension.height = elementToModify.dimension.height
}
}
if (obj?.format) {
historyObj.format = {}
if (obj.format.hasOwnProperty('borderColor')) {
elementToModify.format.borderColor = obj.format.borderColor
historyObj.format.borderColor = elementToModify.format.borderColor
}
if (obj.format.hasOwnProperty('backgroundColor')) {
elementToModify.format.backgroundColor = obj.format.backgroundColor
historyObj.format.backgroundColor = elementToModify.format.backgroundColor
}
if (obj.format.hasOwnProperty('borderWidth')) {
elementToModify.format.borderWidth = obj.format.borderWidth
historyObj.format.borderWidth = elementToModify.format.borderWidth
}
}
if (obj?.transform) {
historyObj.transform = {}
if (obj.transform.hasOwnProperty('xFlip')) {
elementToModify.transform.xFlip = obj.transform.xFlip
historyObj.transform.xFlip = elementToModify.transform.xFlip
}
if (obj.transform.hasOwnProperty('yFlip')) {
elementToModify.transform.yFlip = obj.transform.yFlip
historyObj.transform.yFlip = elementToModify.transform.yFlip
}
if (obj.transform.hasOwnProperty('angle')) {
elementToModify.transform.angle = obj.transform.angle
historyObj.transform.angle = elementToModify.transform.angle
}
}
}
if (!option.isHistory) {
history.push(historyObj)
historyIndex = history.length - 1
}
if (option.toRender) reRenderCanvas()
window.historyList = history
}
function undo() {
if (historyIndex < 0) {
if (configuration.isDev) console.warn('UNDO: no previous history state to go to')
return
}
let thisData = history[historyIndex]
if (thisData?.selectedElement) {
let selectedElement = elements.find(item => item.id == thisData.selectedElement.id)
thisData.selectedElement.selectedElement = JSON.parse(JSON.stringify(selectedElement))
modifySelected(thisData.selectedElement, { toRender: true, isHistory: true })
--historyIndex
}
}
function redo() {
if (historyIndex >= history.length - 1) {
if (configuration.isDev) console.warn('REDO: no next history state to go to')
return
}
if (historyIndex < history.length) {
let thisData = history[historyIndex + 1]
let selectedElement = elements.find(item => item.id == thisData.selectedElement.id)
thisData.selectedElement = JSON.parse(JSON.stringify(selectedElement))
modifySelected(thisData, { isHistory: true, toRender: true })
++historyIndex
}
}
function clearHistory() {
// this is called when you want to clear the undo/redo states
// you won't be able to undo or redo if yuou invoke this method.
initialData = JSON.parse(JSON.stringify(elements))
history = []
}
let returnObj = {
getCanvas() { return canvas },
getElements() { return JSON.parse(JSON.stringify(elements)) },
getHandles() { return JSON.parse(JSON.stringify(handleElements)) },
mount(data) {
configuration = { ...configuration, ...data }
if (!isModule) container = document.getElementById(data.containerId)
init(data)
},
addElement(elemData) {
if (!elemData.id) elemData.id = `elem-${new Date().getTime()}-${uniqueCounter++}`
elements.push(elemData)
reRenderCanvas()
},
clearCanvas() {
elements = []
selectedElement = null
selectedHandle = null
reRenderCanvas()
},
reRenderCanvas,
toCanvasImage() {
if (!isModule) {
var image = new Image();
image.src = canvas.toDataURL("image/png");
var win = window.open();
win.document.write(image.outerHTML);
}
},
getSelectedItemData() {
if (selectedElement) return JSON.parse(JSON.stringify(selectedElement))
return null
},
modifySelected,
deleteElement(id) {
if (id) {
let elementIndex = elements.findIndex(item => item.id == id)
if (elementIndex != -1) elements.splice(elementIndex, 1)
}
selectedElement = null
selectedHandle = null
isAction = null
actionData.actionType = null
mouseUp()
reRenderCanvas()
},
async getBuffer() {
return new Promise((res, rej) => {
callbackAfterLoading = () => {
if (isModule) {
let newOptions = ['image/png', { compressionLevel: 3, filters: canvas.PNG_FILTER_NONE }]
res(canvas.toBuffer(...newOptions))
}
else {
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
res(imageData.data);
}
}
reRenderCanvas()
})
},
undo, redo, clearHistory,
}
return returnObj
}
if (isModule) module.exports = CanvasEditor
\ No newline at end of file
const sharp = require('sharp')
const ffmpeg = require('fluent-ffmpeg')
const fs = require('fs')
const path = require('path')
/**
*
* @param {[
* {
* filePath: 'String: path of the file you want',
* buffer: 'Buffer: buffer of the file you want',
* duration: 'Number: duration in seconds, how long you want the image to be displayed',
* }
* ]} imageArr
* @param {
* {
* outputFileName: "String: name of the video file, without extension; (required)",
* outputFormat: "String: mp4 (required)",
* frameRate: "Number: frames per second; (required, default: 1)",
* imagePathString: "String: path to the individual frames: ex:'/path/test-video_%d.png'",
* deleteImages: "Boolean: to delete the individual frames from the disk; (default: true)",
* outputFilePath: "String: path to the directory where the video would be generated",
* }
* } options
* @returns
*/
module.exports.createVideoFromImages = async function (imageArr, options) {
return new Promise(async (res, rej) => {
let frameRate = options?.frameRate ? options.frameRate : 24
let tempImageDir = path.join(__dirname, '..', 'temporary', 'images')
let outputFilePath = path.join(options.outputFilePath, `${options.outputFileName}.${options.outputFormat}`)
let imagePathString = options?.imagePathString
let deleteImages = (options && options?.hasOwnProperty('deleteImages')) ? (!!options.deleteImages) : true
let frameNumber = 1
let frames = []
if (!imagePathString) { // if the path is not generated then generate the path
imagePathString = path.join(tempImageDir, `${options.outputFileName}_%d.png`)
////// to create temporary image files //////
for (let i = 0; i < imageArr.length; i++) {
if (imageArr[i].filePath) {
let limit = imageArr[i]?.duration ? imageArr[i].duration : 1
limit = limit * frameRate
let frameNum = 0
do {
let newFilePath = path.join(tempImageDir, `${options.outputFileName}_${frameNumber++}.png`)
await sharp(imageArr[i].filePath).toFile(newFilePath)
frames.push(newFilePath)
} while (++frameNum < limit)
}
}
}
////// using ffmpeg creating video //////
ffmpeg()
.on('end', () => {
res(path.join(options.outputFilePath, `${options.outputFileName}.${options.outputFormat}`))
////// to delete the frames that are created //////
if (deleteImages)
frames.forEach((filePath) => {
fs.access(filePath, fs.constants.F_OK, (err) => {
if (!err) {
// File exists, proceed with deletion
fs.unlink(filePath, (err) => {
if (err) { console.error(`Error deleting ${filePath}:`, err); }
});
};
});
});
})
.on('error', (err) => {
console.error('Error creating video:', err);
rej(undefined, err)
})
.input(imagePathString)
.output(outputFilePath)
.outputFPS(frameRate) // Set frames per second as needed
.run();
})
}
module.exports.joinAudioVideo = async function (videoPath, audioPath, output) {
return new Promise((res, rej) => {
console.log('videoPath', videoPath)
console.log('audioPath', audioPath)
console.log('output', output)
ffmpeg()
.on('end', () => {
res(output)
})
.on('error', (err) => {
rej(err)
})
.input(videoPath)
.input(audioPath)
.output(output)
.run()
})
}
\ No newline at end of file
const CanvasEditor = require("./canvas-editor.js");
const sharp = require('sharp')
const axios = require('axios')
module.exports.generateCanvas = function (segmentData, options) {
let CE = new CanvasEditor()
CE.mount(options)
for (let i = 0; i < segmentData.object.length; i++) {
CE.addElement(segmentData.object[i])
}
return CE
}
module.exports.mergeImages = async function (imageArr, options) {
let imageSharp;
if (imageArr[0].url) {
let { data } = await axios.get(imageArr[0].url, { responseType: 'arraybuffer' });
imageSharp = sharp(Buffer.from(data))
delete data
}
let compositeArr = []
for (let i = 1; i < imageArr.length; i++) {
let nextSharp;
if (imageArr[i].url) {
let { data } = await axios.get(imageArr[i].url, { responseType: 'arraybuffer' });
nextSharp = sharp(Buffer.from(data))
delete data
} else if (imageArr[i].buffer) {
nextSharp = sharp(imageArr[i].buffer)
}
compositeArr.push({ input: await nextSharp.toBuffer() })
}
imageSharp.composite(compositeArr)
if (options.outputType == 'buffer') return imageSharp.toBuffer()
if (options.outputType == 'file' && options.outputFile) {
await imageSharp.toFile(options.outputFile)
return options.outputFile
}
return imageSharp
}
\ No newline at end of file
const Fs = require('fs');
const AWS = require('aws-sdk');
AWS.config.update({
accessKeyId: CONFIG.S3_ACCESS_KEY,
secretAccessKey: CONFIG.S3_SECRET_KEY,
});
const s3 = new AWS.S3({
params: { Bucket: CONFIG.S3_BUCKET_NAME, },
region: CONFIG.S3_REGION,
})
module.exports.uploadToAwsS3 = async function (localPath, remotePath, options) {
const buffer = Fs.readFileSync(localPath);
try {
var params = {
Body: buffer,
Bucket: CONFIG.S3_BUCKET_NAME,
Key: remotePath
};
s3.putObject(params, function (err, data) {
if (err) {
errorLog.error(err, `Exception handling error on uploadToAwsS3`);
}
// successful response
});
if (options && !options.preventUnlink) {
try { Fs.unlinkSync(localPath) }
catch (err) { console.log(err) }
}
return
} catch (error) {
errorLog.error(error, `error occur while uploading data to s3`);
return { status: httpStatus.NETWORK_ERROR, path: remotePath }
}
}
\ No newline at end of file
const fs = require('fs')
module.exports.createDirectory = function (directory) {
fs.mkdir(directory, { recursive: true }, (err) => {
if (err) {
console.error(`Error creating directory: ${err}`);
} else {
console.log(`Directory created successfully at: ${directory}`);
}
});
}
module.exports.deleteFile = function (item) {
function deleteFileByPath(path) {
fs.unlink(path, (err) => { if (err) console.log(err) })
}
if (typeof item == 'string') {
deleteFileByPath(item)
} else if (Array.isArray(item)) {
for (let i = 0; i < item.length; i++) {
if (typeof item[i] == 'string') deleteFileByPath(item[i])
}
}
return
}
const express = require('express')
const PORT = process.env.PORT || 5000;
const CONFIG = require('./config.js')
console.log('CONFIG', CONFIG)
const PORT = CONFIG.PORT;
const app = express()
const app = express()
app.use( require("./routes/tutor-shot") )
......
......@@ -9,8 +9,471 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"axios": "^1.6.7",
"canvas": "^2.11.2",
"express": "^4.18.3",
"mongoose": "^8.2.0"
"fluent-ffmpeg": "^2.1.2",
"mongoose": "^8.2.0",
"sharp": "^0.33.2"
}
},
"node_modules/@emnapi/runtime": {
"version": "0.45.0",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-0.45.0.tgz",
"integrity": "sha512-Txumi3td7J4A/xTTwlssKieHKTGl3j4A1tglBx72auZ49YK7ePY6XZricgIg9mnZT4xPfA+UPCUdnhRuEFDL+w==",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@img/sharp-darwin-arm64": {
"version": "0.33.2",
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.2.tgz",
"integrity": "sha512-itHBs1rPmsmGF9p4qRe++CzCgd+kFYktnsoR1sbIAfsRMrJZau0Tt1AH9KVnufc2/tU02Gf6Ibujx+15qRE03w==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"darwin"
],
"engines": {
"glibc": ">=2.26",
"node": "^18.17.0 || ^20.3.0 || >=21.0.0",
"npm": ">=9.6.5",
"pnpm": ">=7.1.0",
"yarn": ">=3.2.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-darwin-arm64": "1.0.1"
}
},
"node_modules/@img/sharp-darwin-x64": {
"version": "0.33.2",
"resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.2.tgz",
"integrity": "sha512-/rK/69Rrp9x5kaWBjVN07KixZanRr+W1OiyKdXcbjQD6KbW+obaTeBBtLUAtbBsnlTTmWthw99xqoOS7SsySDg==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"darwin"
],
"engines": {
"glibc": ">=2.26",
"node": "^18.17.0 || ^20.3.0 || >=21.0.0",
"npm": ">=9.6.5",
"pnpm": ">=7.1.0",
"yarn": ">=3.2.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-darwin-x64": "1.0.1"
}
},
"node_modules/@img/sharp-libvips-darwin-arm64": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.1.tgz",
"integrity": "sha512-kQyrSNd6lmBV7O0BUiyu/OEw9yeNGFbQhbxswS1i6rMDwBBSX+e+rPzu3S+MwAiGU3HdLze3PanQ4Xkfemgzcw==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"darwin"
],
"engines": {
"macos": ">=11",
"npm": ">=9.6.5",
"pnpm": ">=7.1.0",
"yarn": ">=3.2.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-darwin-x64": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.1.tgz",
"integrity": "sha512-eVU/JYLPVjhhrd8Tk6gosl5pVlvsqiFlt50wotCvdkFGf+mDNBJxMh+bvav+Wt3EBnNZWq8Sp2I7XfSjm8siog==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"darwin"
],
"engines": {
"macos": ">=10.13",
"npm": ">=9.6.5",
"pnpm": ">=7.1.0",
"yarn": ">=3.2.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-arm": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.1.tgz",
"integrity": "sha512-FtdMvR4R99FTsD53IA3LxYGghQ82t3yt0ZQ93WMZ2xV3dqrb0E8zq4VHaTOuLEAuA83oDawHV3fd+BsAPadHIQ==",
"cpu": [
"arm"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"glibc": ">=2.28",
"npm": ">=9.6.5",
"pnpm": ">=7.1.0",
"yarn": ">=3.2.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-arm64": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.1.tgz",
"integrity": "sha512-bnGG+MJjdX70mAQcSLxgeJco11G+MxTz+ebxlz8Y3dxyeb3Nkl7LgLI0mXupoO+u1wRNx/iRj5yHtzA4sde1yA==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"glibc": ">=2.26",
"npm": ">=9.6.5",
"pnpm": ">=7.1.0",
"yarn": ">=3.2.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-s390x": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.1.tgz",
"integrity": "sha512-3+rzfAR1YpMOeA2zZNp+aYEzGNWK4zF3+sdMxuCS3ey9HhDbJ66w6hDSHDMoap32DueFwhhs3vwooAB2MaK4XQ==",
"cpu": [
"s390x"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"glibc": ">=2.28",
"npm": ">=9.6.5",
"pnpm": ">=7.1.0",
"yarn": ">=3.2.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linux-x64": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.1.tgz",
"integrity": "sha512-3NR1mxFsaSgMMzz1bAnnKbSAI+lHXVTqAHgc1bgzjHuXjo4hlscpUxc0vFSAPKI3yuzdzcZOkq7nDPrP2F8Jgw==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"glibc": ">=2.26",
"npm": ">=9.6.5",
"pnpm": ">=7.1.0",
"yarn": ">=3.2.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linuxmusl-arm64": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.1.tgz",
"integrity": "sha512-5aBRcjHDG/T6jwC3Edl3lP8nl9U2Yo8+oTl5drd1dh9Z1EBfzUKAJFUDTDisDjUwc7N4AjnPGfCA3jl3hY8uDg==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"musl": ">=1.2.2",
"npm": ">=9.6.5",
"pnpm": ">=7.1.0",
"yarn": ">=3.2.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-linuxmusl-x64": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.1.tgz",
"integrity": "sha512-dcT7inI9DBFK6ovfeWRe3hG30h51cBAP5JXlZfx6pzc/Mnf9HFCQDLtYf4MCBjxaaTfjCCjkBxcy3XzOAo5txw==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"musl": ">=1.2.2",
"npm": ">=9.6.5",
"pnpm": ">=7.1.0",
"yarn": ">=3.2.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-linux-arm": {
"version": "0.33.2",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.2.tgz",
"integrity": "sha512-Fndk/4Zq3vAc4G/qyfXASbS3HBZbKrlnKZLEJzPLrXoJuipFNNwTes71+Ki1hwYW5lch26niRYoZFAtZVf3EGA==",
"cpu": [
"arm"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"glibc": ">=2.28",
"node": "^18.17.0 || ^20.3.0 || >=21.0.0",
"npm": ">=9.6.5",
"pnpm": ">=7.1.0",
"yarn": ">=3.2.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-arm": "1.0.1"
}
},
"node_modules/@img/sharp-linux-arm64": {
"version": "0.33.2",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.2.tgz",
"integrity": "sha512-pz0NNo882vVfqJ0yNInuG9YH71smP4gRSdeL09ukC2YLE6ZyZePAlWKEHgAzJGTiOh8Qkaov6mMIMlEhmLdKew==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"glibc": ">=2.26",
"node": "^18.17.0 || ^20.3.0 || >=21.0.0",
"npm": ">=9.6.5",
"pnpm": ">=7.1.0",
"yarn": ">=3.2.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-arm64": "1.0.1"
}
},
"node_modules/@img/sharp-linux-s390x": {
"version": "0.33.2",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.2.tgz",
"integrity": "sha512-MBoInDXDppMfhSzbMmOQtGfloVAflS2rP1qPcUIiITMi36Mm5YR7r0ASND99razjQUpHTzjrU1flO76hKvP5RA==",
"cpu": [
"s390x"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"glibc": ">=2.28",
"node": "^18.17.0 || ^20.3.0 || >=21.0.0",
"npm": ">=9.6.5",
"pnpm": ">=7.1.0",
"yarn": ">=3.2.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-s390x": "1.0.1"
}
},
"node_modules/@img/sharp-linux-x64": {
"version": "0.33.2",
"resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.2.tgz",
"integrity": "sha512-xUT82H5IbXewKkeF5aiooajoO1tQV4PnKfS/OZtb5DDdxS/FCI/uXTVZ35GQ97RZXsycojz/AJ0asoz6p2/H/A==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"glibc": ">=2.26",
"node": "^18.17.0 || ^20.3.0 || >=21.0.0",
"npm": ">=9.6.5",
"pnpm": ">=7.1.0",
"yarn": ">=3.2.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linux-x64": "1.0.1"
}
},
"node_modules/@img/sharp-linuxmusl-arm64": {
"version": "0.33.2",
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.2.tgz",
"integrity": "sha512-F+0z8JCu/UnMzg8IYW1TMeiViIWBVg7IWP6nE0p5S5EPQxlLd76c8jYemG21X99UzFwgkRo5yz2DS+zbrnxZeA==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"musl": ">=1.2.2",
"node": "^18.17.0 || ^20.3.0 || >=21.0.0",
"npm": ">=9.6.5",
"pnpm": ">=7.1.0",
"yarn": ">=3.2.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linuxmusl-arm64": "1.0.1"
}
},
"node_modules/@img/sharp-linuxmusl-x64": {
"version": "0.33.2",
"resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.2.tgz",
"integrity": "sha512-+ZLE3SQmSL+Fn1gmSaM8uFusW5Y3J9VOf+wMGNnTtJUMUxFhv+P4UPaYEYT8tqnyYVaOVGgMN/zsOxn9pSsO2A==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"musl": ">=1.2.2",
"node": "^18.17.0 || ^20.3.0 || >=21.0.0",
"npm": ">=9.6.5",
"pnpm": ">=7.1.0",
"yarn": ">=3.2.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-libvips-linuxmusl-x64": "1.0.1"
}
},
"node_modules/@img/sharp-wasm32": {
"version": "0.33.2",
"resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.2.tgz",
"integrity": "sha512-fLbTaESVKuQcpm8ffgBD7jLb/CQLcATju/jxtTXR1XCLwbOQt+OL5zPHSDMmp2JZIeq82e18yE0Vv7zh6+6BfQ==",
"cpu": [
"wasm32"
],
"optional": true,
"dependencies": {
"@emnapi/runtime": "^0.45.0"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0",
"npm": ">=9.6.5",
"pnpm": ">=7.1.0",
"yarn": ">=3.2.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-win32-ia32": {
"version": "0.33.2",
"resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.2.tgz",
"integrity": "sha512-okBpql96hIGuZ4lN3+nsAjGeggxKm7hIRu9zyec0lnfB8E7Z6p95BuRZzDDXZOl2e8UmR4RhYt631i7mfmKU8g==",
"cpu": [
"ia32"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0",
"npm": ">=9.6.5",
"pnpm": ">=7.1.0",
"yarn": ">=3.2.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-win32-x64": {
"version": "0.33.2",
"resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.2.tgz",
"integrity": "sha512-E4magOks77DK47FwHUIGH0RYWSgRBfGdK56kIHSVeB9uIS4pPFr4N2kIVsXdQQo4LzOsENKV5KAhRlRL7eMAdg==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0",
"npm": ">=9.6.5",
"pnpm": ">=7.1.0",
"yarn": ">=3.2.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@mapbox/node-pre-gyp": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
"integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==",
"dependencies": {
"detect-libc": "^2.0.0",
"https-proxy-agent": "^5.0.0",
"make-dir": "^3.1.0",
"node-fetch": "^2.6.7",
"nopt": "^5.0.0",
"npmlog": "^5.0.1",
"rimraf": "^3.0.2",
"semver": "^7.3.5",
"tar": "^6.1.11"
},
"bin": {
"node-pre-gyp": "bin/node-pre-gyp"
}
},
"node_modules/@mongodb-js/saslprep": {
......@@ -34,6 +497,11 @@
"@types/webidl-conversions": "*"
}
},
"node_modules/abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
},
"node_modules/accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
......@@ -46,11 +514,93 @@
"node": ">= 0.6"
}
},
"node_modules/agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
"dependencies": {
"debug": "4"
},
"engines": {
"node": ">= 6.0.0"
}
},
"node_modules/agent-base/node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/agent-base/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"engines": {
"node": ">=8"
}
},
"node_modules/aproba": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
"integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ=="
},
"node_modules/are-we-there-yet": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
"integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
"dependencies": {
"delegates": "^1.0.0",
"readable-stream": "^3.6.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
},
"node_modules/async": {
"version": "3.2.5",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
"integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg=="
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/axios": {
"version": "1.6.7",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz",
"integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==",
"dependencies": {
"follow-redirects": "^1.15.4",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"node_modules/body-parser": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
......@@ -74,6 +624,15 @@
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/bson": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/bson/-/bson-6.4.0.tgz",
......@@ -108,6 +667,94 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/canvas": {
"version": "2.11.2",
"resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz",
"integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==",
"hasInstallScript": true,
"dependencies": {
"@mapbox/node-pre-gyp": "^1.0.0",
"nan": "^2.17.0",
"simple-get": "^3.0.3"
},
"engines": {
"node": ">=6"
}
},
"node_modules/chownr": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
"engines": {
"node": ">=10"
}
},
"node_modules/color": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
"dependencies": {
"color-convert": "^2.0.1",
"color-string": "^1.9.0"
},
"engines": {
"node": ">=12.5.0"
}
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/color-string": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
"dependencies": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
},
"node_modules/color-support": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
"bin": {
"color-support": "bin.js"
}
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"node_modules/console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="
},
"node_modules/content-disposition": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
......@@ -148,6 +795,17 @@
"ms": "2.0.0"
}
},
"node_modules/decompress-response": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
"integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
"dependencies": {
"mimic-response": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/define-data-property": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
......@@ -164,6 +822,19 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
......@@ -181,11 +852,24 @@
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/detect-libc": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz",
"integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==",
"engines": {
"node": ">=8"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
},
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
......@@ -284,6 +968,50 @@
"node": ">= 0.8"
}
},
"node_modules/fluent-ffmpeg": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz",
"integrity": "sha512-IZTB4kq5GK0DPp7sGQ0q/BWurGHffRtQQwVkiqDgeO6wYJLLV5ZhgNOQ65loZxxuPMKZKZcICCUnaGtlxBiR0Q==",
"dependencies": {
"async": ">=0.2.9",
"which": "^1.1.1"
},
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/follow-redirects": {
"version": "1.15.5",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz",
"integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
......@@ -300,6 +1028,33 @@
"node": ">= 0.6"
}
},
"node_modules/fs-minipass": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
"dependencies": {
"minipass": "^3.0.0"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/fs-minipass/node_modules/minipass": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
......@@ -308,6 +1063,25 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/gauge": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
"integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
"dependencies": {
"aproba": "^1.0.3 || ^2.0.0",
"color-support": "^1.1.2",
"console-control-strings": "^1.0.0",
"has-unicode": "^2.0.1",
"object-assign": "^4.1.1",
"signal-exit": "^3.0.0",
"string-width": "^4.2.3",
"strip-ansi": "^6.0.1",
"wide-align": "^1.1.2"
},
"engines": {
"node": ">=10"
}
},
"node_modules/get-intrinsic": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
......@@ -326,6 +1100,25 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
......@@ -370,6 +1163,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ=="
},
"node_modules/hasown": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz",
......@@ -396,6 +1194,39 @@
"node": ">= 0.8"
}
},
"node_modules/https-proxy-agent": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
"dependencies": {
"agent-base": "6",
"debug": "4"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/https-proxy-agent/node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/https-proxy-agent/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
......@@ -407,6 +1238,15 @@
"node": ">=0.10.0"
}
},
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
......@@ -420,6 +1260,24 @@
"node": ">= 0.10"
}
},
"node_modules/is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
},
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"engines": {
"node": ">=8"
}
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
"node_modules/kareem": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz",
......@@ -428,6 +1286,39 @@
"node": ">=12.0.0"
}
},
"node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
"dependencies": {
"semver": "^6.0.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/make-dir/node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
......@@ -484,6 +1375,70 @@
"node": ">= 0.6"
}
},
"node_modules/mimic-response": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
"integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"node_modules/minipass": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
"integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
"engines": {
"node": ">=8"
}
},
"node_modules/minizlib": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
"dependencies": {
"minipass": "^3.0.0",
"yallist": "^4.0.0"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/minizlib/node_modules/minipass": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/mkdirp": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
"bin": {
"mkdirp": "bin/cmd.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/mongodb": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.3.0.tgz",
......@@ -609,6 +1564,11 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/nan": {
"version": "2.18.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz",
"integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w=="
},
"node_modules/negotiator": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
......@@ -617,6 +1577,77 @@
"node": ">= 0.6"
}
},
"node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/node-fetch/node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"node_modules/node-fetch/node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"node_modules/node-fetch/node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/nopt": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
"integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
"dependencies": {
"abbrev": "1"
},
"bin": {
"nopt": "bin/nopt.js"
},
"engines": {
"node": ">=6"
}
},
"node_modules/npmlog": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
"integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
"dependencies": {
"are-we-there-yet": "^2.0.0",
"console-control-strings": "^1.1.0",
"gauge": "^3.0.0",
"set-blocking": "^2.0.0"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object-inspect": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
......@@ -636,6 +1667,14 @@
"node": ">= 0.8"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
......@@ -644,6 +1683,14 @@
"node": ">= 0.8"
}
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
......@@ -661,6 +1708,11 @@
"node": ">= 0.10"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
......@@ -705,6 +1757,33 @@
"node": ">= 0.8"
}
},
"node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
......@@ -729,6 +1808,20 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/semver": {
"version": "7.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/send": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
......@@ -771,6 +1864,11 @@
"node": ">= 0.8.0"
}
},
"node_modules/set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
},
"node_modules/set-function-length": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz",
......@@ -792,6 +1890,45 @@
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
},
"node_modules/sharp": {
"version": "0.33.2",
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.2.tgz",
"integrity": "sha512-WlYOPyyPDiiM07j/UO+E720ju6gtNtHjEGg5vovUk1Lgxyjm2LFO+37Nt/UI3MMh2l6hxTWQWi7qk3cXJTutcQ==",
"hasInstallScript": true,
"dependencies": {
"color": "^4.2.3",
"detect-libc": "^2.0.2",
"semver": "^7.5.4"
},
"engines": {
"libvips": ">=8.15.1",
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
"@img/sharp-darwin-arm64": "0.33.2",
"@img/sharp-darwin-x64": "0.33.2",
"@img/sharp-libvips-darwin-arm64": "1.0.1",
"@img/sharp-libvips-darwin-x64": "1.0.1",
"@img/sharp-libvips-linux-arm": "1.0.1",
"@img/sharp-libvips-linux-arm64": "1.0.1",
"@img/sharp-libvips-linux-s390x": "1.0.1",
"@img/sharp-libvips-linux-x64": "1.0.1",
"@img/sharp-libvips-linuxmusl-arm64": "1.0.1",
"@img/sharp-libvips-linuxmusl-x64": "1.0.1",
"@img/sharp-linux-arm": "0.33.2",
"@img/sharp-linux-arm64": "0.33.2",
"@img/sharp-linux-s390x": "0.33.2",
"@img/sharp-linux-x64": "0.33.2",
"@img/sharp-linuxmusl-arm64": "0.33.2",
"@img/sharp-linuxmusl-x64": "0.33.2",
"@img/sharp-wasm32": "0.33.2",
"@img/sharp-win32-ia32": "0.33.2",
"@img/sharp-win32-x64": "0.33.2"
}
},
"node_modules/side-channel": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
......@@ -814,6 +1951,48 @@
"resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz",
"integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ=="
},
"node_modules/signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
},
"node_modules/simple-concat": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/simple-get": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz",
"integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
"dependencies": {
"decompress-response": "^4.2.0",
"once": "^1.3.1",
"simple-concat": "^1.0.0"
}
},
"node_modules/simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
"dependencies": {
"is-arrayish": "^0.3.1"
}
},
"node_modules/sparse-bitfield": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
......@@ -830,6 +2009,54 @@
"node": ">= 0.8"
}
},
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"dependencies": {
"safe-buffer": "~5.2.0"
}
},
"node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/tar": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz",
"integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==",
"dependencies": {
"chownr": "^2.0.0",
"fs-minipass": "^2.0.0",
"minipass": "^5.0.0",
"minizlib": "^2.1.1",
"mkdirp": "^1.0.3",
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
......@@ -849,6 +2076,12 @@
"node": ">=14"
}
},
"node_modules/tslib": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
"optional": true
},
"node_modules/type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
......@@ -869,6 +2102,11 @@
"node": ">= 0.8"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
......@@ -904,6 +2142,35 @@
"engines": {
"node": ">=16"
}
},
"node_modules/which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"dependencies": {
"isexe": "^2.0.0"
},
"bin": {
"which": "bin/which"
}
},
"node_modules/wide-align": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
"integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
"dependencies": {
"string-width": "^1.0.2 || 2 || 3 || 4"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
}
}
}
......@@ -10,7 +10,11 @@
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^1.6.7",
"canvas": "^2.11.2",
"express": "^4.18.3",
"mongoose": "^8.2.0"
"fluent-ffmpeg": "^2.1.2",
"mongoose": "^8.2.0",
"sharp": "^0.33.2"
}
}
const path = require('path');
const tutorShotController = require("../controller/tutor-shot")
const { createDirectory } = require("../helper/utilities")
const router = new require('express').Router()
router.post("/generate", tutorShotController.generateVideo)
createDirectory( path.join(__dirname, '..', 'temporary', 'image') )
createDirectory( path.join(__dirname, '..', 'temporary', 'video') )
createDirectory( path.join(__dirname, '..', 'temporary', 'audio') )
module.exports = router
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment