从shell元数据属性中获取变形视频的显示大小

时间:2012-11-13 14:35:27

标签: c# video windows-shell windows-api-code-pack m4v

我正在使用Microsoft.WindowsAPICodePack.Shell.ShellFile从文件路径中获取视频大小(宽度和高度)。

public Size GetVideoSize(string videoFullPath)
{
    if (File.Exists(videoFullPath))
    {
        ShellFile shellFile = ShellFile.FromFilePath(videoFullPath);

        int videoWidth = (int)shellFile.Properties.System.Video.FrameWidth.Value;
        int videoHeight = (int)shellFile.Properties.System.Video.FrameHeight.Value;

        return new Size(videoWidth, videoHeight);
    }
    return Size.Empty;
}

问题是此方法无法检索m4v文件的正确大小。你有什么建议吗?我可以使用什么来获得实际的宽度/高度?

示例:我有一个m4v视频,其实际大小为856x480

  • 如果我在Windows资源管理器中查看文件的属性,则大小为 720x480(错误)
  • 如果我在视频播放器中打开视频,视频会在 正确的尺寸,即使视频细节仍然显示大小为720x480
  • 如果我在WPF中的MediaElement控件中加载视频,我会通过mediaElement.NaturalVideoWidth, mediaElement.NaturalVideoHeight获得正确的大小,但问题是我需要在没有任何WPF的类库中获取大小引用。

1 个答案:

答案 0 :(得分:1)

这里的关键提示是856/480 = 1.78,大约等于16/9 = 1.77,这是宽屏视频的常见宽高比。具有比率为1:1.33或1:1.5(例如640x480或720x480)的像素分辨率的视频并不罕见,但其意图显示为拉伸到更宽的宽高比,1:1.77(例如856x480)。这称为Anamorphic Widescreen。因此,720x480可能是视频的正确分辨率,但不是正确的显示尺寸

在窗口中显示变形宽屏时,视频播放器通常只保持相同的高度并拉伸宽度以获得正确的显示宽高比。如果是全屏,则可以拉伸宽度和高度,但不能使用相同的因子,因此显示宽高比正确,视频完全符合屏幕分辨率。

要获得显示尺寸(看起来像你想要的那样),我们需要宽高比。幸运的是,您用于获取帧宽和高度的metadata properties API也具有宽高比属性,即System.Video.HorizontalAspectRatioSystem.Video.VerticalAspectRatio。虽然这是未记录的,但这些似乎是指像素长宽比,而不是图像显示宽高比。您想要变形视频的内容如下:

int videoWidth = (int)shellFile.Properties.System.Video.FrameWidth.Value;
int videoHeight = (int)shellFile.Properties.System.Video.FrameHeight.Value;
int horizontalAspect = (int)shellFile.Properties.System.Video.HorizontalAspectRatio.Value;
int verticalAspect = (int)shellFile.Properties.System.Video.VerticalAspectRatio.Value;
int displayWidth = videoWidth * horizontalAspect / verticalAspect;
int displayHeight = videoHeight;

我期望你的情况是horizo​​ntalAspect = 53和verticalAspect = 45(或其他值产生相似的比率)。

显示分辨率可能会四舍五入为16或8像素的精确倍数,因此您可能还需要执行以下操作:

int roundingMultiple = 8;
int displayWidth = videoWidth * horizontalAspect / verticalAspect;
displayWidth = ((displayWidth - 1) / roundingMultiple + 1) * roundingMultiple;

这不是特定于mkv文件;任何容器格式的任何变形视频文件都必须处理相同的内容。

编辑:更改了上面的代码,以反映horizo​​ntalAspect / verticalAspect显然是 pixel 宽高比的事实。