捕获每个 WPF MediaElement 帧

发布于 2024-09-05 20:16:44 字数 153 浏览 8 评论 0原文

有没有办法捕获每个 WPF MediaElement 帧?就像在每个渲染帧触发并允许我访问它的事件一样。如果 MediaElement 不提供此类功能,如何实现或我可以使用其他哪些控件?顺便说一句,是否有这样的控件或方法可以允许通过帧捕获进行离屏快速渲染媒体剪辑? (这样我就可以尽快处理帧)

Is there a way to capture each WPF MediaElement frame? Like an event that fires at each rendered frame and allows me to access it. If MediaElement does not provide such functionality, how could it be implemented or what other control could I use? On a side note, is there such a control or method that would allow for off-screen fast rendering of media clips with frame capture? (so I could process frames as fast as possible)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

深海蓝天 2024-09-12 20:16:44

尝试我的 WPF MediaKit 项目。允许您使用 Media 在 WPF 中执行几乎所有操作。尝试一下 MediaDetector.cs,它允许您从媒体中的任何时间提取帧。它有点问题,因为我从来没有花很多时间在上面,但应该可以满足你的需要。

Try out my WPF MediaKit project. Allows you to do pretty much anything in WPF with Media. Try out the MediaDetector.cs, it allows you to extract out frames from any time in the media. It's a little buggy as I've never put a lot of time in it, but should work for what you need.

野稚 2024-09-12 20:16:44

没有内置的WPF方式:

  • MediaElement没有这个能力。
  • BitmapDecoder 有 API 来请求此操作,但未实现使用 BitmapDecoder 从任意媒体中提取帧:它只能从一些动画位图格式(如 .gif)中提取帧。

我能够使用 DirectShow 从 .mpg、.wmv、.mov、.flv、.avi 和其他电影格式获取帧图像。我使用 DirectShow 的 COM 图形生成器接口构建了一个过滤器图形。生成的过滤器图对影片进行了解码,并将其连接到用 C# 编写的自定义渲染器过滤器。我的自定义过滤器接收帧数据并将其转换为 BitmapSource 对象以使用 BitmapSource.Create 进行显示。

DirectShow 解决方案表现得相当好,托管到非托管的转换没什么大不了的,但花了一段时间才弄清楚 DirectShow 图形构建的细节。

There is no built-in WPF way:

  • MediaElement does not have this ability.
  • BitmapDecoder has the API to request this but using BitmapDecoder to extract frames from arbitrary media is not implemented: It can only extract frames from a few animated bitmap formats like .gif.

I was able to get frame images from .mpg, .wmv, .mov, .flv, .avi and other movie formats using DirectShow. I constructed a filter graph using DirectShow's COM graph builder interfaces. The resulting filter graph decoded the movie and connected it to a custom renderer filter written in C#. My custom filter received the frame data and converted it into BitmapSource objects for display using BitmapSource.Create.

The DirectShow solution performed quite well, and the managed to unmanaged transition was no big deal, but it took a while to figure out the details of the DirectShow graph building.

美人骨 2024-09-12 20:16:44

如果你发挥你的想象力,也许这个片段可以给你一些想法:

MediaPlayer player = new MediaPlayer();
player.Open(new Uri(_inputFilename));
player.ScrubbingEnabled = true;
DrawingVisual dv = new DrawingVisual();
for (int i = 0; i < session.FramesList.Count; i++)
{
    Frame f = session.FramesList[i];
    player.Position = new TimeSpan((long)(f.Time * 10000000));
    using (DrawingContext dc = dv.RenderOpen())
    {
        dc.DrawVideo(player, new Rect(0, 0, 1024, 576));
    }
    RenderTargetBitmap bmp = new RenderTargetBitmap(1024, 576, 96, 96, PixelFormats.Pbgra32);
    bmp.Render(dv);
    f.Thumbnail = bmp.GetAsFrozen() as ImageSource;
    framesListView.Dispatcher.Invoke(() => FramesList.Add(f));
}

If you use your imagination perhaps this snippet can give you some ideas:

MediaPlayer player = new MediaPlayer();
player.Open(new Uri(_inputFilename));
player.ScrubbingEnabled = true;
DrawingVisual dv = new DrawingVisual();
for (int i = 0; i < session.FramesList.Count; i++)
{
    Frame f = session.FramesList[i];
    player.Position = new TimeSpan((long)(f.Time * 10000000));
    using (DrawingContext dc = dv.RenderOpen())
    {
        dc.DrawVideo(player, new Rect(0, 0, 1024, 576));
    }
    RenderTargetBitmap bmp = new RenderTargetBitmap(1024, 576, 96, 96, PixelFormats.Pbgra32);
    bmp.Render(dv);
    f.Thumbnail = bmp.GetAsFrozen() as ImageSource;
    framesListView.Dispatcher.Invoke(() => FramesList.Add(f));
}
寄与心 2024-09-12 20:16:44

您可以尝试此方法来输出任何 UI 元素,包括 WPF 中的 MediaElement

 public static void ConvertUiElementToBitmap(UIElement elt, string path)
        {
            double h = elt.RenderSize.Height;
            double w = elt.RenderSize.Width;
            if (h > 0)
            {
                PresentationSource source = PresentationSource.FromVisual(elt);
                RenderTargetBitmap rtb = new RenderTargetBitmap((int)w, (int)h, 96, 96, PixelFormats.Default);

                VisualBrush sourceBrush = new VisualBrush(elt);
                DrawingVisual drawingVisual = new DrawingVisual();
                DrawingContext drawingContext = drawingVisual.RenderOpen();
                using (drawingContext)
                {
                    drawingContext.DrawRectangle(sourceBrush, null, new Rect(new Point(0, 0),
                          new Point(w, h)));
                }
                rtb.Render(drawingVisual);

                // return rtb;
                var encoder = new PngBitmapEncoder();
                var outputFrame = BitmapFrame.Create(rtb);
                encoder.Frames.Add(outputFrame);

                using (var file = System.IO.File.OpenWrite(path))
                {
                    encoder.Save(file);
                }
            }
        }

you can try this method to output any UI Element including the MediaElement in WPF

 public static void ConvertUiElementToBitmap(UIElement elt, string path)
        {
            double h = elt.RenderSize.Height;
            double w = elt.RenderSize.Width;
            if (h > 0)
            {
                PresentationSource source = PresentationSource.FromVisual(elt);
                RenderTargetBitmap rtb = new RenderTargetBitmap((int)w, (int)h, 96, 96, PixelFormats.Default);

                VisualBrush sourceBrush = new VisualBrush(elt);
                DrawingVisual drawingVisual = new DrawingVisual();
                DrawingContext drawingContext = drawingVisual.RenderOpen();
                using (drawingContext)
                {
                    drawingContext.DrawRectangle(sourceBrush, null, new Rect(new Point(0, 0),
                          new Point(w, h)));
                }
                rtb.Render(drawingVisual);

                // return rtb;
                var encoder = new PngBitmapEncoder();
                var outputFrame = BitmapFrame.Create(rtb);
                encoder.Frames.Add(outputFrame);

                using (var file = System.IO.File.OpenWrite(path))
                {
                    encoder.Save(file);
                }
            }
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文