tungs / timecut Goto Github PK
View Code? Open in Web Editor NEWNode.js program to record smooth movies of web pages with JavaScript animations
License: BSD 3-Clause "New" or "Revised" License
Node.js program to record smooth movies of web pages with JavaScript animations
License: BSD 3-Clause "New" or "Revised" License
Hi there!
I'm trying to capture a mapbox visualization but am having difficulties getting timecut to capture screenshots that are on par with the screenshots I can capture just using my browser.
timecut "http://localhost:3001/" --viewport=1600,900 --fps=60 --duration=153 --frame-cache --pix-fmt=yuv420p --output=video7.mp4
Any help would be appreciated!
@tungs Thanks a lot for developing this tool. We are planning to use it in our project but we have some specific requirements.
I was wondering if you can offer paid support/feature development.
Sorry for filing issue for this but I could not another way to contact you.
Puppeeter may be the problem, and how to fix it, Thank you very much
What's the best config I can follow to make the capture speed fast!
The whole library is awesome but Current capture speed is very slow, it's taking almost 2 minutes to capture a 7-second video, with 30fps.
Thanks in advance
This library is using timesnap for capturing image, is there any way to capture image as jpg format from timecut and render the video from that jpg images?
Thanks in advance
Can you speedup the capture process by using multi pupeeter tabs ?
I'm Vietnamese, Love your name !
Hi @tungs, thanks for the timecut repo. I checked the time-snap index.js. you wrote all the functions are on promise type. On that the page.evaluateHandle puppeter method is not present. Kindly let me know how to include or implement the evaluatehandle method in timecut.
cc: @varunarora
Describe the bug
From a Node.js script with puppeteer and timecut libraries i'm trying to screen record as a video specific html element content based on CSS selector from a web page headless mode. Page is hosted on server or loaded locally from filesystem from the same folder as the script.
Still, i'm unable to do that, because i receive different errors:
selector: '[data-lpid="posterContainer"]'
error is: Error: Evaluation failed: TypeError: Cannot read properties of null (reading 'getBoundingClientRect')
selector: '#some-existing-id '
i get this error: Error: Evaluation failed: DOMException: Failed to execute 'querySelector' on 'Document': '#some-existing-id is not a valid selector.
div
and video
element inside, i receive Error: Execution context was destroyed, most likely because of a navigation
index.html
or with full path file:///C:/zFVStuff/cms/poc-cms-video-poster-render-download/basic-puppeteer/test-local-lpac-files/index.html
but i'm receiving: TimeoutError: Navigation timeout of 30000 ms exceeded at C:\zFVStuff\DentsuSRC\liveposter\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\LifecycleWatcher.js:142:21
To Reproduce
Please List:
From Windows 10 (or Ubuntu), through Node.js script (the official basic example script) fails when trying use selector like the ones from above.
Expected behavior
A video recorded only with that element content i expected to see.
Attachments and Screenshots
If applicable to a local, publicly unavailable web site, upload a minimal reproducible example. Also if applicable, add screenshots to help explain your problem.
Desktop (please complete the following information):
Additional context
Add any other context about the problem here.
My code:
const timecut = require('timecut');
timecut({
// url: 'https://tungs.github.io/amuse/truchet-tiles/#autoplay=true&switchStyle=random',
// // url: 'http://127.0.0.1:5500/puppeteer-timecut-element-screen-recorder.html',
// https://www.pexels.com/video/drone-footage-of-a-surfer-barrelling-a-wave-12715991,
// url: 'https://www.youtube.com/watch?v=t8ljgrq0YEk',
url: 'http://localhost:3000',
viewport: {
width: 1920, // sets the viewport (window size) to 800x600
height: 1080
},
// selector: '#container', // crops each frame to the bounding box of '#container'
selector: '[data-lpid="posterContainer"]', // crops each frame to the bounding box of '#container'
// selector: '#some-existing-id',
// selector: '#player-theater-container', // for youtube.com
// selector: '#player', // for pexels.com
left: 20, top: 40, // further crops the left by 20px, and the top by 40px
right: 6, bottom: 30, // and the right by 6px, and the bottom by 30px
fps: 30, // saves 30 frames for each virtual second
// duration: 20, // for 20 virtual seconds
duration: 10, // for 20 virtual seconds
output: 'video-timecut.mp4', // to video.mp4 of the current working directory
// headless: false,
executablePath: 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe',
}).then(function () {
console.log('Done!');
});
Example of html code that i want to record:
// html... head... body... (removed for brevity)...
<div id="some-existing-id" data-lpid="posterContainer">
<video crossorigin="" src="/some-video.mp4" preload="auto" autoplay="" muted
style="width: 100%; height: 100%;"></video>
<div class="css-animated-text">
some CSS animated text
</div>
</div>
// ... removed for brevity
Detailed errors:
Page loaded
Capturing Frame 1 to C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\timecut-temp-1661987464345\image-000000001.png...
Capturing Frame 2 to C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\timecut-temp-1661987464345\image-000000002.png...
Capturing Frame 3 to C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\timecut-temp-1661987464345\image-000000003.png...
Capturing Frame 4 to C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\timecut-temp-1661987464345\image-000000004.png...
Error: Execution context was destroyed, most likely because of a navigation.
at rewriteError (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\ExecutionContext.js:167:15)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async ExecutionContext._evaluateInternal (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\ExecutionContext.js:120:56)
at async ExecutionContext.evaluate (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\ExecutionContext.js:48:12)
at async runInAllFrames (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\lib\utils.js:49:7)
at async run (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\index.js:253:9)
at async module.exports (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\index.js:287:5)
at async module.exports (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timecut\index.js:210:7)
Page loaded
Error: Evaluation failed: TypeError: Cannot read properties of null (reading 'getBoundingClientRect')
at __puppeteer_evaluation_script__:3:18
at ExecutionContext._evaluateInternal (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\ExecutionContext.js:122:13)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async ExecutionContext.evaluate (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\ExecutionContext.js:48:12)
at async Object.beforeCapture (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\lib\capture-screenshot.js:45:22)
at async run (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\index.js:277:9)
at async module.exports (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\index.js:287:5)
at async module.exports (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timecut\index.js:210:7)
-- ASYNC --
at ExecutionContext.<anonymous> (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\helper.js:111:15)
at DOMWorld.evaluate (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\DOMWorld.js:112:20)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
-- ASYNC --
at Frame.<anonymous> (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\helper.js:111:15)
at Page.evaluate (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\Page.js:860:43)
at Page.<anonymous> (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\helper.js:112:23)
at getSelectorDimensions (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\lib\utils.js:87:15)
at Object.beforeCapture (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\lib\capture-screenshot.js:45:28)
at Object.fn (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\index.js:199:29)
at run (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\index.js:277:27)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async module.exports (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\index.js:287:5)
at async module.exports (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timecut\index.js:210:7)
Error: Evaluation failed: TypeError: Cannot read properties of null (reading 'getBoundingClientRect')
at __puppeteer_evaluation_script__:3:18
at ExecutionContext._evaluateInternal (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\ExecutionContext.js:122:13)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async ExecutionContext.evaluate (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\ExecutionContext.js:48:12)
at async Object.beforeCapture (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\lib\capture-screenshot.js:45:22)
at async run (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\index.js:277:9)
at async module.exports (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\index.js:287:5)
at async module.exports (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timecut\index.js:210:7)
-- ASYNC --
imesnap\node_modules\puppeteer\lib\helper.js:111:15)
e_modules\puppeteer\lib\DOMWorld.js:112:20)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
-- ASYNC --
at Frame.<anonymous> (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\helper.js:111:15)
at Page.evaluate (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\Page.js:860:43)
at Page.<anonymous> (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\helper.js:112:23)
at getSelectorDimensions (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\lib\utils.js:87:15)
at Object.beforeCapture (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\lib\capture-screenshot.js:45:28)
at Object.fn (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\index.js:199:29)
at run (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\index.js:277:27)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async module.exports (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\index.js:287:5)
at async module.exports (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timecut\index.js:210:7)
node:fs:1390
handleErrorFromBinding(ctx);
^
Error: ENOENT: no such file or directory, scandir 'C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\timecut-temp-1661963724406'
at Object.readdirSync (node:fs:1390:3)
at deleteFolder (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timecut\index.js:54:6)
at module.exports (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timecut\index.js:244:5)
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
errno: -4058,
syscall: 'scandir',
code: 'ENOENT',
path: 'C:\\zFVStuff\\DentsuSRC\\liveposter\\cms\\poc-cms-video-poster-render-download\\basic-puppeteer\\timecut-temp-1661963724406'
}
DevTools listening on ws://127.0.0.1:58924/devtools/browser/026aedc3-de58-47d6-b2f7-283c6c427d05
Capture Mode: Screenshot
Going to file://C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\test-local-lpac-files\index.html...
[0901/193102.224:INFO:CONSOLE(45)] "[object Object] [object Object]", source: file:///C:/zFVStuff/DentsuSRC/liveposter/cms/poc-cms-video-poster-render-download/basic-puppeteer/test-local-lpac-files/bundle.js (45)
TimeoutError: Navigation timeout of 30000 ms exceeded
at C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\LifecycleWatcher.js:142:21
-- ASYNC --
at Frame.<anonymous> (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\helper.js:111:15)
at Page.goto (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\Page.js:672:49)
at Page.<anonymous> (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\helper.js:112:23)
at run (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\index.js:175:18)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async module.exports (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\index.js:287:5)
at async module.exports (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timecut\index.js:210:7)
TimeoutError: Navigation timeout of 30000 ms exceeded
at C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\LifecycleWatcher.js:142:21
-- ASYNC --
at Frame.<anonymous> (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\helper.js:111:15)
at Page.goto (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\Page.js:672:49)
at Page.<anonymous> (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\node_modules\puppeteer\lib\helper.js:112:23)
at run (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\index.js:175:18)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async module.exports (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timesnap\index.js:287:5)
at async module.exports (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timecut\index.js:210:7)
node:fs:1390
handleErrorFromBinding(ctx);
^
0107'
at deleteFolder (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timecut\index.js:54:6)
at module.exports (C:\zFVStuff\cms\poc-cms-video-poster-render-download\basic-puppeteer\node_modules\timecut\index.js:244:5) {
errno: -4058,
syscall: 'scandir',
code: 'ENOENT',
path: 'C:\\zFVStuff\\cms\\poc-cms-video-poster-render-download\\basic-puppeteer\\test-local-lpac-files\\recorded-videos\\timecut-temp-1662049860107'
}
Great job with the library!!!
Thank you very much in advance for any help!
Hey there!
I have tried to run the timecut package on AWS Lambda but unfortunately if timecut is installed via npm all dependencies combined result in a deploy package over 300MB, AWS Lambda currently allows only unzipped deploy packages below 250MB. The biggest issue is the Chrome package that is installed by default.
Is there kind of a workaround to maybe cut off some dependencies that are not needed for the core functionalities of timecut? Or has anyone experiences with using timecut on AWS Lambda and has managed to use a package like https://github.com/alixaxel/chrome-aws-lambda ?
Hope that someone has a smart solution for this.
Best Andreas
Describe the bug
A clear and concise description of what the bug is.
I faced this when running ./node_modules/.bin/timecut
[1219/095903.380227:WARNING:gpu_process_host.cc(1165)] The GPU process has crashed 1 time(s)
[1219/095903.415464:WARNING:gpu_process_host.cc(1165)] The GPU process has crashed 2 time(s)
[1219/095903.446328:WARNING:gpu_process_host.cc(1165)] The GPU process has crashed 3 time(s)
[1219/095903.477149:WARNING:gpu_process_host.cc(1165)] The GPU process has crashed 4 time(s)
[1219/095903.511928:WARNING:gpu_process_host.cc(1165)] The GPU process has crashed 5 time(s)
[1219/095903.542351:WARNING:gpu_process_host.cc(1165)] The GPU process has crashed 6 time(s)
[1219/095903.565672:WARNING:gpu_process_host.cc(1165)] The GPU process has crashed 7 time(s)
[1219/095903.596905:WARNING:gpu_process_host.cc(1165)] The GPU process has crashed 8 time(s)
[1219/095903.627619:WARNING:gpu_process_host.cc(1165)] The GPU process has crashed 9 time(s)
[1219/095903.627729:FATAL:gpu_data_manager_impl_private.cc(1034)] The display compositor is frequently crashing. Goodbye.
...
To Reproduce
Please List:
I ran this for installation with 1 warning
$ npm i timecut
npm WARN deprecated [email protected]: < 18.1.0 is no longer supported
Expected behavior
Was not expecting a GPU crash
Attachments and Screenshots
See logs
Desktop (please complete the following information):
Additional context
No
I am using a pretty standard and popular animation library called anime.js
. The animations don't seem to render. Am I doing something fundamentally wrong? Or is the library non-standard?
An error pops up when I try and create a new video with the ff config:
const uuid = v4();
const tempFolderName = "./videos/" + uuid;
await fs.mkdirSync(tempFolderName);
const output = "./videos/" + uuid + ".mp4";
garbageCollector.addFile(output);
garbageCollector.addFolder(tempFolderName);
const data = stack.videoData;
timecut({
url: data.url,
viewport: data.viewport,
fps: data.fps, // saves 30 frames for each virtual second
duration: data.duration, // for 20 virtual seconds
frameCache: uuid,
quiet: true,
output,
frameProcessor: (buffer, currentFrame, totalFrames) => {
const progress = currentFrame / totalFrames;
parentPort.postMessage({
key: "progress",
progress,
});
},
// of the current working directory
})
err: Error: ENOENT: no such file or directory, scandir '/var/www/encoder/videos/70a9555f-e407-46a8-b7bd-980fd0011422/timecut-temp-1607066744976'
at Object.readdirSync (fs.js:955:3)
at deleteFolder (/var/www/encoder/node_modules/timecut/index.js:51:6)
at /var/www/encoder/node_modules/timecut/index.js:194:9
at processTicksAndRejections (internal/process/task_queues.js:97:5)
as you can see its trying to create a video inside of timecut-temp-1607**** which i think is wrong because this is the actual name of the file itself? the folder should just be 70a***
I am recording an animation rendered on the canvas using Timecut. The screenshots (frames or temporary images) of the canvas show a white background but when the animation is combined to form the video, the backgorund turns black. How can I keep the background white in the video as well.
Here is the command that I run from the terminal:
timecut "path/to/file.html" --viewport=1920,1080 --duration=30 --canvas-capture-mode=true --output=bounce.mp4
Thanks.
Elapsed capture time: 75683
Error: spawn ffmpeg ENOENT
at Process.ChildProcess._handle.onexit (internal/child_process.js:269:19)
at onErrorNT (internal/child_process.js:467:16)
at processTicksAndRejections (internal/process/task_queues.js:82:21) {
errno: -2,
code: 'ENOENT',
syscall: 'spawn ffmpeg',
path: 'ffmpeg',
spawnargs: [
'-framerate',
60,
'-i',
'/Users/gurugeek/Downloads/fishdraw-main/timecut-temp-1654480292749/image-%09d.png',
'-pix_fmt',
'yuv420p',
'-y',
'/Users/gurugeek/Downloads/fishdraw-main/video.mp4'
]
}
(node:57394) UnhandledPromiseRejectionWarning: Error: spawn ffmpeg ENOENT
at Process.ChildProcess._handle.onexit (internal/child_process.js:269:19)
at onErrorNT (internal/child_process.js:467:16)
at processTicksAndRejections (internal/process/task_queues.js:82:21)
(Use node --trace-warnings ...
to show where the warning was created)
(node:57394) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict
(see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:57394) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
gurugeek@davids-imac fishdraw-main %
Great work. Thank you for sharing
Any guidance on how to export to gif instead of video?
Timecut version 0.1.2
npm i timecut
node node_modules/timecut/cli.js https://google.com
Error: spawn ffmpeg ENOENT
at Process.ChildProcess._handle.onexit (internal/child_process.js:264:19)
at onErrorNT (internal/child_process.js:456:16)
at processTicksAndRejections (internal/process/task_queues.js:80:21) {
errno: 'ENOENT',
code: 'ENOENT',
syscall: 'spawn ffmpeg',
path: 'ffmpeg',
spawnargs: [
'-framerate',
30,
'-i',
'/Users/x/image-%09d.png',
'-pix_fmt',
'yuv420p',
'-y',
'/Users/x/video.mp4'
]
}
Do you know what this error means?
when I run this command:
timecut https://bl.ocks.org/micahstubbs/3f439df92579c5bb2902fab15742ba87 --selector "iframe" --left 1 --right 1 --top 1 --bottom 1 --duration=120 --output=/path/to/output/video.mp4
I see this error in the terminal:
[0922/163349.098134:ERROR:gpu_process_transport_factory.cc(1043)] Lost UI shared context.
DevTools listening on ws://127.0.0.1:61493/devtools/browser/1c5d40b3-3f48-4d35-b490-4977aa179363
Going to https://bl.ocks.org/micahstubbs/3f439df92579c5bb2902fab15742ba87...
[0922/163350.219793:INFO:CONSOLE(4)] "graph", source: https://bl.ocks.org/micahstubbs/raw/3f439df92579c5bb2902fab15742ba87/6d432e10e85c9d21497ac7d44ddc85a1bcda64f1/vis.js (4)
[0922/163350.225464:INFO:CONSOLE(49)] "clusters", source: https://bl.ocks.org/micahstubbs/raw/3f439df92579c5bb2902fab15742ba87/6d432e10e85c9d21497ac7d44ddc85a1bcda64f1/vis.js (49)
Page loaded
{ Error: EACCES: permission denied, mkdir '/path'
at Object.fs.mkdirSync (fs.js:902:18)
at makeFileDirectoryIfNeeded (/Users/m/.config/yarn/global/node_modules/timesnap/index.js:211:10)
at /Users/m/.config/yarn/global/node_modules/timesnap/index.js:374:15
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:182:7) errno: -13, code: 'EACCES', syscall: 'mkdir', path: '/path' }
{ Error: EACCES: permission denied, mkdir '/path'
at Object.fs.mkdirSync (fs.js:902:18)
at makeFileDirectoryIfNeeded (/Users/m/.config/yarn/global/node_modules/timecut/index.js:45:10)
at makeProcessPromise (/Users/m/.config/yarn/global/node_modules/timecut/index.js:116:5)
at /Users/m/.config/yarn/global/node_modules/timecut/index.js:176:16
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:182:7) errno: -13, code: 'EACCES', syscall: 'mkdir', path: '/path' }
Hi,
We are trying to use timecut to animate one of the application page which uses native setTimeout functions to show a few elements on page. While using this application page with timecut, we noticed that the features (using setTimeout) are behaving incorrectly. after digging down a bit, we noticed that timecut overrides the native function which is causing this issue. Any suggestions on how to use timecut for this kind of application?
[1028/180242.409718:FATAL:zygote_host_impl_linux.cc(116)] No usable sandbox! Update your kernel or see https://chromium.googlesource.com/chromium/src/+/master/docs/linux_suid_sandbox_development.md for more information on developing with the SUID sandbox. If you want to live dangeround, you can try using --no-sandbox.
#0 0x55ab105a8219 base::debug::CollectStackTrace()
#1 0x55ab1050c363 base::debug::StackTrace::StackTrace()
#2 0x55ab1051e195 logging::LogMessage::~LogMessage()
#3 0x55ab11d9a00e service_manager::ZygoteHostImpl::Init()
#4 0x55ab10115f27 content::ContentMainRunnerImpl::Initialize()
#5 0x55ab10164afa service_manager::Main()
#6 0x55ab10114501 content::ContentMain()
#7 0x55ab101638f5 headless::(anonymous namespace)::RunContentMain()
#8 0x55ab1016359d headless::HeadlessShellMain()
#9 0x55ab0dcd8aa7 ChromeMain
#10 0x7fb910e63495 __libc_start_main
#11 0x55ab0dcd88ea _start
@tungs thank you for sharing this awesome project.
Following is the HTML file that I'm trying to record with headless Google-Chrome & timecut.
<!-- <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> -->
<html>
<body>
<div id="theater">
<video
id="video"
src="file:///home/bob/BigBuckBunny2.mp4"
type="video/mp4"
autoplay muted width=400 height=300>
</video>
<div>
<canvas id="my-canvas" width=400 height=300 style="border: 10px solid red;"></canvas>
</div>
<label>
<br />Try to play me :)</label>
<br />
</div>
<script>
function fn() {
var canvas = document.getElementById('my-canvas');
var ctx = canvas.getContext('2d');
var video = document.getElementById('video');
console.log("inside function\n");
video.addEventListener('play', function() {
var $this = this; //cache
(function loop() {
if (!$this.paused && !$this.ended) {
ctx.drawImage($this, 0, 0);
setTimeout(loop, 1000 / 30); // drawing at 30fps
}
})();
}, 0);
};
fn();
</script>
</body>
</html>
It looks like this on Desktop in Google Chrome.
I'm using the following command to record the page. The recording happens in headless mode.
timecut "file:///home/bob/test2.html" --viewport="1920,1080" --executable-path="/usr/bin/google-chrome" --fps=25 --duration=5 --pipe-mode --pix-fmt=yuv420p --output=video.mp4
And the recording looks like this. Why nothing is being captured from the canvas element?
I'm on Ubuntu 16.04 LTS, using Chrome Version 90.0.4430.212 (Official Build) (64-bit).
I'm using the same chrome binary for headless recording.
Node Version v15.2.0
Timecut Version 0.2.0
BigBuckBunny mp4 file available at http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4
Why nothing is being captured from the canvas element? What am I missing here?
Hi @tungs, when am opening an URL none of the xhr request is working. Kindly let me know if any arguments are need to enable?
cc: @varunarora
Is your feature request related to a problem? Please describe.
I want to inject data into the window as described here: https://stackoverflow.com/a/56318041/1715153
I've tried this with the regular puppeteer package using page.evaluate()
method and it works.
Example:
await page.evaluate(data => {
window.renderData = {};
window.renderData = data;
}, renderData)
However, if I try to inject window data with timecut's preparePage
or navigatePageToURL
, neither seems to work. I need to pass this data object into the window so my frontend website can pick up the data. I tried to pass the data as an encoded url but that doesn't work because it gets too long and causes chromium 431 error
.
Example of what I've tried with timecut:
preparePage: function (page) {
return page.evaluate(function () {
window.renderData = {};
window.renderData = renderData;
}
);
}
Describe the solution you'd like
Some way to inject data into the window before the page loads!
Describe alternatives you've considered
Using puppeteer instead which is not ideal.
P.S. I'm not sure if this is a bug or a feature request, I just need access to the puppeteer window during page.evaluate()
.
It'd beneficial to be able to change the waitUntil
behavior (currently set to networkidle0
https://github.com/tungs/timesnap/blob/fdfece3dd7eb7766365b42a7ab3d4b94195d9a3f/index.js#L175. In general, it'd be good to allow the user to specify all page.goto
options.
Also see #38, where it seems that overwriting time can interfere with loading the page.
Promise in timesnap
p = timeHandler.goToTimeAndAnimateForCapture(browserFrames, marker.time);
does not get resolved after some frames and puppeteer hangs infinitely.
As a workaround, I have used a timeout to detect unhandled promise but its letting me destroy that process.
Can we discuss - why is this odd behaviour?
Is your feature request related to a problem? Please describe.
I am trying to use timecut with node-ffmpeg installer. This proves to be problematic, as my desired ffmpeg path is contained within nodemodules, rather than installed on system binaries.
Describe the solution you'd like
I would like to be able to pass in a custom argument for ffmpegPath as a config value.
Describe alternatives you've considered
Additional context
Hi, @tungs
I had recorded canvas using timecut. But result was not full video, one half of video is blank, And it started to play after some time. How to sync video start time with this module?
Cc : @varunarora
Thank you soo much for your great work.
It will be great if there is a option to merge silent video with the final video output it will be easy to merge the audio with another video with audio using ffmpeg.
ffmpeg command to add silent audio
ffmpeg -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 -i {{$input}}
-shortest -c:v copy -c:a aac {{$output}}.
The arg doesn't work, even though it is accounted for in index.js
Hello @tungs,
I'm trying to record a page that plays a video on canvas using requestAnimationFrame
.
Following is the HTML file that I'm trying to record with headless Google-Chrome & timecut.
<html>
<body>
<div>
<canvas id="myCanvas" width="640" height="360"></canvas>
</div>
<script>
var mediaSource = "/home/bob/445329631.mp4";
var muted = true;
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var videoContainer;
var video = document.createElement("video");
video.src = mediaSource;
video.autoplay = false;
video.loop = true;
video.muted = muted;
videoContainer = {
video : video,
ready : false,
};
video.oncanplay = readyToPlayVideo;
function readyToPlayVideo(event){
videoContainer.scale = Math.min(
canvas.width / this.videoWidth,
canvas.height / this.videoHeight);
videoContainer.ready = true;
requestAnimationFrame(updateCanvas);
}
function updateCanvas(){
ctx.clearRect(0,0,canvas.width,canvas.height);
if(videoContainer !== undefined && videoContainer.ready){
video.muted = muted;
var scale = videoContainer.scale;
var vidH = videoContainer.video.videoHeight;
var vidW = videoContainer.video.videoWidth;
var top = canvas.height / 2 - (vidH /2 ) * scale;
var left = canvas.width / 2 - (vidW /2 ) * scale;
ctx.drawImage(videoContainer.video, left, top, vidW * scale, vidH * scale);
}
requestAnimationFrame(updateCanvas);
}
video.play();
</script>
</body>
</html>
I'm using following command to record the page.
timecut "file:///home/bob/test4.html" --viewport="1280,720" --executable-path="/usr/bin/google-chrome" --fps=25 --duration=5 --pipe-mode --pix-fmt=yuv420p --output=video_canvas_reqAnimFrame_25.mp4
Here's the original video element.
First, I recorded the page at 25 FPS using --fps=25
and --duration=5
. I got following.
Then, I recorded the same page at 60 FPS using --fps=60
and --duration=5
. I got following.
As you must have noticed, the video element on canvas is playing faster than usual in both recorded clips.
The video element plays faster than usual in 25 fps recording. And it plays even faster in 60 fps recording.
Does timeweb support recording of pages with video elements on canvas?
It seems like the video element is not playing in sync with the virtual timeline.
I tried multiple input video files. But all recordings had the same behavior.
What am I missing here?
Side Note:
There is one more way to play a video on canvas, i.e by using setTimeout
function.
If I use setTimeout(...)
to play video-element and render the page, it creates correct recording. But something is going wrong with requestAnimationFrame
way of playing video.
I'm on Ubuntu 16.04 LTS, using Chrome Version 90.0.4430.212 (Official Build) (64-bit).
I'm using my Desktop chrome binary for headless recording ( instead of chromium).
Node Version v15.2.0
Timecut Version 0.2.0
"Blocked script execution in 'file:///D:/makevideo/replay.html' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.", source: file:///D:/makevideo/replay.html (0)
TimeoutError: Navigation timeout of 30000 ms exceeded
at D:\software\nodejs\node_global\node_modules\timecut\node_modules\puppeteer\lib\LifecycleWatcher.js:142:21
-- ASYNC --
at Frame. (D:\software\nodejs\node_global\node_modules\timecut\node_modules\puppeteer\lib\helper.js:111:15)
at Page.goto (D:\software\nodejs\node_global\node_modules\timecut\node_modules\puppeteer\lib\Page.js:672:49)
at Page. (D:\software\nodejs\node_global\node_modules\timecut\node_modules\puppeteer\lib\helper.js:112:23)
at D:\software\nodejs\node_global\node_modules\timecut\node_modules\timesnap\index.js:173:21
at processTicksAndRejections (internal/process/task_queues.js:97:5)
Error: spawn ffmpeg ENOENT
at Process.ChildProcess._handle.onexit (internal/child_process.js:267:19)
at onErrorNT (internal/child_process.js:469:16)
at processTicksAndRejections (internal/process/task_queues.js:84:21) {
errno: 'ENOENT',
code: 'ENOENT',
syscall: 'spawn ffmpeg',
path: 'ffmpeg',
spawnargs: [
'-framerate',
60,
'-i',
'D:\makevideo\timecut-temp-1598701129093\image-%09d.png',
'-pix_fmt',
'yuv420p',
'-y',
'D:\makevideo\video.mp4'
]
}
How to solve this problem,thank you very much
I am wondering that if there is any available option to use timecut with node-canvas or jsdom instead of url option.
Please allow passing custom flags to the ffmpeg process.
I wanted to add an audio by passing it as an input to the ffmpeg process.
Also, have you considered fluent-ffmpeg? Maybe using and exposing it would be better than exposing the arguments array that you currently pass to spawn
Ah, sorry, I'm too lazy to read. It seems this also already exists.
I'm sorry if GH Issues isn't the correct avenue for this, but I wasn't sure where else to ask and I don't see it in the docs. Does Timecut emit any events upon each frame being created so that I can emit that message and use it to render a progress bar?
Hello!
I have an issue while recording an animated SVG.
Pobably I'm just confused on how the "fps" and "duration" options really work.
My goal is to generate multiple PNG images (I use the --keep-frames
option for this) representing the animation frames.
My first test was rendering a 64fps, 1s long video.
So I used --fps 64 --duration 1
Unfortunately, the animation was too fast so I decided to go for a 256fps, 4s long video. The result was just the same as before, but looped 4 times in sequence.
Just for test, I also tried rendering both a 64fps 4s video and a 256fps 1s video.... And they appear to be the same!
I thought that the first would result in a 4 cycles loop (one per second), while the second would result in a single cycle rendered at a higher framerate.
Is there a way to get a slowmotion video out of an animated SVG?
Attached, you can find the SVG I used in my tests.
Hey there,
I really love the plugin and thank you very much for sharing it with us 🙏
I'm trying to record a local webpage that consists of multiple HTML canvases and an HTML audio element. The canvases react and move based on the audio file, I'm hoping to record the movement, and glue the MP3 file to the video afterward the creation of the video.
In the preparePage function I trigger the page to play the audio element which triggers the canvases to animate, which all works fine. But the actual video is not realtime/aligned with the audio file, the video skips a lot of frames in between. I feel like its only recording 1 FPS.
Is there some way of making this awesome plugin work for my use case or am I misunderstanding something?
Thank you in advance.
Bug - The video becomes blank if the page scrolls with window.scrollTo
When writing to the ffmpeg's stdin
(i.e. when not in frame mode), there can be a ECONNRESET error thrown from the ffmpeg process. It looks like this is caused by ffmpeg resetting the input stream for some option configurations. In these observed cases, it seems to not be thrown when ffmpeg is passed the -pix_fmt yuv420p
option for its output.
In any case, this should error should be detected and recommend the user to switch to frame mode or -pix_fmt.
I ran this command : sudo timecut "http://localhost:8888/timecut/index.html" --duration=0.5 --selector="#canvas" --output="videos/vid.mp4"
But after capturing all the frames, timecut show an error and did not save the file:
{ Error: spawn ENOTDIR at ChildProcess.spawn (internal/child_process.js:355:11) at spawn (child_process.js:521:9) at makeProcessPromise (/Users/ymoussaba/.nvm/versions/node/v10.1.0/lib/node_modules/timecut/index.js:135:22) at /Users/ymoussaba/.nvm/versions/node/v10.1.0/lib/node_modules/timecut/index.js:176:16 errno: 'ENOTDIR', code: 'ENOTDIR', syscall: 'spawn' }
Hi, @tungs this package is very useful to render web videos. Here i need one more development process while output rendering process. ie) need to stitch audio at a particular duration while rendering the output mp4 with the use of ffmpeg.
Cc : @varunarora
Hi @tungs,
Thanks for this amazing library.
I'm recording a fabricjs canvas that has a video in it. I have added the same video element in DOM and kept it as hidden.
I'm using Google Chrome (103.0.5060.53 (Official Build) (arm64) ) on MacOS Monterey for recording canvas (instead of Chromium).
Everything works fine with [email protected]
But If I upgrade to v0.3.3, the video element on the page doesn't play.
I tried both headless and headful mode. In both cases the video element doesn't play.
Interestingly, GIFs are recorded correctly.
I can not share exact code for reproducing this.
How can I debug this issue?
Thanks!
Thanks for the awesome library.
Recording of .mp4 embeds not working.
It's giving an error like "PIPELINE_ERROR DEMUXER_ERROR_NO_SUPPORTED_STREAMS"
Could you please tell me how to fix it
Hi @tungs, When starting my server using js file, this error occurs. Kindly know me what argument i missed in it.
const timecut = require('timecut');
const fs = require('fs');
timecut({
headless: false,
frameCache : true,
launchArguments : '--no-sandbox --allow-http-screen-capture --disable-setuid-sandbox --single-process',
url: 'localurl/video',
timeout: 10000,
viewport: {
width: 800, // sets the viewport (window size) to 800x600
height: 600
},
selector: '#myCanvas', // crops each frame to the bounding box of '#container'
left: 20, top: 40, // further crops the left by 20px, and the top by 40px
right: 6, bottom: 30, // and the right by 6px, and the bottom by 30px
fps: 30, // saves 30 frames for each virtual second
duration: 20, // for 20 virtual seconds
output: 'video.mp4' // to video.mp4 of the current working directory
}).then(function () {
console.log('Done!');
}).catch(function(e) {
console.log(e);
})
Cc: @varunarora
Just like the title said, the video rendered is much faster than the original animation open in the browser. I try to change settings but I have no idea what causes this.
I tried to render the night animation (https://github.com/antonyleme/CSS-Animations)
and this is the result (https://user-images.githubusercontent.com/50512341/124915006-e0db5300-dfa5-11eb-8fff-692b10e0e7a1.mp4)
The animation in the video ends up very fast. Help.
Hey!
I have a simple functions which runs when I open my index.html
file. My animation takes about 20 seconds for full cycle and I'm trying to capture only first 2.
$('.wall').css('animation', 'fade ' + 20 + 's infinite linear');
$('.wrap').css('animation', 'move ' + 20 + 's infinite linear');
$('.wall').css('animation-direction', 'reverse');
$('.wrap').css('animation-direction', 'reverse');
$('.glow').css('filter', 'blur(' + 1 + 'px)');
$('.glow').css('opacity', 1 / 100);
$('.wall').css('background', 'url("some/path/to/img.jpg")');
When I try to capture the animation I have using following command line code:
timesnap index.html --screenshot-type jpeg \
-V "2000,2000" --fps=60 --duration=2 \
--output-stdout | ffmpeg -framerate 60 -i pipe:0 -y -pix_fmt yuv420p video.mp4
It returns a video which is faster 5-10x times than the one I see when I just open index.html
in Chrome.
Is there a way to let timecut
to take only first 2 seconds of real animation I see in browser?
I'm sorry for noobie questions, haha.
Describe the bug
It randomly fails to execute
To Reproduce
timecut/cli.js flow5.svg --viewport="520,520" --fps=30 --duration=10
--frame-cache --pix-fmt=yuv420p --output=Flow5.mp4
Expected behavior
No Errors
Attachments and Screenshots
Capturing Frame 47 to /Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut-temp-1654507450971/image-000000047.png...
Received signal 11 SEGV_MAPERR 000000000000
[0x00011b210d79]
[0x00011b140003]
[0x00011b210c91]
[0x7ff809fbadfd]
[0x000000000000]
[0x7ff809fa0f70]
[end of stack trace]
Error: Protocol error (Page.captureScreenshot): Target closed.
at /Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/puppeteer/lib/Connection.js:183:56
at new Promise ()
at CDPSession.send (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/puppeteer/lib/Connection.js:182:12)
at Page._screenshotTask (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/puppeteer/lib/Page.js:948:39)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
-- ASYNC --
at Page. (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/puppeteer/lib/helper.js:111:15)
at Object.capture (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/timesnap/lib/capture-screenshot.js:93:31)
at run (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/timesnap/index.js:271:28)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at async module.exports (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/timesnap/index.js:287:5)
at async module.exports (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/index.js:210:7)
Error: Protocol error (Page.captureScreenshot): Target closed.
at /Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/puppeteer/lib/Connection.js:183:56
at new Promise ()
at CDPSession.send (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/puppeteer/lib/Connection.js:182:12)
at Page._screenshotTask (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/puppeteer/lib/Page.js:948:39)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
-- ASYNC --
at Page. (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/puppeteer/lib/helper.js:111:15)
at Object.capture (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/timesnap/lib/capture-screenshot.js:93:31)
at run (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/timesnap/index.js:271:28)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at async module.exports (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/timesnap/index.js:287:5)
at async module.exports (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/index.js:210:7)
(node:88556) UnhandledPromiseRejectionWarning: Error: Protocol error (Page.captureScreenshot): Target closed.
at /Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/puppeteer/lib/Connection.js:183:56
at new Promise ()
at CDPSession.send (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/puppeteer/lib/Connection.js:182:12)
at Page._screenshotTask (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/puppeteer/lib/Page.js:948:39)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
-- ASYNC --
at Page. (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/puppeteer/lib/helper.js:111:15)
at Object.capture (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/timesnap/lib/capture-screenshot.js:93:31)
at run (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/timesnap/index.js:271:28)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at async module.exports (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/node_modules/timesnap/index.js:287:5)
at async module.exports (/Users/gurugeek/Documents/Dokumente - David’s iMac/fishdraw-main/timecut/index.js:210:7)
(Use node --trace-warnings ...
to show where the warning was created)
(node:88556) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict
(see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:88556) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
gurugeek@davids-imac fishdraw-main % timecut/cli.js flow5.svg --viewport="520,520" --fps=30 --duration=10
--frame-cache --pix-fmt=yuv420p --output=Flow5.mp4
Desktop (please complete the following information):
Additional context
When recording a declarative (SMIL) animation, the animation speed in the recorded video does not match the animation speed in the actual SVG file.
Hi, great library!
I'm trying to record a css animation that lasts 12 seconds realtime on browser, but with the following code, the animation lasts 3 seconds and the video the 12 seconds, any idea if I'm missing some configuration?
Thanks!
const timecut = require('timecut'); timecut({ url: '', viewport: { width: 300, height: 250 }, quiet: false, pipeMode: true, fps: 30, duration: 12, output: 'video.mp4' }).then(function () { console.log('Done!'); });
Hi,
I'm calling timecut the following way
timecut({ url: this._input, output: this._output, duration: this._duration, fps: this._framerate, quiet: true, pipeMode: true, launchArguments: ["--no-sandbox", "--disable-setuid-sandbox", "--allow-file-access-from-files"], canvasCaptureMode: true, selector: "#canvas" }).then(this.markAsDone).catch(this.markAsError);
unfortunately I'm not able to catch the above mentioned errors as the promise is already rejected when returning it in
return timesnap(timesnapConfig) .then(function () { if (convertProcess) { convertProcess.stdin.end(); } }) .then(function () { // wait for ffmpeg to finish if (processPromise) { return processPromise; } else { return makeProcessPromise(); } }).catch(function (err) { log(err); }).then(function () { if (frameMode && !config.keepFrames) { deleteFolder(frameDirectory); } });
Best regards
I'm trying to load external web fonts before Timecut starts recording.
I use Webfontloader to load multiple web fonts from Google.
The problem is that I can't find a way to load the fonts before or during the initial page render, the fonts will always start loading when Timecut is recording. Which results in the text suddenly changing from font-family during the render.
Webfontloader has a "Loaded" event callback but I can't find a way to wait for it in the "preparePage" function of Puppeteer.
I also tried using setInterval to check if the fonts have finished loading but this just results in the same issue.
setInterval, setTimeout and the callbacks never get fired during the preparePage stage.
Hey Steve, I was wondering if you had a "best practice" timecut options screenshot example you could share with me? I'm using this for video render:
const render = (io, payload) => {
const { mediaType, extension, duration } = payload.data.renderOptions;
timecut({
url: myUrlVariable,
viewport: {
width: 1920,
height: 1080
},
fps: 25,
duration,
transparentBackground: true,
pipeMode: true,
outputOptions: ['-c:v', 'prores_ks', '-pix_fmt', 'yuva444p10le'],
screenshotType: 'jpeg',
output: `renders/${payload.fileId}.${extension ? extension : 'mov'}`,
logger: (message) => {
io.emit('timecut', {
message: getMessage(message)
});
},
preparePageForScreenshot: (page, num1, num2) => {
console.log(page, num1, num2); // <--- What do I do here?
return Promise.resolve();
}
}).then(function() {
console.log('Done!');
});
};
Do I just set the FPS to 1 and duration to 1? Just trying to see if I need to use a totally different function or if I can just reply on passed args.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.