Nic*_*rfe 5 c# video-capture uwp mediacapture
我正在尝试在使用 MediaFrameReader 时录制相机视频。对于我的应用程序,我需要 MediaFrameReader 实例来单独处理每个帧。我尝试另外应用 LowLagMediaRecording 来简单地将相机流保存到文件中,但似乎不能同时使用这两种方法。这意味着我只能使用 MediaFrameReader 来访问 Frame_Arrived 方法中的每个帧。
我尝试了多种方法,并找到了两种使用 MediaComposition 类创建 MediaClip 对象的可行解决方案。您可以将每个帧保存为 JPEG 文件,然后将所有图像最终渲染为视频文件。这个过程非常慢,因为您需要不断访问硬盘。或者,您可以从帧的 Direct3DSurface 创建 MediaStreamSample 对象。通过这种方式,您可以将数据保存在 RAM 中(首先保存在 GPU RAM 中,如果已满,则保存在 RAM 中),而不是硬盘驱动器中,理论上速度要快得多。问题在于,调用 MediaComposition 类的 RenderToFileAsync 方法需要所有 MediaClip 已添加到内部列表中。这会导致在已经很短的录制时间后超出 RAM。在收集大约 5 分钟的数据后,Windows 已经创建了一个 70GB 的交换文件,这违背了当初选择此路径的原因。
我还尝试了第三方库OpenCvSharp将处理后的帧保存为视频。我之前在 python 中已经这样做过,没有任何问题。但在 UWP 中,如果没有 StorageFile 对象,我无法与文件系统交互。因此,当我尝试将渲染的视频保存到文件系统时,我从 OpenCvSharp 得到的只是 UnauthorizedAccessException。
所以,总结一下:我需要的是一种在数据仍在输入时将相机帧的数据渲染到视频的方法,这样我就可以在处理后处理每一帧,就像 python OpenCV 实现一样。我非常感谢每一个提示。以下是我的代码的一部分,可以更好地理解上下文:
private void ColorFrameArrived(MediaFrameReader sender, MediaFrameArrivedEventArgs args)
{
MediaFrameReference colorFrame = sender.TryAcquireLatestFrame();
if (colorFrame != null)
{
if (currentMode == StreamingMode)
{
colorRenderer.Draw(colorFrame, true);
}
if (currentMode == RecordingMode)
{
MediaStreamSample sample = MediaStreamSample.CreateFromDirect3D11Surface(colorFrame.VideoMediaFrame.Direct3DSurface, new TimeSpan(0, 0, 0, 0, 33));
ColorComposition.Clips.Add(MediaClip.CreateFromSurface(sample.Direct3D11Surface, new TimeSpan(0, 0, 0, 0, 33)));
}
}
}
private async Task CreateVideo(MediaComposition composition, string outputFileName)
{
try
{
await mediaFrameReaderColor.StopAsync();
mediaFrameReaderColor.FrameArrived -= ColorFrameArrived;
mediaFrameReaderColor.Dispose();
StorageFolder folder = await documentsFolder.GetFolderAsync(directory);
StorageFile vid = await folder.CreateFileAsync(outputFileName + ".mp4", CreationCollisionOption.GenerateUniqueName);
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
await composition.RenderToFileAsync(vid, MediaTrimmingPreference.Precise);
stopwatch.Stop();
Debug.WriteLine("Video rendered: " + stopwatch.ElapsedMilliseconds);
composition.Clips.Clear();
composition = null;
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试在使用 MediaFrameReader 时录制相机视频。对于我的应用程序,我需要 MediaFrameReader 实例来单独处理每个帧。
请创建自定义视频效果并将其添加到 MediaCapture 对象中以实现您的要求。使用自定义视频效果将允许我们在 MediaCapture 对象的上下文中处理帧,而无需使用 MediaFrameReader,这样您提到的 MediaFrameReader 的所有限制都消失了。
此外,它还具有许多内置效果,可以让我们分析相机帧,有关更多信息,请查看以下文章:
#MediaCapture.AddVideoEffectAsync
https://learn.microsoft.com/en-us/uwp/api/windows.media.capture.mediacapture.addvideoeffectasync。
#自定义视频效果
https://learn.microsoft.com/en-us/windows/uwp/audio-video-camera/custom-video-effects。
#分析相机帧的效果
https://learn.microsoft.com/en-us/windows/uwp/audio-video-camera/scene-analysis-for-media-capture。
谢谢。