视频处理遇到的一些问题

1. flv文件时间戳突然变大

1.1 问题描述

我们的视频推流到cdn后,cdn会记录下来我们的流的并生成flv文件。由于flv文件生成是一小段一小段的,所以在一堂课结束后,我们会有一个小工具,将这些小段的flv文件拼接起来。有一个出现了几次的问题是,拼接起来的文件有一段是播放不了的。 我检查了flv文件,发现视频文件有问题,如下图: flv文件问题 可以看出flv中封装的H.264的视频帧,居然时间直接到了93:38.900,这个应该就是罪魁祸首了。我理了一下推流的过程,可能是老师先讲了90多分钟,中间休息了一会,再接着推,但悲剧的是打时间戳的变量没有从头算。

下载到本地用播放器播放时,还是可以正常播放的,应该是播放器本身作了调整。但是一般的播放器拖时间轴是不能快进的。另外一些播放器直接就停在第一帧动不了。

1.2 我的尝试1

这个其实我还折腾了挺久,例如搜索了一下"flv时间戳"或者"flv时间轴"修复工具,也直接用flvbugger来修复了一下,但其实这些工具基本都是对flv的头信息进行修复。对于时间戳这种问题压根没有用。 最后还是回到了ffmpeg,我先对这个flv视频重新抽样编码,存在mp4中。这样其实是把流单独弄了出来,音频也单独弄了出来最后合到了mp4,命令: ffmpeg -i e.mp4 -map 0 -c copy -f mpegts -bsf h264_mp4toannexb -y xe.mp4 最后合并一下: ffmpeg -i "concat:xa.mp4|xb.mp4|xc.mp4|xd.mp4|xe.mp4" -c copy -absf aac_adtstoasc xx.mp4 悲剧的是,这种方式也是无用的。

1.3 同事的尝试2

第二天来公司,同事给了个建议,就是把音频和视频分别抽取出来,对齐后再合到一起,他用这种方式实现了。不过有一个问题是抽取和合并后,文件会变成4倍多,另外对齐时间戳也有点折腾。虽然能搞定,但我还是想是不是直接修改flv中的时间戳就完事了。

1.4 我的尝试3

我找了一下github上操作flv文件的开源项目,最后找到了这个H264Parse,这个项目把flv的格式都分析得非常好了也有输入输出的例子,可以让我快速达到目的,于是就用了。不过在用的时候,发现会报ByteBuffer的一个异常,搜了一下是一个常见的问题,就是如果不是他这个格式编码的flv,读入和读出都会有问题。因为它会取buffer中的字节作成number,string,int之类的,在读最后一个字节时就经常报问题。后来我想了一下,我的 tagBody其实是没有必要进行加解密的,于是自己fork了一份简单修改了一下,放在这里了我用的H264Parse

主要的修改是在这里:


if (type == 0x09) {
    if (timestamp > 1000) {
        // 这个时间就是我们的客户端打超前了的时间
        // 看代码是因为时间戳这个变量在关直播时还在计数,下次开就会有问题。。。
        timestamp = timestamp - ((117 * 60 + 54) *1000 + 800);
        if (timestamp < 0 ) {
            timestamp = 0;
        }
    }
}

这个坑之前也出现过两次,当时简单调了一下就好了,也没有跟客户端同事强烈要求看代码。然后这次是我和客户端新人看了2分钟就定位到了问题,真的不能因为bug小就不花精力盯,没准会导致更大更变态的使用问题呢。

1.5 更多的问题

除了这个时间戳不对之后,还有另一个问题,我们的HLS流播放出来是一卡一卡的,然后跟进了一下推上去的原始流,发现也是一卡一卡的。再细查视频帧的时间戳,发现一般是会100ms一个,并且都是整数,但是有时会出现一个200ms间隔,另外音频正常的是23ms一个帧,但是也会跳帧。后来与客户端同事一起联调,最新的方案是视频帧的时间戳打在上一个音频时间戳之后1ms或者同时。目前看来卡顿是没有了,但是hls还是有可能会音画不同步。估计还是编码层有问题。

2. h5video标签播放时音画不同步

2.1 问题描述

2016.01.19号上线了新的jwplayer播放器,对于录播,jw6我们用的还是flash模式进行播放的,而在最新上线的jw7中,我为了加入变速播放这个功能,使用h5模式,也就是让jw6用h5的video标签。然后发现,音频和视频居然是对不上的。

2.2 验证实验

对同一个视频,我下载到本地用播放器无问题,在web端用flash播放无问题,直接在浏览器中打开播放有问题,用h5的video播放有问题。我换了一个别的视频,用h5的video播放无问题,在我们的jw7 h5模式播放也没有问题。

这样看起来,对比我的视频A和另一个视频B的差别可能会帮我要找出问题的原因。对比后发现 Frame rate mode : Constant
Frame rate : 25.000 fps
Maximum bit rate : 5 022 Kbps
在我的是variable的。 查一下资料,找到了这个:http://ffmpeg.org/pipermail/ffmpeg-user/2012-December/012232.html 看来别的人也遇到过这个问题,而原因就是"input file is a variable frame rate".

2.3 解决办法

做了十几个实验,包括加入: -vsync 为0,1,-1,drop的,使用-crf的,最后还是使用-async解决。 ffmpeg -i 1.flv -c:v libx264 -r 15 -c:a aac -strict -2 -b:a 64k -ar 44100 -ac 2 -async 1 e1.mp4

其实主要的参数就是-async,另外再加上-r 15,这样video frame rate mode是constant的,有些资料上面也说非15和29.3的fps会导致音画不同步。不过在看录播听音乐时还会有时有破音的情况。不过一般说话还是感觉不出来的。

comments powered by Disqus