如何解决VideoView播放FFmpeg编码MP4视频时的拉伸问题?
嘿,这个坑我之前踩过!VideoView对视频宽高比的处理确实会因为编码时的元数据差异出现不一致的情况,尤其是FFmpeg编码的视频容易栽在这里。先给你捋清楚原因:
大部分常规软件编码的MP4会正确写入**样本宽高比(SAR)和显示宽高比(DAR)**的元数据,VideoView能识别这些参数并自动保持比例;但如果用FFmpeg编码时没明确设置这些参数,视频文件里就只有像素宽高信息,VideoView就会默认按屏幕尺寸强制拉伸铺满,导致比例失调。
给你两个方向的解决方案,按需选择:
方案1:从编码源头解决(最优)
重新编码视频时,用FFmpeg明确指定SAR和DAR参数,确保元数据正确写入。举个例子,如果你的视频是16:9的比例,像素分辨率是1280x720,编码命令可以这么写:
ffmpeg -i input.mp4 -vf "scale=1280:720,setsar=1:1" -c:v libx264 -c:a aac output.mp4
或者直接指定显示宽高比:
ffmpeg -i input.mp4 -vf "scale=1280:720,setdar=16/9" -c:v libx264 -c:a aac output.mp4
这样编码后的视频会包含完整的宽高比信息,VideoView就能自动识别并正常显示,不会出现拉伸。
方案2:在Android代码中手动控制缩放(无法重新编码时用)
如果没办法重新编码视频,我们可以在代码里监听VideoView的准备事件,手动计算正确的宽高比,强制调整视频显示尺寸:
第一步:调整布局XML
把VideoView放在一个容器(比如FrameLayout)里,方便后续动态调整尺寸:
<FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <VideoView android:id="@+id/videoView" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitCenter" /> </FrameLayout>
注意这里把scaleType设为fitCenter,避免默认的拉伸行为。
第二步:添加代码逻辑
在Activity/Fragment里给VideoView设置准备监听,计算并调整尺寸:
VideoView videoView = findViewById(R.id.videoView); videoView.setVideoPath("你的视频路径"); videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { // 获取视频的原始宽高 int videoWidth = mp.getVideoWidth(); int videoHeight = mp.getVideoHeight(); // 获取容器的宽高 int containerWidth = videoView.getWidth(); int containerHeight = videoView.getHeight(); // 计算视频和容器的宽高比 float videoRatio = (float) videoWidth / videoHeight; float containerRatio = (float) containerWidth / containerHeight; ViewGroup.LayoutParams params = videoView.getLayoutParams(); if (videoRatio > containerRatio) { // 视频比容器宽,按容器宽度适配,高度按比例计算 params.width = containerWidth; params.height = (int) (containerWidth / videoRatio); } else { // 视频比容器高,按容器高度适配,宽度按比例计算 params.height = containerHeight; params.width = (int) (containerHeight * videoRatio); } videoView.setLayoutParams(params); // 开始播放 mp.start(); } });
这段代码会忽略视频元数据的缺失,直接按视频原始像素宽高计算比例,强制VideoView按正确比例显示,彻底避免拉伸。
额外检查点
确认你的布局里VideoView的scaleType不是fitXY——这个属性会强制视频拉伸铺满屏幕,是拉伸问题的常见诱因。
内容的提问来源于stack exchange,提问作者BertoGT




