robmikh / simplerecorder Goto Github PK
View Code? Open in Web Editor NEWA simple screen recorder using both the Windows.Graphics.Capture and Windows.Media.Transcoding APIs.
License: MIT License
A simple screen recorder using both the Windows.Graphics.Capture and Windows.Media.Transcoding APIs.
License: MIT License
Recording Failed
Uh-oh! Something went wrong!
0x8004003 - Object reference not set to an instance of an object
Hi, I'm trying to create a similar screen recorder uwp app for internal use. Your project given me a good demo about how to capture the screen video to a file. I'm wondering can you show me how to "pause/resume" the recording process?
Thanks!
Hello,
I have black stripes on the right and bottom. Can this be prevented in any way?
Many greetings
schabau
Hi There!
Love your app! But today it starts crashing.
As soon as I click on the Save button, the program closes and an empty file is saved where its supposed to be the video file.
Is there a log anywhere to troubleshoot?
Thanks
Looking back at this code... I'm not sure why I'm using CopyResource instead of a clear. Hell, the blank texture is made blank using a clear!
Definitely should revisit this. This pattern propagated to a few other of my projects too, without thinking (the gif encoders and ffmpeg demo come to mind).
Are you considering the possibility to record audio along with the video? Is that allowed by the APIs you use
Is it possible to record the audio output as well? Could it be added as a feature?
Microsoft store forces you to login before you can install anything.
Can you please upload the installer to Github Releases
Heya,
After the latest (28.08) update the 1280x720 resolution started to produce distorted output.
Changing the bitrate doesn't help. Other resolutions are perfectly OK, but I'm not using them on day-to-day basis (I need smallest file size and 720p is a good choice for me).
Output video for 720p/9mbps/30fps in the zip attached.
Cheers & keep up the good work!
Provide an about/info button so that users can be lead back to the source code of the sample. Consider placing some diagnostics here too.
How to save system audio with the screen capture using this sample.
Can we use this without calling GraphicsCapturePicker? What if I want create desktop streaming application, so that the client could connect to host and begin streaming whole screen without the need of calling GraphicsCapturePicker on the host? I see there is CreateForMonitor function in Win32 version of screen capture.
When I select a certain resolution and record a small window it ends up having the same resolution of the full screen, I suppose a kind of upscaling is performed. Is there a way to disable it and keep the original window resolution? On high res displays (such as 5k) this seems to affect the recording smoothness.
i am new to windows apps i am working on a screen recorder and i need some help. im using winui3.
Whats the difference between mainwindow and mainpage should i use window or Page in my mainwinodw.xaml file.
So i figured out how to get frames from this project
`public sealed partial class MainWindow : Window
{
private SizeInt32 _lastSize;
private GraphicsCaptureItem _item;
private Direct3D11CaptureFramePool _framePool;
private GraphicsCaptureSession _session;
// Non-API related members.
private CanvasDevice _canvasDevice;
private CompositionGraphicsDevice _compositionGraphicsDevice;
private Compositor _compositor;
private CompositionDrawingSurface _surface;
private CanvasBitmap _currentFrame;
private string _screenshotFilename = "test.png";
private AppWindow m_AppWindow;
public MainWindow()
{
this.InitializeComponent();
m_AppWindow = GetAppWindowForCurrentWindow();
m_AppWindow.Title = "Test";
m_AppWindow.SetIcon("C:\\Users\\name\\OneDrive\\Pictures\\zup.0849b3176cec0e8f7fe3.ico");
var titleBar = m_AppWindow.TitleBar;
titleBar.BackgroundColor = Colors.Purple;
titleBar.ForegroundColor = Colors.Purple;
titleBar.InactiveBackgroundColor = Colors.Purple;
titleBar.InactiveForegroundColor = Colors.Purple;
titleBar.ButtonForegroundColor = Colors.Orange;
titleBar.ButtonBackgroundColor = Colors.Purple;
titleBar.ButtonInactiveForegroundColor = Colors.Orange;
titleBar.ButtonInactiveBackgroundColor = Colors.Purple;
}
private AppWindow GetAppWindowForCurrentWindow()
{
IntPtr hWnd = WindowNative.GetWindowHandle(this);
WindowId wndId = Win32Interop.GetWindowIdFromWindow(hWnd);
return AppWindow.GetFromWindowId(wndId);
}
private async void myButton_Click(object sender, RoutedEventArgs e)
{
await StartCaptureAsync();
}
public async Task StartCaptureAsync()
{
// The GraphicsCapturePicker follows the same pattern the
// file pickers do.
var hWnd = await Task.Run(() => WinRT.Interop.WindowNative.GetWindowHandle(this));
var picker = new GraphicsCapturePicker();
InitializeWithWindow.Initialize(picker, hWnd);
GraphicsCaptureItem item = await picker.PickSingleItemAsync();
// The item may be null if the user dismissed the
// control without making a selection or hit Cancel.
if (item != null)
{
Debug.WriteLine(item.DisplayName);
StartCaptureInternal(item);
}
}
private void Stop(object sender, RoutedEventArgs e)
{
StopCapture();
}
public void StartCaptureInternal(GraphicsCaptureItem item)
{
_canvasDevice = new CanvasDevice();
_item = item;
_lastSize = _item.Size;
int i = 1;
_framePool = Direct3D11CaptureFramePool.Create(
_canvasDevice, // D3D device
Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, // Pixel format
60, // Number of frames
_item.Size); // Size of the buffers
Debug.WriteLine(i);
_framePool.FrameArrived += (s, a) =>
{
// The FrameArrived event is raised for every frame on the thread
// that created the Direct3D11CaptureFramePool. This means we
// don't have to do a null-check here, as we know we're the only
// one dequeueing frames in our application.
// NOTE: Disposing the frame retires it and returns
// the buffer to the pool.
using (var frame = _framePool.TryGetNextFrame())
{
ProcessFrame(frame);
i++;
Debug.WriteLine(i);
Debug.WriteLine(frame.GetType().Name);
}
};
_item.Closed += (s, a) =>
{
StopCapture();
};
_session = _framePool.CreateCaptureSession(_item);
_session.StartCapture();
}
public void StopCapture()
{
_session?.Dispose();
_framePool?.Dispose();
_item = null;
_session = null;
_framePool = null;
}
private void ProcessFrame(Direct3D11CaptureFrame frame)
{
// Resize and device-lost leverage the same function on the
// Direct3D11CaptureFramePool. Refactoring it this way avoids
// throwing in the catch block below (device creation could always
// fail) along with ensuring that resize completes successfully and
// isn’t vulnerable to device-lost.
bool needsReset = false;
bool recreateDevice = false;
if ((frame.ContentSize.Width != _lastSize.Width) ||
(frame.ContentSize.Height != _lastSize.Height))
{
needsReset = true;
_lastSize = frame.ContentSize;
}
try
{
// Take the D3D11 surface and draw it into a
// Composition surface.
// Convert our D3D11 surface into a Win2D object.
CanvasBitmap canvasBitmap = CanvasBitmap.CreateFromDirect3D11Surface(
_canvasDevice,
frame.Surface);
_currentFrame = canvasBitmap;
// Helper that handles the drawing for us.
//FillSurfaceWithBitmap(canvasBitmap);
}
// This is the device-lost convention for Win2D.
catch (Exception e) when (_canvasDevice.IsDeviceLost(e.HResult))
{
// We lost our graphics device. Recreate it and reset
// our Direct3D11CaptureFramePool.
needsReset = true;
recreateDevice = true;
}
if (needsReset)
{
ResetFramePool(frame.ContentSize, recreateDevice);
}
}
private void ResetFramePool(SizeInt32 size, bool recreateDevice)
{
do
{
try
{
if (recreateDevice)
{
_canvasDevice = new CanvasDevice();
}
_framePool.Recreate(
_canvasDevice,
Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized,
2,
size);
}
// This is the device-lost convention for Win2D.
catch (Exception e) when (_canvasDevice.IsDeviceLost(e.HResult))
{
_canvasDevice = null;
recreateDevice = true;
}
} while (_canvasDevice == null);
}`
Up till here everything is working how do i display the frames on my ui page?
This is my UI
`
<Button x:Name="CaptureButton" Grid.Row="2" Margin="300" HorizontalAlignment="Left" VerticalAlignment="Center" Click="myButton_Click" Background="Black">
<!--<FontIcon Glyph="▶" FontFamily="Segoe UI Emoji" FontSize="24" />-->
Capture
</Button>
<Button x:Name="StopButton" Grid.Row="2" Margin="300" HorizontalAlignment="Right" VerticalAlignment="Center" Click="Stop" Background="Black">
<!--<FontIcon Glyph="🛑" FontFamily="Segoe UI Emoji" FontSize="24" />-->
STOP
</Button>
<CheckBox Margin="300 100 0 0" >Check this to display mouse</CheckBox>
`
Please help me im barely understanding what im doing.
After manually installing the certificate in the "Trusted People" folder I get Error 0x800B0101 saying that it failed to open the msixbundle packet.
Add a screenshot to the readme.
Provide the ability for the application to enter compact overlay mode.
Hey, Robert.
First, thanks for all your example projects. They've been really helpful!
I can't seem to find an answer anywhere about this, so maybe you can help me. I'm considering using the MediaTranscoding APIs for screen recording/screen sharing purposes, but I'm noticing that the MP4 encoding profile doesn't appear to do any compression or frame diffing.
For example, if I use this project to record a window that has no changes occurring, the file size continues increasing linearly with the length of the video. A 10-second video with no visual changes ends up being about 20 MB.
However, if I use WMV format, the resulting file is about 1.5MB. This is about the size I'd expect from either format after diffing/compression is applied (e.g. about the size of a screenshot).
Is this expected behavior for MP4? Am I missing something?
Thanks! :)
Hi, I'm trying to build this project from source in VS 2017 on Windows 10 Build 19042.928.
However when I build the solution, the compile complaints about 2 missing definitions:
Does someone have an idea why these definitions might be missing? Is a certain directX version required?
Best
Maurice
Why aren't you giving app executable or .msixbundle in releases section of GitHub for new releases?
The rationale is this, for example I would like to record 1280x720 clip so I am also interested to have the window of the same size or maybe a multiple. One way is to maybe put a button and offer a resize of the target window to the desired resolution, but I realize it might be tricky in certain aspects like e.g. permissions and UWP app sandbox. So maybe we can at least see current width and height of what will be scaled to target 1280x720 during recording and let user manually size the window to desired matching. This also might apply to aspect ratio (if the app is doing letterboxing in the transcoding session, probably it does not). Or, alternatively maybe one another and good way is to just keep the resolution of original window assuming it won't change or just doing scaling to what we started with.
When I select record an app and I minimize it during the recording, once I go back to Simple Screen Recorder I cannot stop it and pressing the button lets me choose whether to record the screen or an app
Update the screenshot for version 2.
The last missing thing to make this software perfect. Recording the system audio of Windows and maybe a microphone.
For some reasons if I use Unigram the app won't record anything, both using screen capture and app one
"Use source size" option causes "cannot find an encoder MFT that accepts the user preferred output type" exception.
Clicking "start recording" after selecting the "use source size" resolution option causes the recording to fail.
Title: Recording failed
Description: Uh-oh! Something went wrong! 0xC00DA412 - Cannot find an encoder MFT that accepts the user preferred output type. (Exception from HRESULT: 0xC00DA412)
Monitor resolution: 3840x2160 (just a single monitor)
OS: Windows 11 22000.318
Using latest version available in Microsoft Store (as of writing).
Let me know if you need any additional information.
How to capture all screens automatically?
There seems to be no api under the Windows.Graphics.Capture
namespace.
GraphicsCapturePicker
class, which requires the user to manually select them one by one, we want to simplify this step.
I see that there seems to be a relevant api here: https://github.com/robmikh/Win32CaptureSample/blob/master/Win32CaptureSample/util/capture.desktop.interop.h
Hi Rob,
I am wondering if you can guide me to save chunk of stream (let's say each chunk 5 secs). Very simple way would be dispose encoder object at each 5 secs and re-create encoder with new file stream. I am a bit concerned overhead. I wonder if there is way to interrupt PrepareTranscodeResult.
Due to a bug in build 17763, buffers from the capture API cannot be directly handed to the Transcoding API. There's currently a workaround to copy the buffer, but I don't think it's correctly synchronized. When the next release ships, remove the workaround and bump the minimum required build.
Hi Rob,
It's really sad that Microsoft time and again doesn't believe in its own projects. You have an awesome lib (win2d), yet you use sharpDX.
Frankly, I would not have minded, but nothing works -- I'm trying to capture Thunderbird or notepad++ (just for testing, of course), and the end result is some part of the title. It seems to work fine 1 out of 10 times. This is completely unuseable code to me.
I can't bear to learn yet another library just for this.
Why the f*** doesn't it record audio 🤷♂️
This is more a feature request than an issue but it would be really great to have an option to record sound too..
P.S. I know it pops up few times already but was curious about the status.
Not all SKUs have screen capture enabled (e.g. Xbox, Hololens, etc). Check IsSupported to make sure we don’t try to call out to the rest of the API.
Hi Rob,
I just found this recorder sample app and thought it was a promising solution for what I'm trying to do. I want to be able to "record" my application and stream the recorded frames over NDI to a Tricaster hardware. All I need for that is to have a bitmap (or just raw pixels I guess) of each frame of the recording, in real-time (near 60 FPS if possible).
This sample is able to record a video of my app at 60 FPS easily, but I struggle to convert it to my use-case where I need the individual frames (as bitmaps / pixels) in real-time.
Would it be possible to grab each frame in real-time and somehow get the pixels in some format that I can use? I am not interested in storing a video, or even an image file, I just need to have the pixels so I can stream them over NDI.
Move to a global D3D device, we end up creating a new one when going back to the MainPage.
The application should either end the current recording or properly recover from losing the D3D device.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.