macos-defaults/record/utils.js

194 lines
4.7 KiB
JavaScript
Raw Normal View History

const fs = require('fs')
const mkdirp = require('mkdirp')
const pngquant = require('node-pngquant-native')
const sharp = require('sharp')
const Jimp = require('jimp')
const robot = require('robotjs')
const { spawn } = require('child_process')
module.exports.captureImage = (x, y, w, h) => {
// Taken from https://github.com/octalmage/robotjs/issues/13#issuecomment-501102240
const pic = robot.screen.capture(x, y, w, h)
const width = pic.byteWidth / pic.bytesPerPixel // pic.width is sometimes wrong!
const height = pic.height
const image = new Jimp(width, height)
let red, green, blue
pic.image.forEach((byte, i) => {
switch (i % 4) {
2020-11-27 12:45:16 +00:00
case 0:
return (blue = byte)
case 1:
return (green = byte)
case 2:
return (red = byte)
case 3:
image.bitmap.data[i - 3] = red
image.bitmap.data[i - 2] = green
image.bitmap.data[i - 1] = blue
image.bitmap.data[i] = 255
}
})
return image
}
2020-11-27 12:45:16 +00:00
module.exports.compressPngImage = async (
inputPath,
outputFolder,
outputName,
2020-11-27 12:45:16 +00:00
) => {
const tmpOutput = `${outputFolder}/${outputName}-tmp.png`
const finalOutput = `${outputFolder}/${outputName}.png`
await mkdirp(outputFolder)
fs.renameSync(inputPath, tmpOutput)
return new Promise((resolve, reject) => {
console.info(' Compressing PNG image')
sharp(tmpOutput)
2020-11-27 12:45:16 +00:00
.resize(740, undefined, {
fit: sharp.fit.inside,
withoutEnlargement: true,
})
.toFormat('png')
.toBuffer()
2020-11-27 12:45:16 +00:00
.then((resizedBuffer) => {
const responseBuffer = pngquant.compress(resizedBuffer)
2020-11-27 12:45:16 +00:00
fs.writeFile(finalOutput, responseBuffer, (writeFileError) => {
removeSync(tmpOutput)
if (writeFileError) {
console.error('An error occured while saving the image')
reject(writeFileError)
}
resolve()
})
})
})
}
module.exports.compressVideo = async (inputPath, outputFolder, outputName) => {
const tmpOutput = `${outputFolder}/${outputName}-tmp.mp4`
const finalOutput = `${outputFolder}/${outputName}.mp4`
await mkdirp(outputFolder)
fs.renameSync(inputPath, tmpOutput)
try {
await resizeVideo(tmpOutput, finalOutput)
} catch (resizeVideoError) {
console.error('An error occured while resizing the video')
throw new Error(resizeVideoError)
} finally {
removeSync(tmpOutput)
}
}
function resizeVideo(input, output) {
console.info(' Resizing video')
return new Promise((resolve, reject) => {
const ffmpegRawLogs = []
2020-11-27 12:45:16 +00:00
const ffmpeg = spawn('ffmpeg', [
'-i',
input,
'-vf',
"scale='min(740,iw)':-2",
'-c:v',
'libx264',
'-crf',
'18',
'-preset',
'veryslow',
'-y',
'-c:a',
'copy',
output,
])
ffmpeg.stderr.on('data', (message) =>
ffmpegRawLogs.push(message.toString('utf8')),
)
2020-11-27 12:45:16 +00:00
ffmpeg.on('exit', (ffmpegExitCode) => {
if (process.env.NODE_ENV === 'DEBUG') {
console.debug(ffmpegRawLogs.join('\n'))
}
if (ffmpegExitCode !== 0) {
return reject(ffmpegRawLogs.join('\n'))
}
resolve()
})
})
}
function removeSync(file) {
if (fs.existsSync(file)) {
fs.unlinkSync(file)
}
}
module.exports.makeAppActive = async (appName) => {
return new Promise((resolve, reject) => {
2020-11-27 12:45:16 +00:00
const osascript = spawn('osascript', [
'-e',
'try',
'-e',
`tell application "${appName}" to activate`,
'-e',
'end try',
])
if (process.env.NODE_ENV === 'DEBUG') {
osascript.stderr.on('data', function (message) {
console.debug(`${message}`)
})
}
2020-11-27 12:45:16 +00:00
osascript.on('exit', (osascriptExitCode) => {
if (osascriptExitCode === '1') {
return reject('osascript')
}
resolve()
})
})
}
module.exports.moveAndResizeApp = async (appName, cropArea, screenHeight) => {
const x = { start: cropArea.x, end: cropArea.x + cropArea.width }
2020-11-27 12:45:16 +00:00
const y = {
start: screenHeight - cropArea.y - cropArea.height,
end: screenHeight - cropArea.y,
}
return new Promise((resolve, reject) => {
2020-11-27 12:45:16 +00:00
const osascript = spawn('osascript', [
'-e',
'try',
'-e',
`tell application "${appName}"`,
'-e',
`set the bounds of the first window to {${x.start}, ${y.start}, ${x.end}, ${y.end}}`,
'-e',
'end tell',
'-e',
'end try',
])
if (process.env.NODE_ENV === 'DEBUG') {
osascript.stderr.on('data', function (message) {
console.debug(`${message}`)
})
}
2020-11-27 12:45:16 +00:00
osascript.on('exit', (osascriptExitCode) => {
if (osascriptExitCode === '1') {
return reject('osascript')
}
resolve()
})
})
}