2

有没有办法捕获每个 WPF MediaElement 帧?就像在每个渲染帧上触发并允许我访问它的事件一样。如果 MediaElement 不提供这样的功能,它如何实现或者我可以使用什么其他控件?附带说明一下,是否有这样的控件或方法可以通过帧捕获实现媒体剪辑的离屏快速渲染?(所以我可以尽快处理帧)

4

4 回答 4

3

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

于 2010-06-11T22:49:58.883 回答
1

没有内置的 WPF 方式:

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

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

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

于 2010-06-11T22:06:16.717 回答
0

您可以尝试使用此方法输出任何 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);
                }
            }
        }
于 2021-01-23T05:29:37.947 回答
0

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

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));
}
于 2019-06-07T16:56:50.433 回答