sskodje / ScreenRecorderLib

A .NET library for screen recording in Windows, using native Microsoft Media Foundation for realtime encoding to h264 video or PNG images.
MIT License
408 stars 93 forks source link

Cursor not recorded properly when using "SourceRect" #260

Closed k1mmm closed 1 year ago

k1mmm commented 1 year ago

Hello!

Cursor recording is not positioned correctly when cropping the output. I'm trying to record a part of the screen and then check if the output size is larger than allowed, and if so i scale it down. I'm using a 4k screen with 150% zoom, so I'm also calculating the pixels * DPI.

The cropping works perfectly, but the cursors position is off by allot. Maybe I'm doing something wrong. OutputOptions = new OutputOptions { OutputFrameSize = outputFrameSize, SourceRect = new ScreenRect(x, y, width, height), },

And here's the full code if it helps =)

        public void StartRecording(int x, int y, int width, int height, string quality = "high")
        {
            Debug.WriteLine("Quality: " + quality);
            if (isRecording)
            {
                // stop recording
                StopRecording();
                return;
            }

            this._x = x;
            this._y = y;
            this._width = width;
            this._height = height;

            ShowRecordingWindow();

            DpiHelper.GetDpiForCurrentScreen(out double dpiX, out double dpiY);

            Debug.WriteLine($"Retrieved DPI - dpiX: {dpiX}, dpiY: {dpiY}");

            // Convert WPF's device-independent units to screen units

            x = (int)(x * dpiX / 96.0);
            y = (int)(y * dpiY / 96.0);
            width = (int)(width * dpiX / 96.0);
            height = (int)(height * dpiY / 96.0);

            Dictionary<string, string> paths = System.Windows.Application.Current.Properties["Paths"] as Dictionary<string, string>;
            int bitrate = GetBitRate(width, height);
            ScreenSize outputFrameSize = GetOutputFrameSize(width, height, quality);

            isRecording = true;

            RecorderOptions recoderOptions = new RecorderOptions
            {
                VideoEncoderOptions = new VideoEncoderOptions
                {
                    Framerate = 60,
                    Bitrate = bitrate,
                },
                OutputOptions = new OutputOptions
                {
                    OutputFrameSize = outputFrameSize,
                    SourceRect = new ScreenRect(x, y, width, height),
                },
                MouseOptions = new MouseOptions
                {    
                    IsMousePointerEnabled = true,
                },
            };

            recorder = Recorder.CreateRecorder(recoderOptions);
            recorder.OnRecordingComplete += Recorder_OnRecordingComplete;
            recorder.OnRecordingFailed += Recorder_OnRecordingFailed;
            recorder.OnStatusChanged += Recorder_OnStatusChanged;
            //Record to a file
            string videoPath = paths["video"];
            recorder.Record(videoPath);

            Debug.WriteLine("Recording started " + paths["video"]);
        }

        private ScreenSize GetOutputFrameSize(int width, int height, string quality)
        {
            ScreenSize maxResolution = GetMaxResolutionForQuality(quality);

            double aspectRatio = (double)width / height;
            double maxAspectRatio = (double)maxResolution.Width / maxResolution.Height;

            int newWidth, newHeight;

            if (aspectRatio > maxAspectRatio)
            {
                newWidth = (int)maxResolution.Width;
                newHeight = (int)(newWidth / aspectRatio);
            }
            else
            {
                newHeight = (int)maxResolution.Height;
                newWidth = (int)(newHeight * aspectRatio);
            }

            // Return the new ScreenSize object with the scaled dimensions
            return new ScreenSize(newWidth, newHeight);
        }

        private ScreenSize GetMaxResolutionForQuality(string quality)
        {
            switch (quality.ToLower())
            {
                case "low":
                    return new ScreenSize(1280, 720);
                case "medium":
                    return new ScreenSize(1920, 1080);
                case "high":
                    return new ScreenSize(2560, 1440);
                case "ultra":
                    return new ScreenSize(3840, 2160);
                default:
                    // Default to medium quality if the input string doesn't match any of the predefined qualities
                    return new ScreenSize(1920, 1080);
            }
        }
k1mmm commented 1 year ago

The cursor do not scale properly either, I'm using a 4k screen with 150% scale, and the cursor is as small as with no scaling.

sskodje commented 1 year ago

I'll look into it :)

k1mmm commented 1 year ago

I'll look into it :)

Thank you, I really appreciate it! =)

sskodje commented 1 year ago

I pushed a fix i believe will fix this issue, and also made a new version. Let me know if there's still any issues :)

k1mmm commented 1 year ago

I pushed a fix i believe will fix this issue, and also made a new version. Let me know if there's still any issues :)

It works beautifully! Thanks allot!