当前位置: 首页 > article >正文

Android用ExoPlayer获取视频正确的尺寸

最近在实现视频预加载功能,遇到了较多的疑问未解决,但机缘巧合解决了困扰我很久的某些视频

展示异常的问题(被压扁),如下图

我的实现方法:

@Override
        public void onVideoSizeChanged(VideoSize videoSize) { 
            currentVideoWidth = videoSize.width;
            currentVideoHeight = videoSize.height;
            //根据视频的宽高比决定改视频是竖屏还是横屏,然后再根据手机的分辨率对视频进行放大/缩小
            //大部分视频只有处理没有问题,近期采购了其他供应商的视频,发现对某些视频会存在压缩
        }

百度/Google啥都问了一遍,没发现什么可借鉴的方法,直到现在deepseek/豆包啥的AI上线,问他们比问百度精准很多,最后是deepseek给我解惑了,如下:

问:pixelWidthHeightRatio等于1.0 等于0.31640625 有什么区别
嗯,用户问到了pixelWidthHeightRatio等于1.0和0.31640625有什么区别。我需要先回顾一下之前讨论的内容,确保自己对这个参数的理解正确。之前讨论过ExoPlayer中视频尺寸的问题,特别是旋转和像素宽高比的影响。用户现在可能在处理视频显示尺寸的问题,特别是在获取到的视频宽高和实际下载的尺寸不符时,遇到的困惑。
首先,pixelWidthHeightRatio(PAR,像素宽高比)是视频元数据中的一个参数,它表示像素的宽高比。通常,如果PAR是1.0,意味着每个像素是正方形的,宽高比为1:1。而如果PAR不是1.0,比如0.31640625,说明像素不是正方形的,可能是长方形,这会影响视频的显示尺寸。
接下来,我需要解释这两种情况的具体区别。当PAR是1.0时,视频的显示宽度就是存储宽度,不需要调整。而当PAR是其他数值时,比如0.31640625,显示宽度需要根据PAR进行调整。例如,视频的存储宽度是607,PAR是0.31640625,那么实际显示宽度会是607 * 0.31640625 ≈ 192,这可能与用户之前提到的1920x1080有关联吗?或者可能是用户遇到了这样的情况,导致显示尺寸与存储尺寸不一致。
这里需要进一步分析用户可能遇到的具体情况。用户之前提到ExoPlayer报告的尺寸是1920x1080,但下载下来的视频是607x1080,需要确认PAR是否是0.31640625,这样计算出来的显示宽度为607 * 0.31640625 ≈ 192,但这似乎与1920相差较大,所以可能存在其他因素,比如旋转或不同的PAR值。
或者,用户提到的0.31640625可能是一个具体的例子,需要解释这个数值的来源和计算方式。例如,如果视频的显示宽高比(DAR)是16:9,存储尺寸是607x1080,那么DAR = (SAR宽 / SAR高) * (存储宽 / 存储高)。这里可能需要用PAR来计算实际的显示尺寸。
另外,用户可能需要了解如何正确处理PAR值,以确保在ExoPlayer中正确显示视频尺寸。例如,在onVideoSizeChanged回调中,pixelWidthHeightRatio参数用于调整实际显示的宽度,这样显示宽度 = width * pixelWidthHeightRatio,而显示高度保持为height,或者需要考虑旋转的情况。
需要确保用户理解PAR的作用,以及如何应用它来正确计算视频的显示尺寸。如果用户仍然遇到尺寸不符的问题,可能需要进一步检查视频的元数据,是否存在旋转或其他因素,或者是否在代码中没有正确应用PAR值。
可能用户在实际操作中发现pixelWidthHeightRatio的值有时是1.0,有时是0.31640625,导致显示尺寸不同,需要解释这两者的区别以及对应的处理方式。例如,当PAR为0.31640625时,如何调整显示宽高,以避免尺寸错误。
总结来说,用户的问题核心在于理解不同PAR值对视频显示尺寸的影响,以及如何在代码中正确处理这些情况,确保显示的尺寸与预期一致。需要分步骤解释这两种PAR值的区别,并提供代码示例或计算公式,帮助用户进行正确的调整。

