视频播放相关记录

一、场景

    App应用测试在二次回归时,提出了安卓端视频定位不准的问题。

二、分析

   代码层面使用了安卓原始的MediaPlayer中的seekTo接口来定位:

 mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {
                    @Override
                    public boolean onInfo(MediaPlayer mp, int what, int extra) {
                        AFLog.d(TAG, "视频播放信息监听what="+ what +" firstEnter="+firstEnter);
                        if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START){
                            //首次根据前端传递过来进行定位
                            if (firstEnter){
                                AFLog.d(TAG, "--------seekValue "+ seekValue );
                                if (seekValue != 0){
                                    mp.seekTo(seekValue*1000);
                                }
                                firstEnter = false;
                            }
                            //视频准备渲染完成,隐藏进度框
//                            if (mLoadingDialog !=null && mLoadingDialog.isShowing()){
//                                mLoadingDialog.dismiss();
//                            }
                            hidGifLoading();
                        }else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START ){
                            //视频缓冲
//                            if (null != mLoadingDialog){
//                                mLoadingDialog.show();
//                            }
                            showGifLoading();
                        }else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END ){
                            //视频缓冲
//                            if (mLoadingDialog !=null && mLoadingDialog.isShowing()){
//                                mLoadingDialog.dismiss();
//                            }
                            hidGifLoading();
                        }
                        return false;
                    }
                });

android seekto实现_关于Android VideoView seekTo不准确的解决方案

根据网上查到信息说这个seek可能是异步返回需要将这个播放动作放到seek完成后进行,尝试了没有效果。

然后看到了第二个可能得原因,关键帧。从ChatGpt的回答可能原因中也有这点。

在视频编码中,关键帧(Keyframe),也称为关键帧图像或I帧(Intra-frame),是视频序列中的特殊帧。关键帧是一种独立的图像,它不依赖于之前或之后的帧来进行解码,而可以独立地解码和显示。关键帧在视频编码中具有重要的作用,它影响着视频的压缩效率、快速随机访问以及编辑等方面。

视频编码通常使用压缩技术来减少文件大小和带宽占用。在视频序列中,连续的帧通常会共享一些相似的内容,这些相似之处可以通过引用之前的帧来进行压缩。然而,这种依赖性也会导致一些问题,比如:

  1. 快速随机访问困难: 如果视频序列中的帧之间有依赖关系,那么要在视频中精确地跳转到某个时间点是比较困难的,因为你可能需要解码之前的帧才能显示目标帧。

  2. 编辑困难: 如果你想在视频中进行编辑、剪切或插入其他内容,依赖关系可能会导致编辑变得复杂,需要重新编码整个片段。

  3. 错误传播: 如果一个帧出现了错误,它可能会影响之后的帧的解码,导致错误在整个序列中传播。

关键帧解决了上述问题,它是独立的、不依赖于其他帧的帧。关键帧包含了完整的图像数据,通常是原始或未压缩的图像。在视频编码中,通常会周期性地插入关键帧,以便提供快速随机访问点和编辑的可能性。其余的帧通常是根据关键帧和之前的帧来进行预测和差异编码,以达到更高的压缩效率。

总之,关键帧在视频编码中扮演着重要的角色,它们提供了视频序列的重要参考点,有助于实现高效的压缩和解码,并提供了更好的随机访问和编辑能力。

于是使用了ffmpeg工具来分析视频中的关键帧是否足够:
 

ffmpeg -i input.mp4 -an -vf select='eq(pict_type\,I)' -vsync 2  -f image2 image-%03d.jpg

视频播放相关记录_第1张图片

 

果然出问题的视频中总共才两个关键帧:

视频播放相关记录_第2张图片

 

 

于是继续使用ffmpeg添加关键帧:

ffmpeg.exe -i "D:\in.mp4" -c:v libx264 -preset superfast -x264opts keyint=25 -acodec copy -f mp4 "D:\out.mp4"

ffmpeg 工具下载地址:

Releases · BtbN/FFmpeg-Builds · GitHub

通过让chatGpt生成bat脚本如下,集聚转换视频编码为h.264格式和添加关键帧功能:

@echo off
setlocal enabledelayedexpansion

REM 获取当前脚本所在的目录
set "script_dir=%~dp0"

REM 设置输入目录为当前脚本所在的目录
set "input_dir=%script_dir%input"

REM 设置输出目录为当前脚本所在的目录下的 "output" 子目录
set "output_dir=%script_dir%output"

REM 遍历输入目录下的所有视频文件并进行转换
for %%F in ("%input_dir%\*.mp4") do (
    set "input_file=%%~nxF"
    set "output_file=!output_dir!\%%~nF_converted.mp4"
    
    ffmpeg -i "%%F" -c:v libx264 -x264-params keyint=25 -c:a copy "!output_file!"
)

echo Conversion completed.
pause
 

 视频播放相关记录_第3张图片

 

来解决安卓端播放视频出现有声音无图像:video标签播放黑屏,只有声音无图像 - 简书

以及定位不准的问题。

苹果端使用avplayer却无此问题,不知为何。

 

 

你可能感兴趣的:(音视频)