如何高效地从RenderTargetBitmap创建一个MediaClip?

8

我正在尝试使用C#在UWP应用程序中捕获XAML网格的视频。

我的方法:

1.使用RenderTargetBitmap通过renderTargetBitmap.RenderAsync拍摄屏幕截图。

2.将数据转换为字节数组。

3.使用BitmapEncoder创建一个图像文件,并将其保存在磁盘上。

4.使用MediaClip.CreateFromImageFileAsync从该图像创建媒体剪辑。

5.将剪辑添加到MediaComposition中,使用composition.Clips.Add(clip)

6.使用composition.RenderToFileAsync(video);将其保存为视频。

现在这个方法是可行的。 但是,正如你所想象的那样,每次截屏都要保存图像并读取它们来创建剪辑,这会很慢,帧速率也很低。

我正在寻找一些避免每次截屏都要进行磁盘操作的解决方案。能够将RenderTargetBitmap (或IBufferbyte[]) 转换为 MediaClip,而不需要使用磁盘,或者采用不同的方法来保存视频。

我正在开发Hololens的UWP应用程序。


这个怎么样?https://dev59.com/3qzka4cB1Zd3GeqP8WsI? - kkica
您可以查看屏幕截图 - 但是请注意,您必须运行W10的ProEnterprise版本。 - Romasz
只是一个猜测,但是IStorageFile不是一个文件,它是一个接口。也许你可以实现该接口(在这种情况下,可能只有一些属性和方法会被调用者方法使用)来支持“虚拟”文件。 - Simon Mourier
那个网格里有什么内容?也许只跟踪网格中的元素(位置和大小的变化),然后使用该信息创建视频,这是否可能? - Furkan Kambay
为什么不将您的RenderTargetBitmap转换为WriteableBitmap呢?当您收集到每个WriteableBitmap后,可以将它们转换为MediaClip以存储它们。 - TheTanic
显示剩余2条评论
2个回答

3
尝试这样做:
与您之前所做的相同。
using (var soft = SoftwareBitmap.CreateCopyFromBuffer(pixels, BitmapPixelFormat.Bgra8, renderTargetBitmap.PixelWidth, renderTargetBitmap.PixelHeight, BitmapAlphaMode.Premultiplied))
{
   CanvasBitmap canvas = CanvasBitmap.CreateFromSoftwareBitmap(CanvasDevice.GetSharedDevice(), soft); 

   MediaClip m = MediaClip.CreateFromSurface(canvas, DateTime.Now - previousFrame); 
   composition.Clips.Add(m); 
}

记得捕获设备丢失的异常并创建新设备


2
这个答案是你能得到的最好的,但是值得一提的是,使用RenderTargetBitmap不会得到实时支持 - 它对此太慢了。 - Johnny Westlake

1

如果您在尝试@Mediarea的答案时遇到异常,请尝试以下方法:

CanvasRenderTarget rendertarget = null;
using (CanvasBitmap canvas = CanvasBitmap.CreateFromBytes(CanvasDevice.GetSharedDevice(), pixel_buffer, renderTargetBitmap.PixelWidth, renderTargetBitmap.PixelHeight, Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized))
{
     rendertarget = new CanvasRenderTarget(CanvasDevice.GetSharedDevice(), canvas.SizeInPixels.Width, canvas.SizeInPixels.Height, 96);
     using (CanvasDrawingSession ds = rendertarget.CreateDrawingSession())
     {
         ds.Clear(Colors.Black);
         ds.DrawImage(canvas);
     }
}

MediaClip m = MediaClip.CreateFromSurface(rendertarget, TimeSpan.FromMilliseconds(80));
mc.Clips.Add(m);

如果您使用此方法,错误“Stream is not in a state to handle the request” 将消失。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接