ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ffmpeg protocol concat 进行ts流合并视频的时间戳计算及其音画同步方式一点浅析

2022-06-25 14:35:21  阅读:238  来源: 互联网

标签:protocol ffmpeg pkt ts ist time dts pts 浅析


ffmpeg protocol concat 进行ts流合并视频的时间戳计算及音画同步方式一点浅析

目录


ffmpeg 有三种常见的视频合并方式: demuxerprotocolfilter

这里有介绍它的使用 :

http://trac.ffmpeg.org/wiki/Concatenate#demuxer

本文主要介绍ts流合并视频时候合并后视频的pkt是如何计算的,音画是怎么同步的。


这种方式 是以复制pkt的方式进行的,不需要解码,不像fitler方式合并没有编码损失。
其基本命令如下 :

ffmpeg -i input1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate1.ts
ffmpeg -i input2.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate2.ts
ffmpeg -i "concat:intermediate1.ts|intermediate2.ts" -c copy -bsf:a aac_adtstoasc output.mp4

libavformat/concat.c中会处理 -i concat:"...." 打开所有输入文件,

输出的 pkt 的 dts 和 pts 为 所有输入pkt的 dts 、 pts + 上一个 ts_offset
第一个片段的ts_offset 应该是 0 - 第一个片段的起始时间
第二个片段的ts_offset 是第一个片段中 最长流的 pts + 上一段的ts_ofsset
依此类推后面的。

main->tanscode()->transcoder_step()->process_input(): 中的这段代码 即处理了 一个片段末尾新ts_offset的计算:

    if ((ist->dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO ||
         ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) &&
         pkt_dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE &&
        !disable_discontinuity_correction) {
        int64_t delta   = pkt_dts - ist->next_dts;
        if (is->iformat->flags & AVFMT_TS_DISCONT) {
            if (delta < -1LL*dts_delta_threshold*AV_TIME_BASE ||
                delta >  1LL*dts_delta_threshold*AV_TIME_BASE ||
                pkt_dts + AV_TIME_BASE/10 < FFMAX(ist->pts, ist->dts)) {
                ifile->ts_offset -= delta;
                av_log(NULL, AV_LOG_DEBUG,
                       "timestamp discontinuity for stream #%d:%d "
                       "(id=%d, type=%s): %"PRId64", new offset= %"PRId64"\n",
                       ist->file_index, ist->st->index, ist->st->id,
                       av_get_media_type_string(ist->dec_ctx->codec_type),
                       delta, ifile->ts_offset);
                pkt.dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
                if (pkt.pts != AV_NOPTS_VALUE)
                    pkt.pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
            }

因此 其合并 方式 应该如下图所示 :

如是,生成两个测试源,验证一下 :

audio 10 video 5s 衔接测试

ffprobe -i c.mp4 -select_streams v:0 -show_packets -of json |grep pts

可以看到 pts 在 5s 处 会有一段 跳变 而 audio 在5-10s是连续的 ->

            "pts_time": "4.776667",
            "pts": 432900,
            "pts_time": "4.810000",
            "pts": 435900,
            "pts_time": "4.843333",
            "pts": 438900,
            "pts_time": "4.876667",
            "pts": 441900,
            "pts_time": "4.910000",
            "pts": 444900,
            "pts_time": "4.943333",
            "pts": 447900,
            "pts_time": "4.976667",
            "pts": 450900,
            "pts_time": "5.010000",
            "pts": 904341,
            "pts_time": "10.048233",
            "pts": 907341,
            "pts_time": "10.081567",
            "pts": 910341,
            "pts_time": "10.114900",
            "pts": 913341,
            "pts_time": "10.148233",
            "pts": 916341,
            "pts_time": "10.181567",

打开 deug_ts 在ffmeg日志处 可以看到 ts 合并方式 下一段新的 偏移 取得是audio 的长度。

在这里插入图片描述

audio 5s video 10s 接着音频短的片尾斜街一段

ffprobe -i c.mp4 -select_streams a:0 -show_packets -of json |grep pts

这次我们检查音频流,可以看到音频在断点处 时间戳是有跳变的。

            "pts": 657792,
            "pts_time": "14.915918",
            "pts": 658944,
            "pts_time": "14.942041",
            "pts": 660096,
            "pts_time": "14.968163",
            "pts": 661248,
            "pts_time": "14.994286",
            "pts": 882216,
            "pts_time": "20.004898",
            "pts": 883368,
            "pts_time": "20.031020",
            "pts": 884520,
            "pts_time": "20.057143"

在这里插入图片描述

因此 基本符合开头猜想的逻辑:

小结

在这里插入图片描述

这种合并方式的优点是 能够 不打乱 原来每段的 音视频时间戳 进而确保音画同步,

缺点是 在音画 duration 差别过大的片段后面进行衔接 会留出一段 音或视频的空隙。 这种 空隙 播放器可能会卡最后一帧处理,不过建议是 转码处理是自行补齐静音 或视频 最后一帧。

再或者 尝试使用 ffmpeg -shortest 选项 截掉 音画 偏长的那一段内容 ,来进行 concat。

标签:protocol,ffmpeg,pkt,ts,ist,time,dts,pts,浅析
来源: https://www.cnblogs.com/ailumiyana/p/16411495.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有