最近因为耳机3.5mm接口的一些干扰问题,舍弃了之前的接入方式,需要重新实现网络音频流的接入,在这个过程中遇到了一些问题,特来记录一下~

一、网络音频流的接入

这个音频流来源各不相同,我这里是udp广播到10001端口上的,直接监听本机10001端口就可以看到音频信息。

需要提前知道的是这个网络音频流原本的采样率和位深是多少,这里我已经知道了61000hz的采样率和16的位深

这时候我们借助ffmpeg下的ffplay程序可以直接播放这个音频,命令如下

.\ffplay.exe -f s16le -ar 61000 -ac 2 udp://0.0.0.0:10001

二、音频流和视频流合并

通过ffmpeg对网络音频流进行读取,读取之后和rtsp视频流进行合并,

这一步简单讲一讲:

首先跟rtsp读取流的方式类似,ffmpeg对音频流的读取方式也是支持url直接读取的

如下所示:

if ((ret = ffmpeg.avformat_open_input(&formatContext, _audioUrl, _inputAudioFormat, &options)) < 0)
{
ffmpeg.av_dict_free(&options);
ffmpeg.avformat_close_input(&formatContext);
throw new Exception($"Could not open input path: {_audioUrl} (error '{FFmpegHelper.av_err2str(ret)}')");
}

需要注意的是,因为是网络音频流,这个音频流是不带位深和采样率信息的,需要我们自己提前指定

AVCodecParameters* codecpar = formatContext->streams[_audioIndex]->codecpar;

if (SampleRate > 0)
{
codecpar->sample_rate = 61000;
codecpar->channels = ffmpeg.av_get_channel_layout_nb_channels((ulong)_channelLayout);
}
_inputAudioFormat = ffmpeg.av_find_input_format("s16le");

由上面初始化开启探针读取网络音频流和视频流之后,剩下的处理就是合并了。

合并这里本质上就是合并读取出来的audioPacket和videoPacket,然后将packet转为frame,这时候转换为要输出的格式,再构建到packet中,最终将packet交错写入到同一个_formatContext进行保存。(很大白话了23333)

ffmpeg.av_interleaved_write_frame(_formatContext, outputPacket);

三、音画不同步的问题

上面的功能实现之后又发现保存后的视频存在音画不同步的问题

现象是:

①实时播放过程中,耳机反馈实时播放声音,实际动作比声音略晚,视频略早于声音

②播放视频过程中,声音比动作先出现了,也就是音频早于视频。

这里①很正常,因为本来音频通过wave过去并播放,肯定是需要时间的

但是②就不太对了,这是摆明了就是视频音画不同步。

而音画不同步的原因有以下几种可能:

①网络延迟:音频和视频数据在传输过程中可能会受到网络延迟的影响,导致数据到达接收端的时间不同步。这可能是由于网络拥塞、传输路径不稳定等原因引起的。

②编解码延迟:音频和视频的编解码过程可能会引入一定的延迟,导致数据的播放时间不同步。不同的编解码算法和参数设置可能会对延迟产生影响。

③媒体同步机制:RTP流中的音频和视频数据通常是分开传输的,接收端需要根据时间戳等信息将它们进行同步播放。如果同步机制实现不正确或者缺失,就会导致音频和视频不同步。

其实原因看起来很多,但归根到底都还是同步问题。

这里上面的现象让我直接推断是视频进入帧的时候比较晚,于是直接就怀疑了是视频读包要晚于音频的情况,想到这我们直接验证:

只需要在写入第一个视频帧和写入第一个音频帧的地方打印一个距流开启的时间就能观察到问题,这里我使用了_stopwatch进行准确的打印。

结果确实也验证了上面的想法——音频的偏移大概是35ms左右,可以忽略不计,而视频相较于音频大概延迟400-500ms。

那么我们这时候就可以进行音画同步了。

四、音画同步

首先说明:这里的同步是针对于探针时间偏差和编解码延迟导致的音画不同步问题设计的。

原理很简单:通过音频和视频写入第一帧的时间和流开启的时间的偏差,移动视频和音频的pts和dts进行对齐。

首先从上面的例子中就可以获取_stopwatch.ElapsedMilliseconds,分别是音频写入第一帧的时间和视频写入第一帧的时间与流开启的时间的偏差,这里分别是音频35ms,视频400ms。这时候我们统一对音频和视频pts和dts进行左移,将二者的首端都移到视频起始的位置。

这里需要注意的是,我们需要在时基转换之后的outpacket上进行操作,不然无法生效。

ffmpeg.av_packet_rescale_ts(outputPacket, _audioCodecContext->time_base, _audioStream->time_base);

在上面的时基转换后,我们以音频举例,这时获取了_sampleStartPts(音频的偏移),因为ElapsedMilliseconds是毫秒,所以我们需要除1000换算成秒,然后乘以时基,这时候我们就得到了pts实际的需要偏移的量。

_sampleStartPts = _stopwatch.ElapsedMilliseconds * _audioStream->time_base.den / 1000;

(特别提醒:这里的时基我默认分子为1,所以我直接用的分母,如果分子不同需要加入进行换算)

得到了ptsOffset(_sampleStartPts)之后呢,我们直接对所有输出的packet进行pts、dts移动就可以啦

outputPacket->pts -= _sampleStartPts;
outputPacket->dts -= _sampleStartPts;

这里因为是要去首端对齐,所以是减去偏移量~

最后再把上面的操作对应到视频流中执行一遍,出来的视频音画就同步了~

ps 文章原创于idealy233,转载请私信哦~

