【问题标题】:WPF MediaElement - play file with custom extensionWPF MediaElement - 播放具有自定义扩展名的文件
【发布时间】:2015-10-16 10:05:44
【问题描述】:

我有自定义扩展名的视频文件。它们是正确编码的 MP4 文件。当我尝试使用MediaElement 播放此类文件时,什么也没发生:

<MediaElement x:Name="UxVideo" Source="D:\111.xyz" />

但是,当我重命名文件扩展名时它可以正常工作:

<MediaElement x:Name="UxVideo" Source="D:\111.mp4" />

似乎MediaElement 使用文件扩展名来确定视频格式。是否有任何解决方法可以使 MediaElement 播放具有自定义扩展名的文件?也许还有其他控件可以实现我的需要?

我不适合在运行时重命名文件,因为其他应用程序可能会使用它。而且我不能复制文件,因为它可能很大。

更新

我已将我的文件扩展名与 Windows Media Player 相关联,并且MediaElement 开始正常工作o_O

好的,但这是我的机器。如何处理客户的 PC?

【问题讨论】:

  • MediaElement 利用较低级别的 API,这些 API 依赖于扩展、MIME 类型和特定格式处理程序之间的映射。在您的情况下,您应该以编程方式研究覆盖内容类型,跳过系统范围的设置。显然,.XYZ 之类的扩展名可能没有正确注册

标签: c# wpf video mediaelement


【解决方案1】:

我会回答这个问题,并且通过这个回答,我并不想贬低你的智慧。 每当您在代码中使用不同的文件扩展名时,您都希望确保文件扩展名与文件本身完全相同。

例子:

<MediaElement x:Name="UxVideo" Source="D:\BABYMETAL - Megitsune.Mp4" />
<MediaElement x:Name="UxVideo" Source="D:\BABYMETAL - Megitsune.XYZ" />

在图片中,除了文件扩展名之外,我有 2 个相同的文件。 对于第一个图像和代码示例,它们都反映了 mp4 并且可以正常工作。 第二个图像和代码示例都反映了 .xyz 扩展名,并且可以正常工作。

简单的答案,确保文件和代码扩展名匹配。

【讨论】:

  • 我会把这个答案留给那些不知道你需要这样做的人。
【解决方案2】:

看起来MediaElement.SetSource() 除了源之外还有一个用于指定 MIME 类型的选项。代码从 https://msdn.microsoft.com/en-us/library/windows/apps/br244338.aspx 逐字提取。

async private void SetLocalMedia()
{
    var openPicker = new Windows.Storage.Pickers.FileOpenPicker();

    openPicker.FileTypeFilter.Add(".wmv");
    openPicker.FileTypeFilter.Add(".mp4");
    openPicker.FileTypeFilter.Add(".wma");
    openPicker.FileTypeFilter.Add(".mp3");

    var file = await openPicker.PickSingleFileAsync();

    var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);

    // mediaControl is a MediaElement defined in XAML
    if (null != file)
    {
        mediaControl.SetSource(stream, file.ContentType);

        mediaControl.Play();
    }
}

【讨论】:

  • 看起来SetSource 方法仅适用于 Silverlight?
  • 不,你是对的!没有可用于 WPF 的 MediaElement 的 SetSource。我暂时将答案留在那里,但建议在任何正确答案下方投票。
  • 无论如何,感谢您的选择。也许 WPF 也有类似的东西。
【解决方案3】:

我发现的解决方法是在尝试播放视频文件之前为 Windows Media Player 注册自定义文件扩展名。所以,我们需要在应用启动时执行以下代码:

private void RegisterFileExtension(string fileName)
{
    var ext = Path.GetExtension(fileName);
    var key = Registry.CurrentUser.CreateSubKey(
        $@"Software\Microsoft\MediaPlayer\Player\Extensions\{ext}"); // C# 6.0
    key.SetValue("Permissions", 1);
    key.SetValue("Runtime", 1);
}

此代码在注册表中创建所需的键,与使用 Windows Media Player 手动打开文件时获得的键相同。

然后,MediaElement 可以正常播放视频:

<MediaElement Source="D:\111.xyz" />

【讨论】:

    【解决方案4】:

    似乎可以使用符号链接来欺骗 MediaElement。这不会产生大量的存储开销,但创建的任何链接都应该在使用后删除以保持一切整洁。

    来自https://msdn.microsoft.com/en-us/library/windows/desktop/aa365680%28v=vs.85%29.aspx

    符号链接是指向另一个文件的文件系统对象 系统对象。被指向的对象称为目标。

    符号链接对用户是透明的;链接显示正常 文件或目录,并且可以由用户或应用程序执行 以完全相同的方式。

    这里给出了如何创建符号链接的示例: https://stackoverflow.com/a/11156870/1095741 。我已修改 symbolicLinkfileName 以匹配您的问题:

    namespace ConsoleApplication
    {
        class Program
        {
            [DllImport("kernel32.dll")]
            static extern bool CreateSymbolicLink(
            string lpSymlinkFileName, string lpTargetFileName, SymbolicLink dwFlags);
    
            enum SymbolicLink
            {
                File = 0,
                Directory = 1
            }
    
            static void Main(string[] args)
            {
                string symbolicLink = @"D:\111.mp4";
                string fileName = @"D:\111.xyz";
    
                using (var writer = File.CreateText(fileName))
                {
                    writer.WriteLine("Hello World");
                }
    
                CreateSymbolicLink(symbolicLink, fileName, SymbolicLink.File);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-10-10
      • 1970-01-01
      • 1970-01-01
      • 2014-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多