ffmpeg protocol concat 进行ts流合并视频的时间戳计算及其音画同步方式一点浅析
ffmpeg protocol concat 进行ts流合并视频的时间戳计算及音画同步方式一点浅析
ffmpeg 有三种常见的视频合并方式: demuxer,protocol,filter
这里有介绍它的使用 :
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。
ffmpeg protocol concat 进行ts流合并视频的时间戳计算及其音画同步方式一点浅析的更多相关文章
- QQ视频直播架构及原理 流畅与低延迟之间做平衡 音画如何做同步?
QQ视频直播架构及原理 - tianyu的专栏 - CSDN博客 https://blog.csdn.net/wishfly/article/details/53035342 作者:王宇(腾讯音视频高 ...
- 使用ffmpeg裁剪和合并视频
剪切视频 使用 -ss 和 -t 选项,从第0秒开始,向后截取31秒视频,并保存 ffmpeg -ss :: -i video.mp4 -vcodec copy -acodec copy -t :: ...
- 利用selenium和ffmpeg爬取m3u8 ts视频《进击的巨人》
需求 想看下动漫<进击的巨人>,发现到处被和谐,找不到资源,但是在一个视频网站找到了在线播放,https://www.55cc.cc/dongman/17890/player-2-1.ht ...
- 用ffmpeg快速剪切和合并视频
如果直接找视频剪切和合并视频的软件,通常出来的都是大的视频编辑软件或者是有图形界面的剪切软件,大型一点的功能太多安装麻烦,小型一点的功能可能不齐全. 只是简单的剪切或者一下合并一下,还是ffmpeg这 ...
- 使用ffmpeg合并视频文件的三种方法
ffmpeg合并视频的方法有三种.国内大多数仅介绍了其中之一.于是觉得有必要翻译一下.其实在ffmpeg的 FAQ文档中有比较详细的说明. 使用concat协议进行视频文件的合并 这种方式的适用场景是 ...
- ffmpeg解析TS流
介绍: MPEG的系统层编码为不同的应用场景设计了两种格式: TS(Transport Stream) 和PS(Program Stream), 它们两者之间不具有层级关系, 在逻辑上,它们两者都 ...
- 网络视频m3u8解密及ts文件合并
网络视频m3u8解密及ts文件合并 参考了两篇博客: https://blog.csdn.net/weixin_41624645/article/details/95939510 https://bl ...
- 分析ffmpeg解析ts流信息的源码
花费一些时间,然后全部扔了.为了不忘记和抛砖引玉,特发此贴. ffmpeg解析ts流 1.目的 打算软件方式解析出pat,pmt等码流信息 2.源代码所在位置 下载ffmpeg ...
- FFMPEG中关于ts流的时长估计的实现(转)
最近在做H.265 编码,原本只是做编码器的实现,但客户项目涉及到ts的封装,搞得我不得不配合了解点ts方面的东西.下面技术文档不错,转一下. ts流中的时间估计 我们知道ts流中是没有时间信息的,我 ...
- 使用vlc实现视频TS流的推送
鉴于Mpeg TS流播放的需求,使用 VLC作为Server来实现输出Mpeg TS 本文仅涉及如何使用VLC的Command来实现作为视频流Server通常可以使用下述四种方式来推送Mpeg ...
随机推荐
- esxi的一些命令
今天本想在vcenter上建个分布式交换机,没想到在迁移主机端口时,由于主机只连了一个物理网卡,导致在迁移到分布式交换机而失去连接,几近周折,从网上找了几篇不错的文章,与众同乐 假如一台ESX主机先通 ...
- web3招聘信息渠道
[web3招聘信息渠道]随手转发,供参考,供补充. 个人微博:https://weibo.com/u/2434823180 Blog: https://apenote.github.io vx: ap ...
- 三大常用集群leader选举+哨兵模式原理
一,Zookeeper集群的leader选举 Zookeeper的选举机制两个触发条件:集群启动阶段和集群运行阶段leader挂机(这2种场景下选举的流程基本一致) 1,Zookeeper集群中的fo ...
- list tuple dic set的区别
list是可变的(可以在list里边添加删除替换内容) 声明时用[ ] tuple和list非常类似,但是tuple一旦初始化就不能修改 ,声明时用() classmates = ('Michael ...
- function | fastica
fastica - Fast Independent Component Analysis FastICA for Matlab 7.x and 6.x Version 2.5, October 19 ...
- Redis集群模式及工作原理
Redis有三种集群模式:主从模式.哨兵模式和集群模式. 1. 主从模式 所有的写请求都被发送到主数据库上,再由主数据库将数据同步到从数据库上.主数据库主要用于执行写操作和数据同步,从数据库主要用于执 ...
- CF1272 B DIV3 ---代码对比
这次DIV3有点可惜啊,题解是我的与学长的代码对比 学长的原博客https://www.cnblogs.com/xyq0220/p/12036109.html B.Snow Walking Robot ...
- 多文件下载并打成zip文件传输到浏览器响应流
import lombok.extern.slf4j.Slf4j; import javax.servlet.http.HttpServletResponse; import java.io.*; i ...
- cmake使用boost静态库,错误提示 Could NOT find Boost (missing: Boost_INCLUDE_DIR) (Required is at least version "1.48")
使用的是Cmake-gui 编译. 问题出在C盘路径下找不到 Boost ,是否需要把boost的路径添加到系统Path 中? 任然不能解决. 更改源码: 找到下面这几行代码(你可以搜索) messa ...
- Windows10安装UR_RTDE
------------恢复内容开始------------ 要使用UR_RTDE必须先配置电脑环境,目前使用的环境是电脑win10,配置环境需要VS2019+boost1_66_0+cmake2.3 ...