使用 MediaElement 从 Stream 播放视频

Posted

技术标签:

【中文标题】使用 MediaElement 从 Stream 播放视频【英文标题】:Using MediaElement to play video from Stream 【发布时间】:2011-10-30 08:41:52 【问题描述】:

是否可以使用 WPF MediaElement 从 System.IO.Stream 对象播放流视频?正在从存储媒体文件的 WCF 服务中检索 Stream 对象。

【问题讨论】:

【参考方案1】:

在任何人浪费时间自己发现这一点之前:不可能在 WPF 应用程序中托管 Silverlight MediaElement。原因是它是出现在 PresentationFramework.dll(WPF 不可避免)和 System.Windows.dll(Silverlight 版本)中具有相同名称和相同命名空间但类型不同的众多类型之一。 (有人应该解释为什么我们有微软的命名空间!)

【讨论】:

这是真的。不幸的是,我不得不以艰难的方式找到这一点。 :( 我知道这是一个多年前的答案,但“在同一个命名空间中具有相同名称的多个不同类型”不是引用别名存在的原因吗? 始终可以创建 Silverlight 网站并在其中使用 MediaElement,并在 WPF 应用程序中将带有源的 WebBrowser 控件添加到该 Silverlight 网站并完成。 是的 @Damien_The_Unbeliever 我最初的想法 - 但这取决于它如何发挥作用,而且我见过类似技巧不可能的情况。尽管我会说这仍然“可能”是可能的,但需要一些黑客攻击。不过没试过,好像有点麻烦【参考方案2】:

可能为时已晚,如果您仍在寻找答案,希望这可能会有所帮助。

是的,您可以使用 WPF 媒体元素从内存流中播放视频。

我使用了一个名为 boxed app 的第三方组件,感谢 BoxedApp 一百万 - http://www.boxedapp.com/boxedappsdk/

我必须稍微更新代码以使其适用于 byte[]。将以下构造函数从 BoxedApp 复制到 CustomFileStream 类

public CustomFileStream(byte[] data)

    _Stream = new MemoryStream(data);
    _Length = _Stream.Length;
    _data = data;
    _Offset = 0;

创建一个 wpf 应用程序并添加一个媒体元素和一个按钮并复制以下代码

public MainWindow()

    BoxedAppSDK.NativeMethods.BoxedAppSDK_Init();

    InitializeComponent();


private void button2_Click(object sender, RoutedEventArgs e)

    var MyFileStream = new CustomFileStream(File.ReadAllBytes(@"wildlife.wmv"));

    IntPtr ptr = BoxedAppSDK.NativeMethods.BoxedAppSDK_CreateVirtualFileBasedOnIStream(
            @"1.wmv",
            BoxedAppSDK.NativeMethods.EFileAccess.GenericWrite,
            BoxedAppSDK.NativeMethods.EFileShare.Read,
            IntPtr.Zero,
            BoxedAppSDK.NativeMethods.ECreationDisposition.New,
            BoxedAppSDK.NativeMethods.EFileAttributes.Normal,
            IntPtr.Zero,
            MyFileStream);

    using (new SafeFileHandle(ptr, true))
    
        mediaElement1.Source = new Uri(Path.GetFullPath("1.wmv"));
        mediaElement1.LoadedBehavior = MediaState.Manual;
        mediaElement1.Play();
    

对于盒装应用,请按照示例进行操作,仅此而已..您在一个快乐的世界中...

QT Player 也是如此。

【讨论】:

【参考方案3】:

如果您可以让 WCF 通过 http-URL (GET) 传递媒体对象,那么您只需将该 URL 分配给 MediaElement.Source 属性 - 请参阅 http://msdn.microsoft.com/en-us/library/system.windows.controls.mediaelement.source.aspx。

对于此类 URL 不可用/可能的情况:

目前无法分配流 - 尽管有一些技巧可以做到这一点,有关基于 DirectShow 的示例,请参阅 http://social.msdn.microsoft.com/forums/en-US/wpf/thread/6191ef1a-0010-4294-a5b4-451bbadca33a/ 和 http://jmorrill.hjtcentral.com/Home/tabid/428/EntryId/15/WPF-Hackery-Part-I.aspx。

另一种选择是以某种方式托管Silverlight MediaElement 并使用SetSource 方法,该方法可以获取流并播放它...参见http://silverlightviewport.codeplex.com/SourceControl/list/changesets 和http://msdn.microsoft.com/en-us/library/cc190669%28v=vs.95%29.aspx

【讨论】:

【参考方案4】:

我知道这不是您要求的,但您可以在 WPF 的窗口内托管 VLC ActiveX 组件,然后使用该 VLC 控件连接到流并显示流。这就是我通过 WPF 进行流式处理的方式。

编辑:this page has an example of how to host an ActiveX control inside WPF

【讨论】:

我可以看到一个 WPF 应用程序的示例,该应用程序将 VLC 作为 ActiveX 组件运行吗?在我真正开始之前,我想看看它的外观以及运行它所涉及的内容。 嗨 Stuart,你能把你的例子用 VLC 贴在某个地方,让我看看。谢谢。【参考方案5】:

由于 WPF mediaelement 在内部使用 windows 媒体播放器。如果您将媒体播放器的缓冲区设置从默认缓冲区设置更改为自定义。打开 windows 媒体播放器  工具  选项  性能。

当您选择“缓冲区”选项并将“内容秒数”设置为 2 时,媒体播放器下将添加以下注册表值。 HKEY_CURRENT_USER\Software\Microsoft\MediaPlayer\Preferences 使用默认缓冲时间=0 CustomBufferTime=2000

您可以使用 dotnet 注册表类进行更改。 参考这个链接: https://social.msdn.microsoft.com/Forums/vstudio/en-US/1b4b8fb9-ff8f-4861-8e99-4a7a4fc75596/setting-windows-media-player-properties-in-wpf?forum=wpf#ac879a7f-37bc-4ccc-854d-ab6e047086e5

【讨论】:

以上是关于使用 MediaElement 从 Stream 播放视频的主要内容,如果未能解决你的问题,请参考以下文章

使用 MediaElement 在 Windows Phone 8 上流式传输音频

ViewModel 中的 MediaElement.play()

如何通过 MediaElement 从库中播放文件?

如何使用 TimedTextSource 在 MediaElement 上查看(srt)字幕

在 MVVM 中,从 Model 或 ViewModel 播放媒体文件?

WPF 媒体播放器(MediaElement)使用实例(转)