How do I make a Nintendo Switch style replay system?

0 favourites
From the Asset Store
Toggles Dials Switches and Alerts ! A foundational sound grouping of Analog type switches and Steampunk effects
  • This may be a bit hard to explain so bear with me.

    I want to add a system to my game where if you press a button on the keyboard, it downloads a video clip of the last 30 seconds of gameplay, similar to if you hold the snapshot button on the nintendo switch for a second.

    My idea for how this could work is by using the Video Recorder plugin, I continuously record footage of the game and continuously delte everything 30 seconds or earlier from the present time (or maybe delete it just when you save the video), and then have a button download the 30 second clip. The problem is that I don't know how to delete certain parts of the video.

    So far I have this basic recording system:

    Any ideas?

    Tagged:

  • Hmm I don't think this is possible with the build in plugin. The first issue is that, as you noticed, there's no way of deleting part of the ongoing recording. Deleting it before download may be possible, but it will still continously record footage, possibly until it runs out of memory (and crashes or something).

    Not sure how I'd tackle this problem.

  • I’m wondering whether you could record in 1 second chunks, delete any older than 30 seconds, then stitch together the last 30 when the user makes the request. No idea if it’s possible though!

  • I’m wondering whether you could record in 1 second chunks, delete any older than 30 seconds, then stitch together the last 30 when the user makes the request. No idea if it’s possible though!

    Interesting idea. That sounds more feasible, but I still need to figure out: 1. How to avoid bombarding the player with download requests, 2. Performance, and 3. How to stitch together the recordings. I'll see what I can do.

  • Interesting idea. That sounds more feasible, but I still need to figure out: 1. How to avoid bombarding the player with download requests, 2. Performance, and 3. How to stitch together the recordings. I'll see what I can do.

    I don't think you need to bombard the player - I was thinking that you might be able to use the AJAX plugin to read the recorded video via its URL. From that plugin's page:

    Binary data

    The AJAX object can receive resources as binary, and also post binary data, using the Binary Data object. This is also useful to fetch local resources like canvas snapshot URLs or video recording URLs, and load them in to a Binary Data object to do something else with them, like save it to storage or upload it to a server.

    So:

    1. Create an array with 30 entries
    2. Record 1 second
    3. Store its URL in the array
    4. Delete the last entry (i.e. the 31st) every time a new video is logged
    5. Player clicks the download button
    6. Loop through the 30 entries in the array
    7. Use the AJAX plugin to retrieve each clip via its URL
    8. Some magic here to stitch all the clips together (might need raw JavaScript)
    9. Serve the resulting 30 clip to the user as a download

    That might solve the problem of not wanting to prompt the user to download every video, but you might have a similar problem requesting permission to start the recording. This is from the Video Recorder manual:

    For security reasons, browsers will prompt the user before the recording starts. To avoid the prompt annoying users, this action may only be allowed in a user input trigger, e.g. On button clicked, On touch start etc.

    And I'm not exactly sure what that implies!

  • just record a new video every 30 seconds

  • just record a new video every 30 seconds

    What do you do if you started recording a new video 5 seconds ago, and now need to replay the last 30?

  • > just record a new video every 30 seconds

    What do you do if you started recording a new video 5 seconds ago, and now need to replay the last 30?

    make like a buffer where you store the last 2 videos and delete the oldest once a new one is recorded

  • I've looked around a bit and I think your best bet is to go the javascript route. It might not be as hard as it seems at first.

    Use the mediarecorder api, which I assume is what the plugin also uses under the hood

    developer.mozilla.org/en-US/docs/Web/API/MediaRecorder

    Specifically note this part

    MediaRecorder.start()

    Begins recording media; this method can optionally be passed a timeslice argument with a value in milliseconds. If this is specified, the media will be captured in separate chunks of that duration, rather than the default behavior of recording the media in a single large chunk.

    So you can specifiy to automatically record chunks of 1 second. Every second from then on will fire the dataavailable event.

    Within this event you can store the created data chunks however you please (e.g. an array of 30 for 30 seconds of recording)

    Then when the user requests the highlight you can combine them like so (and I think this should generate a blob url that you can then invoke a download on)

    function play() {
     var superBuffer = new Blob(recordedChunks);
    }

    It's basically what citron2010 suggested but handling it in js is going to be much easier than doing some roundabout way in events.

    EDIT: It should also avoid the issue with requesting permission. This should only request permission once, when the recording starts. After that it's just a continous recording, that you can tap in at any given moment to extract the last 30 seconds from.

  • > Interesting idea. That sounds more feasible, but I still need to figure out: 1. How to avoid bombarding the player with download requests, 2. Performance, and 3. How to stitch together the recordings. I'll see what I can do.

    I don't think you need to bombard the player - I was thinking that you might be able to use the AJAX plugin to read the recorded video via its URL. From that plugin's page:

    > Binary data

    > The AJAX object can receive resources as binary, and also post binary data, using the Binary Data object. This is also useful to fetch local resources like canvas snapshot URLs or video recording URLs, and load them in to a Binary Data object to do something else with them, like save it to storage or upload it to a server.

    So:

    1. Create an array with 30 entries
    2. Record 1 second
    3. Store its URL in the array
    4. Delete the last entry (i.e. the 31st) every time a new video is logged
    5. Player clicks the download button
    6. Loop through the 30 entries in the array
    7. Use the AJAX plugin to retrieve each clip via its URL
    8. Some magic here to stitch all the clips together (might need raw JavaScript)
    9. Serve the resulting 30 clip to the user as a download

    That might solve the problem of not wanting to prompt the user to download every video, but you might have a similar problem requesting permission to start the recording. This is from the Video Recorder manual:

    > For security reasons, browsers will prompt the user before the recording starts. To avoid the prompt annoying users, this action may only be allowed in a user input trigger, e.g. On button clicked, On touch start etc.

    And I'm not exactly sure what that implies!

    >

    Thanks for the feedback. I used the list to make a system in a test project that downloads all of the last 30 second clips, but it keeps giving "check internet access" errors, and I still need a way to stich them together (both issues may be related, as the constant downloads may be causing the error while only downloading one file may not).

    I've looked around a bit and I think your best bet is to go the javascript route. It might not be as hard as it seems at first.

    Use the mediarecorder api, which I assume is what the plugin also uses under the hood

    https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder

    Specifically note this part

    > MediaRecorder.start()

    > Begins recording media; this method can optionally be passed a timeslice argument with a value in milliseconds. If this is specified, the media will be captured in separate chunks of that duration, rather than the default behavior of recording the media in a single large chunk.

    So you can specifiy to automatically record chunks of 1 second. Every second from then on will fire the dataavailable event.

    Within this event you can store the created data chunks however you please (e.g. an array of 30 for 30 seconds of recording)

    Then when the user requests the highlight you can combine them like so (and I think this should generate a blob url that you can then invoke a download on)

    > function play() {
    var superBuffer = new Blob(recordedChunks);
    }

    It's basically what citron2010 suggested but handling it in js is going to be much easier than doing some roundabout way in events.

    EDIT: It should also avoid the issue with requesting permission. This should only request permission once, when the recording starts. After that it's just a continous recording, that you can tap in at any given moment to extract the last 30 seconds from.

    Yeah I feared that the use of JS may be inevitable. I have very little experience with text-based coding, but I suppose I can try. I think that if I can use both event sheets (for the main code) and JS (for stitching the files together) I may be able to make it work.

    If anyone wants to see what I have or try a solution themselves here is the sample file: drive.google.com/file/d/1q1x6LwLyEeOzNXZGZTuas6cDnQT5RUMS/view

  • I gave my idea a shot but unfortunately I'm running into the issue that I cannot just discard older chunks. I'm assuming the first chunk aka the beginning contains some vital information/header, so the recording gets corrupted once the 30 second mark is passed because that first chunk gets removed. Keeping it also does not properly work and just creates some nice visual glitches in the resulting video if it works at all.

    I found very little information on this and no real solutions. Not sure if there is some kind of magic one could employ to get this to work. The only possible solution I saw (although in a different context) was this stackoverflow.com/questions/42127276/trim-or-cut-audio-recorded-with-mediarecorder-js

    But I have no clue how to actually implement this since it's for audio and not video.

    I can't post the c3p right now but here's the relevant js code which almost works but alas.

    	export class ReplaySystem {
    	constructor() {
    		this.stream = document.querySelector("canvas").captureStream();
    		this.highlightDuration = 10;
    		
    		this.mediaRecorder = new MediaRecorder(this.stream, {"mimeType": "video/webm"});
    		this.mediaRecorder.ondataavailable = this.dataAvailable.bind(this);
    		
    		this.replay = [];
    	}
    	
    	startRecording() {
    		this.mediaRecorder.start(1000);
    		console.log("Recording started");
    	}
    	
    	stopRecording() {
    		this.mediaRecorder.stop();
    		this.replay = [];
    		console.log("Recording stopped");	
    	}
    	
    	addChunk(chunk) {
    		this.replay.push(chunk);
    		if(this.replay.length > this.highlightDuration) {
    			this.replay.shift();
    		}
    	}
    	
    	dataAvailable(ev) {
    		this.addChunk(ev.data);
    	}
    	
    	captureHighlight(runtime) { 
    		const highlight = new Blob(this.replay, {type: 'video/webm'});
    		const url = URL.createObjectURL(highlight);
    		
    		runtime.callFunction("downloadHighlight", url);
    	}
    }
    
  • I gave my idea a shot but unfortunately I'm running into the issue that I cannot just discard older chunks. I'm assuming the first chunk aka the beginning contains some vital information/header, so the recording gets corrupted once the 30 second mark is passed because that first chunk gets removed. Keeping it also does not properly work and just creates some nice visual glitches in the resulting video if it works at all.

    I found very little information on this and no real solutions. Not sure if there is some kind of magic one could employ to get this to work. The only possible solution I saw (although in a different context) was this stackoverflow.com/questions/42127276/trim-or-cut-audio-recorded-with-mediarecorder-js

    But I have no clue how to actually implement this since it's for audio and not video.

    I can't post the c3p right now but here's the relevant js code which almost works but alas.

    > 	export class ReplaySystem {
    	constructor() {
    		this.stream = document.querySelector("canvas").captureStream();
    		this.highlightDuration = 10;
    		
    		this.mediaRecorder = new MediaRecorder(this.stream, {"mimeType": "video/webm"});
    		this.mediaRecorder.ondataavailable = this.dataAvailable.bind(this);
    		
    		this.replay = [];
    	}
    	
    	startRecording() {
    		this.mediaRecorder.start(1000);
    		console.log("Recording started");
    	}
    	
    	stopRecording() {
    		this.mediaRecorder.stop();
    		this.replay = [];
    		console.log("Recording stopped");	
    	}
    	
    	addChunk(chunk) {
    		this.replay.push(chunk);
    		if(this.replay.length > this.highlightDuration) {
    			this.replay.shift();
    		}
    	}
    	
    	dataAvailable(ev) {
    		this.addChunk(ev.data);
    	}
    	
    	captureHighlight(runtime) { 
    		const highlight = new Blob(this.replay, {type: 'video/webm'});
    		const url = URL.createObjectURL(highlight);
    		
    		runtime.callFunction("downloadHighlight", url);
    	}
    }
    

    Yeah, I don't know JS so I can't provide much feedback, but thanks for trying it out. I suppose if this doesn't work I can just make a system where the game records a whole level/session automatically, and you can use a button to download the recorded clip, but that isn't as cool in my opinion so I'll keep my eyes open for a solution.

  • Wait. I have an idea for how to stitch together the clips. What if I recorded the 30 1-second chucks in arrays (as shown in my demo project from earlier) and then had construct 3 play those clips back-to-back while I recorded the screen. Then I download the recording of the clips playing. Ima try this out...

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • I think I'm onto something here, but the video isn't playing. Feedback?

  • No idea, I'd have to try the project. A different although silly idea I had was to record 30 videos at the same time, all offset by 1 second. So when a highlight is requested you can just save the most recent one. But that's kind of an absurd solution.

    I also found some js implementations of ffmpeg, perhaps something could be done with this?

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)