Home › Forums › General Questions › Screenshots and Video Grabs
- This topic has 21 replies, 6 voices, and was last updated 5 months, 1 week ago by joeb.
-
AuthorPosts
-
2020-07-02 at 5:37 am #29500grimmyCustomer
Is there any way to download screenshots of my app at a size specified by the user and/or download gameplay of my app as a video? (some kind of screen recording functions)
Cheers
2020-07-06 at 10:01 am #29714Ivan LyubovnikovStaffHi,
You can download a screenshot of what’s rendered on a 3d scene via the
take screenshot
anddownload file
puzzles. See here for more info: https://www.soft8soft.com/docs/manual/en/puzzles/HTML.html#download_file.EDIT: you also need to enable screenshots in your application via the configure_application puzzle. The option you need is called ‘enabled screenshots’.
Co-founder and lead developer at Soft8Soft.
2020-07-06 at 11:29 am #29722grimmyCustomerCool. And what about grabbing video? Could I theoretically use something like GetDisplayMedia if I created all the functions in Javascript? Or maybe there is another way?
2020-07-06 at 1:03 pm #29725Ivan LyubovnikovStaffCould I theoretically use something like GetDisplayMedia if I created all the functions in Javascript?
Actually, yes. You can grab a video stream from the canvas element and download it.
Here’s a simple snippet which you can add into the runCode function in your app’s js file:
function runCode(app) { var isRecording = false; var TEXT_START = 'Start Recording'; var TEXT_STOP = 'Stop Recording'; var button = document.createElement('button'); button.innerText = TEXT_START; button.style.position = 'relative'; document.body.appendChild(button); var recorder = new MediaRecorder(app.renderer.domElement.captureStream()); var videoElem = document.createElement('video'); recorder.addEventListener('dataavailable', function(e) { var link = document.createElement('a'); link.href = URL.createObjectURL(e.data); link.download = 'video.webm'; document.body.appendChild(link); link.click(); URL.revokeObjectURL(link.href); }); button.addEventListener('click', function() { isRecording = !isRecording; button.innerText = isRecording ? TEXT_STOP : TEXT_START; if (isRecording) { recorder.start(); } else { recorder.stop(); } }); }
It adds a button to start recording and after you stop it automatically downloads the video in the webm format. Although, this snippet may not work in some browsers if some API features that’s used there are not supported, I only tested it in the latest Google Chrome version.
Co-founder and lead developer at Soft8Soft.
2022-10-17 at 6:56 pm #56663bhobbesParticipantHello,
I am an artist with zero coding experience. I came across Verge3D and so far it has been so easy to use (thank you!). I have one last thing I am trying to do with my app before I am ready to get a license and start production. I need to be able to make a video recording of my animation. I came across this thread and the code to record a video stream works when I plug it into the run code puzzle, however I have my verge app inside an iframe in my main html file.I would like to be able to alter the code above to record when the user clicks an html button “recordStart” and then to stop the recording when they click a second button “recordStop”. I already have puzzles set up to start and stop the animation when those buttons are clicked and would like to start/stop the recording with the same buttons.
I have been trying to get that code to work for a while now, but I really have no javascript experience. Any help you could offer would be greatly appreciated.
Thanks,
Bobby2022-10-18 at 10:04 am #56672kdvParticipantfunction runCode(app) { const type = v3d.Detector.checkIOS() ? 'video/mp4' : 'video/webm;codecs=avc1'; const stream = app.renderer.domElement.captureStream(30); const recorder = new MediaRecorder(stream, {mimeType: type}); recorder.addEventListener('dataavailable', function(e) { const link = document.createElement('a'); link.href = URL.createObjectURL(e.data); link.download = 'video.mp4'; document.body.appendChild(link); link.click(); URL.revokeObjectURL(link.href); link.remove(); }); const start = document.getElementById('recordStart'); start.addEventListener('click', function() { if (recorder.state == 'inactive') recorder.start(); }); const stop = document.getElementById('recordStop'); stop.addEventListener('click', function() { if (recorder.state != 'inactive') recorder.stop(); }); }
Puzzles and JS coding. Fast and expensive.
If you don’t see the meaning in something it primarily means that you just don’t see it but not the absence of the meaning at all.
2022-10-19 at 7:12 pm #56707bhobbesParticipantPerfect. Thank you so much for the help.
I plugged the code in and it didn’t seem to be working, so I put some buttons inside the project’s main html file that is being loaded into the iframe in my main html file. When I click the buttons inside the iframe it works, but not the buttons outside the iframe in the main index.html.
The buttons in the index.html work to start the animation (I have those set up with an html “on event of” puzzle). I think I am looking for the code equivalent of ticking on the checkbox for “in parent doc” for the puzzles?
So sorry to be a bother. I tried to look it up, but couldn’t find a suggestion that worked.
2022-10-19 at 7:15 pm #56708kdvParticipantconst start = parent.document.getElementById('recordStart'); const stop = parent.document.getElementById('recordStop');
Puzzles and JS coding. Fast and expensive.
If you don’t see the meaning in something it primarily means that you just don’t see it but not the absence of the meaning at all.
2022-10-19 at 9:14 pm #56709bhobbesParticipantBrilliant! That worked. Thank you sooo much for your help.
2022-10-21 at 10:22 am #56739kdvParticipantOne strange thing with this MediaRecorder: once created it loads CPU as if it’s already active and recording. After
start()
/stop()
the CPU load drops down.Puzzles and JS coding. Fast and expensive.
If you don’t see the meaning in something it primarily means that you just don’t see it but not the absence of the meaning at all.
2023-01-02 at 3:59 am #59324bhobbesParticipantThanks to your help, I was able to get this implemented and it works wonderfully. I’ve been testing on my live site and it’s going well.
The only thing I’ve noticed is the outputted video dimensions vary randomly. I’ve spent the past week trying out different things I found online to try and force a set video width and height with the code and haven’t been able to get anything to work. It’s probably just my lack of coding knowledge, but is it not possible to force the saved video to be a specific width & height?
2023-01-02 at 10:33 am #59328kdvParticipanthe outputted video dimensions vary randomly
what do you mean? the video dimensions directly depend on the canvas/window size. The canvas is captured 1:1.
Puzzles and JS coding. Fast and expensive.
If you don’t see the meaning in something it primarily means that you just don’t see it but not the absence of the meaning at all.
2023-01-02 at 7:48 pm #59338bhobbesParticipantYeah, that’s what is weird. The canvas is set at 1296×729. I opened the app and saved a bunch of videos back to back and most are saving at 1296×729, but about 1 in 3 videos save at 2073×1166.
Not a super huge deal. I just thought it was weird and wanted to see if I could force a size on the video to keep it consistent.
2023-01-02 at 8:01 pm #59339kdvParticipantSomething in your logic changes the pixel ratio with the factor
1.6
. Try to set the pixel ratio to1
before recording…function runCode(app) { const type = v3d.Detector.checkIOS() ? 'video/mp4' : 'video/webm;codecs=avc1'; const stream = app.renderer.domElement.captureStream(); const recorder = new MediaRecorder(stream, {mimeType: type}); recorder.addEventListener('dataavailable', function(e) { const link = document.createElement('a'); link.href = URL.createObjectURL(e.data); link.download = 'video.mp4'; document.body.appendChild(link); link.click(); URL.revokeObjectURL(link.href); link.remove(); }); const start = parent.document.getElementById('recordStart'); start.addEventListener('click', function() { if (recorder.state == 'inactive') { setScreenScale(1); setTimeout(function() { recorder.start(); }, 100); } }); const stop = parent.document.getElementById('recordStop'); stop.addEventListener('click', function() { if (recorder.state != 'inactive') recorder.stop(); }); function setScreenScale(factor) { app.renderer.setPixelRatio(factor); if (app.postprocessing) app.postprocessing.composer.setPixelRatio(factor); app.onResize(); } }
Puzzles and JS coding. Fast and expensive.
If you don’t see the meaning in something it primarily means that you just don’t see it but not the absence of the meaning at all.
2023-01-03 at 12:50 am #59344bhobbesParticipantThat did the job. Saved 10 videos back to back and they all came out the same size. Thank you very much!
-
AuthorPosts
- You must be logged in to reply to this topic.