Skip to content

Instantly share code, notes, and snippets.

@vorg
Created October 11, 2021 11:34
Show Gist options
  • Save vorg/f0c16bd4cc7292476311aad48687a039 to your computer and use it in GitHub Desktop.
Save vorg/f0c16bd4cc7292476311aad48687a039 to your computer and use it in GitHub Desktop.
module.exports = function (node, graph) {
const canvasScreenshot = require('canvas-screenshot').default
const triggerIn = node.triggerIn('in')
const triggerOut = node.triggerOut('out')
const fpsIn = node.in('fps', 30, { precision: 0, connectable: false })
const durationIn = node.in('duration (s)', 10)
const onStartRecordingOut = node.triggerOut('onStartRecording')
let recording = false
let recordingStartDate = null
let time = 0 //TODO: time vs totalTime?
let frame = 0
let totalFrames = 0
let prevResolution
const { ctx } = graph
const resolutionIn = node.in('resolution', '', {
type: 'dropdown', values: [], connectable: false
})
const startStopRecordingBtn = node.in('start / stop recording', () => {
if (!recording) {
startRecording()
onStartRecordingOut.trigger()
}
else stopRecording()
})
const takeScreenshotBtn = node.in('take screenshot', () => {
if (!recording) takeScreenshot()
})
function startRecording () {
const fps = fpsIn.value
const duration = durationIn.value
time = 0
frame = 0
totalFrames = duration * fps
recording = true
recordingStartDate = new Date()
}
function takeScreenshot () {
recording = true
recordingStartDate = new Date()
totalFrames = 1
}
function stopRecording () {
recording = false
}
function getScreenshotName(date) {
const fileName = `${graph.name} ${date.toISOString().slice(0, 10)} at ${date
.toTimeString()
.slice(0, 8)
.replace(/:/g, ".")}.png`
return fileName
}
function getFrameName(frame) {
return ('00000' + frame).substr(-5) + '.jpg'
}
function getFolderName(date) {
const YYYYMMDD = date.toISOString().slice(0, 10).replace(/-/g, '')
const mmhhss = date.toTimeString().slice(0, 8).replace(/:/g, '')
const folderName = `frames/${graph.name}-${YYYYMMDD}-${mmhhss}`
return folderName
}
function uploadFile (blob, fileName, folderName) {
var formData = new window.FormData()
formData.append('filepath', folderName)
formData.append('file', blob, fileName)
var postReq = new window.XMLHttpRequest()
postReq.open('POST', 'asset')
postReq.send(formData)
}
let isSaving = false
let framesSkipped = 0
function pad2(n) {
return ('00' + n).substr(-2)
}
function formatSeconds(seconds) {
var minutes = Math.floor(seconds / 60)
var remainingSeconds = Math.floor(seconds - minutes * 60)
return `${pad2(minutes)}:${pad2(remainingSeconds)}`
}
triggerIn.onTrigger = async (props) => {
if (isSaving) {
framesSkipped++
return
}
if (resolutionIn.options.values !== props.contextResolutions) {
resolutionIn.options.values = props.contextResolutions || []
}
if (recording) {
isSaving = true
const fps = fpsIn.value
const duration = durationIn.value
const deltaTime = 1 / fps
time += deltaTime
triggerOut.trigger({
...props,
time,
deltaTime,
recording
})
if (totalFrames == 1) {
canvasScreenshot(props.canvas, {
useBlob: true,
filename: getScreenshotName(recordingStartDate)
})
} else {
const fileName = getFrameName(frame)
const blob = await canvasScreenshot(props.canvas, {
useBlob: true,
download: false,
filename: fileName
})
uploadFile(blob, fileName, getFolderName(recordingStartDate))
}
if (++frame >= totalFrames) {
stopRecording()
}
if (recording) { // still recording after await resolved
var renderTime = ((Date.now() - recordingStartDate.getTime())/1000)
var secondsPerFrame = renderTime / frame
var totalTimeEst = secondsPerFrame * totalFrames
var remainingTime = totalTimeEst - renderTime
var renderTimeStr = formatSeconds(renderTime)
var remainingTimeStr = formatSeconds(remainingTime)
node.comment = `Recording:
Speedup: x ${(time/renderTime).toFixed(1)}
Remaining Time: ${remainingTimeStr}
Elapsed Time: ${renderTimeStr}
Time: ${time.toFixed(1)} / ${duration}
Frame: ${frame} / ${totalFrames}
Skipped Frames: ${framesSkipped}`
}
isSaving = false
} else {
triggerOut.trigger(props)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment