Git Product home page Git Product logo

Comments (9)

NiiightmareXD avatar NiiightmareXD commented on May 19, 2024 1

The most straightforward solution to the problem is to record with the same source resolution. However, I'm interested in developing a resizing operation that allows users to record at any desired resolution and output it in their desired resolution. This feature is similar to what most recording software does, but it's a bit complicated, and I want to make it highly efficient. To achieve this, I plan to use DirectX with compute shader technology, which I'm unfamiliar with. Nonetheless, recording monitors are currently effortless.

I will leave this issue open until the problem is fully resolved.

If anyone is familiar with DirectX, please let me know. My current idea is to create a scene with the same size as the VideoEncoder resolution and overlay the image on top so that if the image is slightly larger, it will be cropped, and if it's smaller, there will be a black border around it, similar to how OBS does it.

from windows-capture.

NiiightmareXD avatar NiiightmareXD commented on May 19, 2024

This usually happens because of wrong resolution in VideoEncoder.

I'm looking for a way to make it work with all resolution but for now it should be the same as the source resolution.

from windows-capture.

yashwanth2804 avatar yashwanth2804 commented on May 19, 2024

Do we get window size from the window instance ,
Please share workable code if u got
Thank you

from windows-capture.

NiiightmareXD avatar NiiightmareXD commented on May 19, 2024

What resolution is your monitor?

from windows-capture.

yashwanth2804 avatar yashwanth2804 commented on May 19, 2024

1920 1080 p 24 inch

from windows-capture.

yashwanth2804 avatar yashwanth2804 commented on May 19, 2024

use std::{
    any::Any,
    io::{self, Write},
    time::Instant,
};

use windows::Win32::{
    Foundation::{BOOL, HWND, LPARAM, RECT, TRUE},
    UI::WindowsAndMessaging::GetWindowRect,
};
use windows_capture::{
    capture::GraphicsCaptureApiHandler,
    encoder::{VideoEncoder, VideoEncoderQuality, VideoEncoderType},
    frame::Frame,
    graphics_capture_api::InternalCaptureControl,
    monitor::Monitor,
    settings::{ColorFormat, CursorCaptureSettings, DrawBorderSettings, Settings},
    window::Window,
};

// This struct will be used to handle the capture events.
struct Capture {
    // The video encoder that will be used to encode the frames.
    encoder: Option<VideoEncoder>,
    // To measure the time the capture has been running
    start: Instant,
}

impl GraphicsCaptureApiHandler for Capture {
    // The type of flags used to get the values from the settings.
    type Flags = String;

    // The type of error that can occur during capture, the error will be returned from `CaptureControl` and `start` functions.
    type Error = Box<dyn std::error::Error + Send + Sync>;

    // Function that will be called to create the struct. The flags can be passed from settings.
    fn new(message: Self::Flags) -> Result<Self, Self::Error> {
        println!("Got The Flag: {message}");
        let flags_array: Vec<&str> = message.split(',').collect();
        let mut w_width = flags_array[0].parse::<u32>().unwrap();
        let mut w_height = flags_array[1].parse::<u32>().unwrap();

        let encoder = VideoEncoder::new(
            VideoEncoderType::Mp4,
            VideoEncoderQuality::HD1080p,
            w_width,
            w_height,
            "Video_1.mp4",
        )?;

        Ok(Self {
            encoder: Some(encoder),
            start: Instant::now(),
        })
    }

    // Called every time a new frame is available.
    fn on_frame_arrived(
        &mut self,
        frame: &mut Frame,
        capture_control: InternalCaptureControl,
    ) -> Result<(), Self::Error> {
        print!(
            "\rRecording for: {} seconds",
            self.start.elapsed().as_secs()
        );
        io::stdout().flush()?;

        // Send the frame to the video encoder
        self.encoder.as_mut().unwrap().send_frame(frame)?;

        // Note: The frame has other uses too for example you can save a single for to a file like this:
        // frame.save_as_image("frame.png", ImageFormat::Png)?;
        // Or get the raw data like this so you have full control:
        // let data = frame.buffer()?;

        // Stop the capture after 6 seconds
        if self.start.elapsed().as_secs() >= 6 {
            // Finish the encoder and save the video.
            self.encoder.take().unwrap().finish()?;

            capture_control.stop();

            // Because there wasn't any new lines in previous prints
            println!();
        }

        Ok(())
    }

    // Optional handler called when the capture item (usually a window) closes.
    fn on_closed(&mut self) -> Result<(), Self::Error> {
        println!("Capture Session Closed");

        Ok(())
    }
}

pub fn get_window_size(hwnd: HWND) -> Result<(i32, i32), windows::core::Error> {
    let mut rect = RECT::default();
    unsafe {
        GetWindowRect(hwnd, &mut rect).ok().expect("s");
    }
    let width = rect.right - rect.left;
    let height = rect.bottom - rect.top;
    Ok((width, height))
}