在 ExoPlayer 的 onVideoSizeChanged 方法中,pixelWidthHeightRatio(PAR,像素宽高比)直接影响视频的最终显示尺寸。以下是 pixelWidthHeightRatio = 1.0 和 pixelWidthHeightRatio = 0.31640625 的详细区别及实际影响:

1. pixelWidthHeightRatio = 1.0

1.含义:像素是正方形的(宽高比为 1:1)。
2.显示尺寸计算:
显示宽度 = 存储宽度(width) × PAR = width × 1.0
显示高度 = 存储高度(height)
即显示尺寸与存储尺寸一致。
3.示例:
若视频存储尺寸为 607×1080,且 PAR=1.0,则显示尺寸为 607×1080。


2. pixelWidthHeightRatio = 0.31640625

1.含义:像素是长方形的(宽高比非 1:1),具体为宽:高 = 0.31640625:1(即宽度更窄,像素被“压扁”)。
2.显示尺寸计算:
显示宽度 = 存储宽度(width) × PAR = width × 0.31640625
显示高度 = 存储高度(height)
显示宽度会被压缩到原始宽度的约 31.6%。
3.示例:
若视频存储尺寸为 607×1080,且 PAR=0.31640625,则显示宽度为:
607 × 0.31640625 ≈ 192,显示尺寸为 192×1080。


3. 为什么需要 PAR?
视频的存储尺寸(stored resolution)和显示尺寸(display resolution)可能不一致,原因包括:

1.历史兼容性:早期视频编码为节省带宽,使用非正方形像素(如 PAL 标清视频的 PAR=59:54)。
2.动态适配:某些编码器会调整 PAR 以匹配目标显示比例(如 16:9)。
4. 结合旋转(Rotation)的场景
如果视频包含旋转元数据(如 90°),onVideoSizeChanged 的 width 和 height 会互换,此时需先处理旋转,再应用 PAR:

override fun onVideoSizeChanged(width: Int, height: Int, unappliedRotationDegrees: Int, pixelWidthHeightRatio: Float) {
    // 处理旋转(交换宽高)
    val rotatedWidth = if (unappliedRotationDegrees % 180 == 90) height else width
    val rotatedHeight = if (unappliedRotationDegrees % 180 == 90) width else height

    // 应用 PAR 计算显示尺寸
    val displayWidth = rotatedWidth * pixelWidthHeightRatio
    val displayHeight = rotatedHeight

    Log.d("Video", "显示尺寸: ${displayWidth.toInt()}x$displayHeight")
}


5. 实际场景示例
假设视频元数据为:

.存储尺寸:607×1080
.旋转角度:90°
.PAR:0.31640625


1.处理旋转:
旋转后尺寸变为 1080×607(宽高交换)。
2.应用 PAR:
显示宽度 = 1080 × 0.31640625 ≈ 342,显示高度 = 607
最终显示尺寸为 342×607。


6. 对比总结

参数pixelWidthHeightRatio = 1.0pixelWidthHeightRatio = 0.31640625
像素形状正方形长方形(宽度被压缩)
显示宽度存储宽度 × 1.0(无缩放)存储宽度 × 0.31640625
典型场景现代标准视频(如 1080p)老式编码视频或特殊比例适配
对显示尺寸的影响显著缩小宽度

7. 如何验证 PAR?
使用 ffprobe 检查视频的宽高比信息:
ffprobe -v error -show_entries stream=sample_aspect_ratio,display_aspect_ratio -of default=noprint_wrappers=1 input.mp4


.sample_aspect_ratio(SAR):即 pixelWidthHeightRatio(如 3164:10000 ≈ 0.3164)。
.display_aspect_ratio(DAR):最终显示宽高比,计算方式为:
DAR = (SAR宽 × 存储宽) / (SAR高 × 存储高)。
8. 代码中正确处理
在 ExoPlayer 中,始终需要结合 unappliedRotationDegrees 和 pixelWidthHeightRatio 计算最终尺寸:

