Skip to content

Commit 36cf11a

Browse files
committed
Add optional video downscaling
1 parent a0fab2f commit 36cf11a

File tree

2 files changed

+74
-10
lines changed

2 files changed

+74
-10
lines changed

Documentation.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ <h3>Configuration</h3>
112112
<ul>
113113
<li><strong>Frame Rate</strong>: Default is 30. Higher rates may increase file size and resource usage.</li>
114114
<li><strong>Recording Duration</strong>: Default is 60 seconds.</li>
115+
<li><strong>Downscale Video</strong>: <em>Off by default.</em> If enabled, the video will be downscaled to a maximum resolution (default: 1920x1080) if your game runs at a higher resolution. This helps reduce CPU usage and file size when recording on high-resolution displays. Enable this option in the inspector if you notice high CPU usage or stuttering during recording at large resolutions.</li>
115116
</ul>
116117
</li>
117118
</ul>

Runtime/Scripts/GameRecorder.cs

Lines changed: 73 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ public class GameRecorder : MonoBehaviour
1212

1313
public int RecordingDuration = 60;
1414

15+
[Tooltip("If true, the video will be downscaled if the screen resolution is higher than the maximum video height and width.")]
16+
public bool DownscaleVideo = false;
17+
18+
[Tooltip("The maximum height of the video. The video will be downscaled if the screen resolution is higher.")]
19+
public int MaxVideoHeight = 1080;
20+
21+
[Tooltip("The maximum width of the video. The video will be downscaled if the screen resolution is higher.")]
22+
public int MaxVideoWidth = 1920;
23+
1524
private Texture2D _screenShot;
1625

1726
public bool IsRecording { get; private set; }
@@ -22,6 +31,8 @@ public class GameRecorder : MonoBehaviour
2231

2332
private int _gameWidth;
2433
private int _gameHeight;
34+
private int _outputWidth;
35+
private int _outputHeight;
2536

2637
private float _captureInterval;
2738
private float _nextCaptureTime;
@@ -37,6 +48,26 @@ void Start()
3748
_gameWidth = Screen.width % 2 == 0 ? Screen.width : Screen.width - 1;
3849
_gameHeight = Screen.height % 2 == 0 ? Screen.height : Screen.height - 1;
3950

51+
// Determine target (output) resolution
52+
_outputWidth = _gameWidth;
53+
_outputHeight = _gameHeight;
54+
float aspect = (float)_gameWidth / _gameHeight;
55+
if (DownscaleVideo && (_gameWidth > MaxVideoWidth || _gameHeight > MaxVideoHeight))
56+
{
57+
_outputHeight = Mathf.Min(_gameHeight, MaxVideoHeight);
58+
_outputWidth = Mathf.RoundToInt(_outputHeight * aspect);
59+
if (_outputWidth > MaxVideoWidth)
60+
{
61+
_outputWidth = MaxVideoWidth;
62+
_outputHeight = Mathf.RoundToInt(_outputWidth / aspect);
63+
}
64+
// Ensure both dimensions are even
65+
_outputWidth -= _outputWidth % 2;
66+
_outputHeight -= _outputHeight % 2;
67+
68+
UnityEngine.Debug.Log($"Video is to be downscaled to {_outputWidth}x{_outputHeight}");
69+
}
70+
4071
// Create a Texture2D with the adjusted resolution
4172
_screenShot = new Texture2D(_gameWidth, _gameHeight, TextureFormat.RGB24, false);
4273
_texturePainter = new TexturePainter(_screenShot);
@@ -48,8 +79,8 @@ void Start()
4879
outputDirectory = "BH_Recording";
4980
}
5081

51-
// Initialize the video encoder with the adjusted resolution
52-
_videoEncoder = new VideoEncoder(_gameWidth, _gameHeight, FrameRate, RecordingDuration, outputDirectory);
82+
// Initialize the video encoder with the output resolution
83+
_videoEncoder = new VideoEncoder(_outputWidth, _outputHeight, FrameRate, RecordingDuration, outputDirectory);
5384

5485
_captureInterval = 1.0f / FrameRate;
5586
_nextCaptureTime = Time.time;
@@ -110,6 +141,17 @@ public string StopRecordingAndSaveLastMinute()
110141

111142
private IEnumerator CaptureFrames()
112143
{
144+
UnityEngine.Debug.Log($"Game resolution: {_gameWidth}x{_gameHeight}");
145+
UnityEngine.Debug.Log($"Output resolution: {_outputWidth}x{_outputHeight}");
146+
147+
RenderTexture scaledRT = null;
148+
Texture2D scaledTexture = null;
149+
if (_outputWidth != _gameWidth || _outputHeight != _gameHeight)
150+
{
151+
scaledRT = new RenderTexture(_outputWidth, _outputHeight, 0, RenderTextureFormat.ARGB32);
152+
scaledTexture = new Texture2D(_outputWidth, _outputHeight, TextureFormat.RGB24, false);
153+
}
154+
113155
while (IsRecording)
114156
{
115157
yield return new WaitForEndOfFrame();
@@ -118,22 +160,43 @@ private IEnumerator CaptureFrames()
118160
{
119161
_nextCaptureTime += _captureInterval;
120162

121-
// Capture the screen content into the Texture2D
163+
// 1. Capture the full-res frame
122164
_screenShot.ReadPixels(new Rect(0, 0, _gameWidth, _gameHeight), 0, 0);
123165
_screenShot.Apply();
124166

125-
// Draw a vertical progress bar as an example
126-
// float cpuUsage = 0.5f; // Replace this with actual CPU usage value
127-
// texturePainter.DrawVerticalProgressBar(10, 10, 20, 100, cpuUsage, Color.green, Color.black);
167+
byte[] frameData;
128168

129-
// Draw a number as an example
130-
// texturePainter.DrawNumber(50, 10, (int) fps, Color.white, 4);
131-
_texturePainter.DrawNumber(5, 5, (int)_fps, Color.white, 2);
169+
if (scaledRT != null)
170+
{
171+
// 2a. Blit (scale) to RT
172+
Graphics.Blit(_screenShot, scaledRT);
173+
174+
// 2b. Read pixels from scaled RT
175+
RenderTexture.active = scaledRT;
176+
scaledTexture.ReadPixels(new Rect(0, 0, _outputWidth, _outputHeight), 0, 0);
177+
scaledTexture.Apply();
178+
RenderTexture.active = null;
179+
180+
// 3a. Draw overlays on the scaled texture
181+
var painter = new TexturePainter(scaledTexture);
182+
painter.DrawNumber(5, 5, (int)_fps, Color.white, 2);
183+
184+
frameData = scaledTexture.GetRawTextureData();
185+
}
186+
else
187+
{
188+
// 2b. Draw overlays on the original screenshot
189+
_texturePainter.DrawNumber(5, 5, (int)_fps, Color.white, 2);
190+
frameData = _screenShot.GetRawTextureData();
191+
}
132192

133-
byte[] frameData = _screenShot.GetRawTextureData();
134193
_videoEncoder.AddFrame(frameData);
135194
}
136195
}
196+
197+
// Clean up if needed
198+
if (scaledTexture != null) Destroy(scaledTexture);
199+
if (scaledRT != null) scaledRT.Release();
137200
}
138201
}
139202
}

0 commit comments

Comments
 (0)