fn main() {
    // Gets The Foreground Window, Checkout The Docs For Other Capture Items
    let primary_monitor = Monitor::primary().expect("There is no primary monitor");
    print!(
        "\rPrimary Monitor: {}",
        primary_monitor.name().unwrap_or_default()
    );

    let window_to_capture = Window::from_contains_name("Visual Studio Code")
        .expect("There is no window with that name");

    let size = get_window_size(window_to_capture.as_raw_hwnd()).unwrap();

    print!("\rWindow Size: {}x{}", size.0, size.1);

    let array = vec![size.0.to_string(), size.1.to_string()];
    // print!("\rWindow to Capture: {}", window_to_capture.try_into().unwrap());

    let settings = Settings::new(
        // Item To Captue
        window_to_capture,
        // primary_monitor,
        // Capture Cursor Settings
        CursorCaptureSettings::Default,
        // Draw Borders Settings
        DrawBorderSettings::Default,
        // The desired color format for the captured frame.
        ColorFormat::Rgba8,
        // Additional flags for the capture settings that will be passed to user defined `new` function.
        array.join(","),
    )
    .unwrap();

    // Starts the capture and takes control of the current thread.
    // The errors from handler trait will end up here
    Capture::start(settings).expect("Screen Capture Failed");
}

in this code i made it worked , when vs code is in windowed mode ,

if the vs code is in full size mode , getting the same issue in pink color

image

from windows-capture.

NiiightmareXD avatar NiiightmareXD commented on May 19, 2024

check if this works:

use std::{
    io::{self, Write},
    time::Instant,
};

use windows_capture::{
    capture::GraphicsCaptureApiHandler,
    encoder::{VideoEncoder, VideoEncoderQuality, VideoEncoderType},
    frame::Frame,
    graphics_capture_api::InternalCaptureControl,
    monitor::Monitor,
    settings::{ColorFormat, CursorCaptureSettings, DrawBorderSettings, Settings},
    window::Window,
};

// This struct will be used to handle the capture events.
struct Capture {
    // The video encoder that will be used to encode the frames.
    encoder: Option<VideoEncoder>,
    // To measure the time the capture has been running
    start: Instant,
}

impl GraphicsCaptureApiHandler for Capture {
    // The type of flags used to get the values from the settings.
    type Flags = String;

    // The type of error that can occur during capture, the error will be returned from `CaptureControl` and `start` functions.
    type Error = Box<dyn std::error::Error + Send + Sync>;

    // Function that will be called to create the struct. The flags can be passed from settings.
    fn new(message: Self::Flags) -> Result<Self, Self::Error> {
        println!("Got The Flag: {message}");

        let encoder = VideoEncoder::new(
            VideoEncoderType::Mp4,
            VideoEncoderQuality::HD1080p,
            1920,
            1080,
            "video.mp4",
        )?;

        Ok(Self {
            encoder: Some(encoder),
            start: Instant::now(),
        })
    }

    // Called every time a new frame is available.
    fn on_frame_arrived(
        &mut self,
        frame: &mut Frame,
        capture_control: InternalCaptureControl,
    ) -> Result<(), Self::Error> {
        if frame.width() == 1920 && frame.height() == 1080 {
            print!(
                "\rRecording for: {} seconds",
                self.start.elapsed().as_secs()
            );
            io::stdout().flush()?;

            // Send the frame to the video encoder
            self.encoder.as_mut().unwrap().send_frame(frame)?;

            // Stop the capture after 6 seconds
            if self.start.elapsed().as_secs() >= 6 {
                // Finish the encoder and save the video.
                self.encoder.take().unwrap().finish()?;

                capture_control.stop();

                // Because there wasn't any new lines in previous prints
                println!();
            }
        } else {
            println!("Wrong resolution");
        }

        Ok(())
    }

    // Optional handler called when the capture item (usually a window) closes.
    fn on_closed(&mut self) -> Result<(), Self::Error> {
        println!("Capture Session Closed");

        Ok(())
    }
}

fn main() {
    // Gets The Foreground Window, Checkout The Docs For Other Capture Items
    let primary_monitor = Monitor::primary().expect("There is no primary monitor");
    print!(
        "Primary Monitor: {}",
        primary_monitor.name().unwrap_or_default()
    );

    let window_to_capture = Window::from_contains_name("Visual Studio Code")
        .expect("There is no window with that name");

    let settings = Settings::new(
        // Item To Captue
        window_to_capture,
        // Capture Cursor Settings
        CursorCaptureSettings::Default,
        // Draw Borders Settings
        DrawBorderSettings::Default,
        // The desired color format for the captured frame.
        ColorFormat::Rgba8,
        // Additional flags for the capture settings that will be passed to user defined `new` function.
        "Yea This Works".to_string(),
    )
    .unwrap();

    // Starts the capture and takes control of the current thread.
    // The errors from handler trait will end up here
    Capture::start(settings).expect("Screen Capture Failed");
}

I know fullscreen windows can sometimes be tricky, especially when they are larger than 1920x1080 resolution. This code checks for such cases.

from windows-capture.

yashwanth2804 avatar yashwanth2804 commented on May 19, 2024

Need a solution for this , when window is full sized unable to capture , getting wrong resolution .
so programmatically need to resize window and let it capture

please let me know if any possible solution here

Thank you

from windows-capture.

yashwanth2804 avatar yashwanth2804 commented on May 19, 2024

Thank you for the detailed response, please let us know once added the new features regarding this.

I'm expecting this library as a simple plug and play type ,
And go to library for video recording

All the best

from windows-capture.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.