val displayWidth = rotatedWidth * pixelWidthHeightRatio
val displayAspectRatio = displayWidth / displayHeight

// 用于设置 SurfaceView 的宽高比例
surfaceView.setAspectRatio(displayAspectRatio)


通过理解 pixelWidthHeightRatio 的作用,可以避免因像素宽高比和旋转导致的显示尺寸错误。

总结:

1.从onVideoSizeChanged中获取视频相关信息:宽&高&像素宽高比(PAR)&角度;

2.如果视频包含旋转元数据(如 90°),onVideoSizeChangedwidthheight 会互换,此时需先处理旋转,再应用 PAR:

3.应用PAR

视频的像素有正方形有长方形,如果像素为正方形直接去宽高没有问题,如果不是正方形,宽度要重新计算:真实的宽度=videoSize.width*videoSize.pixelWidthHeightRatio,正方形时videoSize.pixelWidthHeightRatio=1.0,所以无论像素是正方形还是长方形:真实的宽度=videoSize.width*videoSize.pixelWidthHeightRatio

 @Override
        public void onVideoSizeChanged(VideoSize videoSize) {//视频尺寸回调,像素宽高比:pixelWidthHeightRatio = 1.0====像素是正方形的(宽高比为 1:1),否则像素是长方形的(宽高比非 1:1),像素被“压扁”
            LogUtil.d(TAG, "onVideoSizeChanged width " + videoSize.width + " height:" + videoSize.height + ",PAR,像素宽高比:" + videoSize.pixelWidthHeightRatio + ",角度:" + videoSize.unappliedRotationDegrees);
            int width = videoSize.width;
            int height = videoSize.height;
            // 处理旋转(交换宽高)
            int rotatedWidth = videoSize.unappliedRotationDegrees % 180 == 90 ? height : width;
            int rotatedHeight = videoSize.unappliedRotationDegrees % 180 == 90 ? width : height;
            // 应用 PAR 计算显示尺寸
            currentVideoWidth = (int) (rotatedWidth * videoSize.pixelWidthHeightRatio);
            currentVideoHeight = rotatedHeight; 
        }

ps:ExoPlayer不同版本onVideoSizeChanged回调的参数格式不一样,我的是2.16.1版本,

有些是:onVideoSizeChanged(width: Int, height: Int, unappliedRotationDegrees: Int, pixelWidthHeightRatio: Float),根据自己的环境获取视频信息即可


http://www.kler.cn/a/566593.html

相关文章:

  • ds回答-开源llm应用开发平台
  • 内容中台是什么?内容管理平台解析
  • 【Excel】 Power Query抓取多页数据导入到Excel
  • RabbitMQ 高级配置与优化:从入门到精通
  • macos uni-app 如何生成安卓APP的公钥和签名
  • Python设置阿里云镜像源教程:解决PIP安装依赖包下载速度慢的问题
  • 【2】VS Code 新建上位机项目---C#面向对象编程
  • el-tree实现双击树节点事件
  • 【官方配图】win10/win11 安装cuda 和 cudnn
  • 【大模型】大模型推理能力深度剖析:从通用模型到专业优化
  • GPT-4.5震撼登场,AI世界再掀波澜!
  • leetcode257-二叉树的所有路径
  • 穷举vs暴搜vs深搜vs回溯vs剪枝(典型算法思想)—— OJ例题算法解析思路
  • 信刻光盘安全隔离与信息交换系统让“数据摆渡”安全高效
  • vllm源码解析(一):整体架构与推理代码
  • IDEA - 查看类的继承结构(通过快捷键查看、通过生成类图查看)
  • Git -版本管理工具 -常用API整理
  • 【解决方案】Ubuntu 20.04安装podman和podman-compose
  • 萤石云+DeepSeek,云边融合助力音视频AI新突破
  • 【WPF命令绑定之--没有Command属性的控件如何进行命令绑定?】