ffmpeg合并时音画不同步问题及音频软编码实现记录的更多相关文章

  1. (大概是最全的解决方法)使用bandicam录制视频导入pr后音画不同步问题

    遇到这个问题大部分都是使用了VBR来录制视频导致的, 搜集了各种能够找到的方法,并没有每个尝试过 一 Handbrake转码 Audio out of sync AFTER importing 解决方 ...

  2. 在FPS游戏中,玩家对音画同步感知的量化与评估

    前言 在游戏测试中,音画同步测试是个难点(所谓游戏音画同步:游戏中,音效与画面的同步程度),现在一般采用人工主观判断的方式测试,但这会带来2个问题: 无法准确量化,针对同一场景的多次测试结果可能会相反 ...

  3. QQ视频直播架构及原理 流畅与低延迟之间做平衡 音画如何做同步?

    QQ视频直播架构及原理 - tianyu的专栏 - CSDN博客 https://blog.csdn.net/wishfly/article/details/53035342 作者:王宇(腾讯音视频高 ...

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

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

  5. 【FFMPEG】各种音视频编解码学习详解 h264 ,mpeg4 ,aac 等所有音视频格式

    目录(?)[-] 编解码学习笔记二codec类型 编解码学习笔记三Mpeg系列Mpeg 1和Mpeg 2 编解码学习笔记四Mpeg系列Mpeg 4 编解码学习笔记五Mpeg系列AAC音频 编解码学习笔 ...

  6. 音视频编解码流程与如何使用 FFMPEG 命令进行音视频处理

    一.前言 FFMPEG 是特别强大的专门用于处理音视频的开源库.你既可以使用它的 API 对音视频进行处理,也可以使用它提供的工具,如 ffmpeg, ffplay, ffprobe,来编辑你的音视频 ...

  7. FastAdmin 开发时如何与官方同步升级

    FastAdmin 开发时如何与官方同步升级 使用 FastAdmin 开发时为了与官方同步升级,推荐使用 git 管理代码. 官网上提供的完整包是为了方便第一次使用的人快速测试. 我一般是给官方的 ...

  8. rsync+inotify 实现资源服务器的同步目录下的文件变化时,备份服务器的同步目录更新,以资源服务器为准,去同步其他客户端

    测试环境: 资源服务器(主服务器):192.168.200.95 备份服务器(客户端):192.168.200.89 同步目录:/etc/test 同步时使用的用户名hadoop密码12345 实验目 ...

  9. 关于 Javascript 严格模式下多文件合并时注意

    Javascript 在第一行使用 "use strict" 声明严格模式. 但是在多个 js 文件合并时就需要注意了,可能你的是严格模式,但别的文件不是,就会造成错误. 为什么使 ...

  10. 使用ffmpeg合并视频文件的三种方法

    ffmpeg合并视频的方法有三种.国内大多数仅介绍了其中之一.于是觉得有必要翻译一下.其实在ffmpeg的 FAQ文档中有比较详细的说明. 使用concat协议进行视频文件的合并 这种方式的适用场景是 ...

随机推荐

  1. 国产系统UOS上的视频监控系统

    一.功能特点 (一)软件模块 视频监控模块,各种停靠小窗体子模块,包括设备列表.图文警情.窗口信息.云台控制.预置位.巡航设置.设备控制.悬浮地图.网页浏览等. 视频回放模块,包括本地回放.远程回放. ...

  2. Java GUI控件SwingX之JXTaskPane的使用示例

    JXTaskPane 类似XP 左边的导航栏,在开发Swing应用的时候很好用的.下面两张截图反应了JXTaskPane的动画效果.可以自由的卷起和展开.   JXTaskPane的的使用步骤:1.新 ...

  3. IM扫码登录技术专题(三):通俗易懂,IM扫码登录功能详细原理一篇就够

    本文引用了作者"大古同学"的"二维码扫码登录是什么原理"一文的主要内容,为了更好的理解和阅读,即时通讯网收录时有修订和改动,感谢原作者的分享. 1.引言 自从微 ...

  4. 基于高德地图API在Python中实现地图功能的方法

      本文介绍在高德开放平台中,申请.获取地图API的Key的方法:同时通过简单的Python代码,调取API信息,对所得Key的可用性加以验证.   首先,我们进入高德开放平台的官方网站.如果大家是第 ...

  5. 【饮食与健康】【AIGC创作】表观生理年龄逆转指北

    一.引言 我们都知道,岁月不饶人,但是谁又不想在岁月的长河中留下青春的容颜呢?在这个人人都追求健康和美丽的时代,我们的生活节奏却愈发紧张,高压的工作和不规律的作息让我们的身体时刻处于亚健康状态.这时候 ...

  6. ABP 系列总结

    2019年第一次接触 ABP 框架,那时候还是比较笨重的旧版本的,后来升级到 vNext 版本,我也基于 ABP 模块化的设计方式开发了一些模块用于日常工作.这个系列主要为了系统地记录一下日常工作与学 ...

  7. 在OERV也可以玩MC(上)

    最近发现一个比较有意思的事情,原来HMCL这个项目也移植到RISC-V上了,之前一直没有发现,因此在OERV(openEuler RISC-V的简称)玩MC也是可以的了.首先,HMCL是一款功能丰富的 ...

  8. ClickHouse-2接口

    客户端 ClickHouse提供了两个网络接口(两个都可以选择包装在TLS中以增加安全性): HTTP, 包含文档,易于使用. Native TCP,简单,方便使用. 在大多数情况下,建议使用适当的工 ...

  9. python实现excel数据处理

    python xlrd读取excel(表格)详解 安装: pip install xlrd 官网地址: https://xlrd.readthedocs.io/ 介绍: 为开发人员提供一个库,用于从M ...

  10. biancheng-linux-shell

    参考http://c.biancheng.net/view/706.html Shell变量:Shell变量的定义.赋值和删除 Shell 支持以下三种定义变量的方式: variable=valuev ...