Created
October 11, 2021 11:34
-
-
Save vorg/f0c16bd4cc7292476311aad48687a039 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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