目录
云存录像回放时间异常,包括但不限于以下情况
- 音视频不同步
- 前30秒只有音频,从第30秒开始有音频和视频,音视频之间相差30秒(或类似问题)
- 视频回放时播放速度时快时慢
- 实际录像时长为1分钟,回放时画面只显示了一瞬间,播放器闪退
- 实际录像时长为1分钟,播放器进度条显示时长为16小时,且画面卡住不动
- 实际录像时长为1分钟,播放器进度条显示时长远超1分钟,且无画面或无声音或即无画面也无声音 部分播放器对于这类情况的处理也不同,最终实际的播放效果也不同,上述现象仅供参考
以上几种问题或类似问题都是音视频帧时间戳异常导致的。云存视频回放严格依赖时间戳,因此在推送音视频帧时务必保证时间戳正确。
下面进行逐个分析: 音视频不同步 通常来说音视频帧的时间戳是这一帧采集的时刻,一般硬件编码器都带有时间戳,这个时间戳建议直接从编码器取出。如果编码器不带时间戳在手动添加时间戳时请尽量保证时间戳准确。手动添加时间戳常见错误是没有考虑误差积累,例如视频帧率是 30fps,每帧之间相差33.333……毫秒,整除为33毫秒,不进行误差补偿的时间戳为 0,33,66,99,132,165,198,补偿后为 0,33,66,100,133,166,200。特别是音频有重采样、格式转换等操作,视频有改变帧率等操作更容易引入误差,导致音视频帧的时间戳误差越来越大。
另一种情形是硬件编码的时间戳从初始化的那一刻开始计时,例如音频编码器在第0秒初始化,视频编码器在第3秒初始化,两个编码器的时间戳都是从0开始计时,两个编码器的时间戳虽然都从0开始计时,但因为初始化时键不同使拿到的音视频时间戳就始终相差3秒,导致音视频不同步。
前30秒只有音频,从第30秒开始有音频和视频,音视频之间相差30秒(或类似问题) 同样属于音视频不同步问题,见上文。
视频回放时播放速度时快时慢 为了光线不足时的画质,部分芯片在夜间或黑暗环境下会延长曝光时间来提升画面亮度,因此导致帧率降低。这种情况往往是手动计算帧率导致的,例如明亮环境下默认20fps,黑暗环境下降低为10fps,但时间戳仍然按20fps计算。 如下所示,假设在第5帧处帧率有20fps变为10fps 正常时间戳 0,50,100,150,200,300,400,500,600,700 异常时间戳 0,50,100,150,200,250,300,350,400,450 最终的效果就是明亮环境下画面正常,黑暗环境下画面速度为正常的2倍。如果芯片的ISP算法会改变帧率,建议直接从编码器获取时间戳,如需手动计算时间戳请按实际帧率计算,或者在向SDK推送视频帧时直接从系统获取毫秒级时间戳。
实际录像时长为1分钟,回放时画面只显示了一瞬间,播放器闪退 音视频帧的时间戳填写错误,典型情况就是误将时间戳填写为帧序号。 假设帧率为20fps 正常时间戳 0,50,100,150,200,300,400,500,600,700 异常时间戳 0,1,2,3,4,5,6,7,8,9 播放的效果为画面以正常速度的50倍进行快放,即1分钟的视频仅用1秒左右就播放完了,给人的感觉就是画面只显示了一瞬间,播放器闪退。
实际录像时长为1分钟,播放器进度条显示时长为16小时,且画面卡住不动 SDK接收的音视频帧时间戳单位是毫秒,造成这种情况是误将时间戳填成了微妙,使得1分钟的录像变为了16小时,画面其实并没有真正卡住,而是以相当于千分之一的速度慢放。
实际录像时长为1分钟,播放器进度条显示时长远超1分钟,且无画面或无声音或即无画面也无声音 这种情况是音视频使用了不同的时间戳导致的,例如音频的时间戳从0开始计时,视频的时间戳从当前UTC事件开始计时,两者相差的时间非常大,使得播放器的进度条显示的时间异常以及播放异常。 SDK要求必须填写音视频帧的时间戳,但不对时间戳的参考时间做强制要求,用户可以根据自己的实际情况填写,例如长供电设备的时间戳可以使用精确到毫秒的UTC时间,断电设备的时间戳可以从0开始计时,或者也可以使用其他值同时作为音视频时间戳的基准。总之音频和视频一等要使用相同的参考时间或相同的时间源,不要各自用各自独立的时间源。
保证音视频时间戳准确无误(手动计算时间戳时考虑误差、可变帧率等情况),保证音视频时间戳采用相同的参考时间或相同的时间源(例如编码器时钟、RTC时钟、UTC时钟、1毫秒tick时钟等) 以上问题用户可以自行使用相关软件排查,软件详细使用方法见下文。
云存录像播放异常,包括但不限于以下情况 云存视频部分播放器能正常播放,其他播放器不能播放 云存视频在线播放失败,下载后播放正常 云存视频播放卡顿 播放器闪退
目前常用的播放器功能差异较大,需要根据实际情况判断,常见原因有:
- 不支持软解码(或硬解码)H.264
- 不支持软解码(或硬解码)H.265
- 软解码H.265 CPU使用率过高导致卡顿(普通家用电脑(或手机)软解码高码率4K H.265视频可能非常吃力)
- 云存视频异常,播放器解码错误导致闪退
建议根据播放器的实际情况进行调整,例如:
- 开启或关闭H.264软解码(硬解码)功能
- 开启或关闭H.265软解码(硬解码)功能
- 开启跳帧功能,优先保证画面流畅度
- 开启纠错功能,跳过异常数据
云存录像回放时花屏(部分播放器可能会跳过花屏部分继续播放)
录像花屏说明云存上传过程中可能出现丢帧,例如由于网速原因导致云存缓存满,此时无法推送新的音视频帧进来,如果用户不做缓存则只能将这些帧丢掉,待网速恢复以后继续上传后续的音视频帧。这种情况下丢帧的地方就有可能异常,部分播放器会强制解码,部分播放器回跳过寻找下一个I帧继续播放。
开解播放器的纠错功能等 如果不希望花屏,用户可以将无法推送的视频数据暂存起来,等网络恢复以后继续发送;或丢弃无法推送的P帧,直到下一个I帧再进行推送,以此减少花屏。
并行事件录像时长不正确,例如第0秒触发了事件1,第15秒触发了事件2,第30秒同时结束了事件1和事件2。 拉取的事件列表中事件1时长30秒,事件1视频时长30秒,事件2时长15秒,视频时长20秒。

上述问题服务器中实际保存了【0秒至10秒】,【11秒至20秒】,【21秒至30秒】的三个视频文件,当查找事件2的视频即15-30秒的视频时,服务器会返回起止时间在15秒到30秒范围内的所有视频分片,即【11秒至20秒】,【21秒至30秒】这两个视频分片,因此实际看到的事件2的视频时长为20秒。同理,假设在第9秒触发了事件3,在第21秒结束事件3,事件3的实际持续时间为12秒,对应的视频为【0秒至10秒】,【11秒至20秒】,【21秒至30秒】这三个视频。
该问题不影响云存录像,如果需要视频时长精确匹配事件时长,可以通过播放器精确定位视频时间来实现。
云存录像实际长度为3分钟,回放时进度条显示为4分钟,且最后1分钟无法播放
全时云存顾名思义是需要持续录像的,正常的全时云存使用流程是初始化以后会收到 iv_cs_push_stream_start_cb 回调,之后用户应当持续推送音视频数据,直到因为云存套餐到期、退出云存等原因收到 iv_cs_push_stream_stop_cb 回调再停止推流。全时云存推流过程中可以调用 iv_cs_event_start 等接口触发事件。如果用户因特殊原因停止录像,SDK内部会等待1分钟,如果1分钟内没有恢复就会结束录像,下次推流时恢复正常。等待的这1分钟内因为没有数据进来,导致回放时进度条显示的时间比实际录像时间长1分钟,且这1分钟无法播放。
开通了全时云存套餐却没有按SDK要求正确推流就会导致这种现象,问题中就是开通了全时套餐,但没有按 iv_cs_push_stream_start_cb 回调的指示开始推流,而是自行按照触发事件开始推流、结束事件停止推流的方式使用,SDK发现无视频流继续等待1分钟后结束录像于是造成了问题中的现象。
全时云存进行持续录像,或更换事件云存套餐
事件云存触发事件后只有视频,没有图片(或没有事件消息,或其他类似情形)
调用 iv_cs_event_start 等接口时没有检查错误码继续推流就可能导致上述问题。
调用 iv_cs_event_start 等接口时请检查返回值,如有异常不建议继续推流,这种情况下SDK无法保证数据能够正常上传。
通过设备端日志发现云存已经上传成功,回放时进度条显示有时间,但无法播放。
云存视频要求必须上传音频和视频,如果用户只上传视频数据部分播放器可以正常播放,部分播放器则不行。 不能正常播放的常见原因是播放器优先使用音频帧的时间戳做音视频同步,因此播放器会一直向后读取,直到遇到音频数据才开始播放。 无音频,不播放,(ts里面标记里音频,实际没音频数据,播放器死等)
- 正常上传音视频数据
- 如果不需要音频(例如无麦克风、静音、保护隐私等)建议发送用0填充的音频数据帧
- 如设备端无法上传音频,则需要修改播放器的相关设置,以ffplay为例,添加
-an参数禁用音频,添加-sync video参数使用视频进行同步
实际网络环境波动较大,如何实现码率自适应
无
iv_avt_init初始化参数 pstInitParm->congestion 中可以设置是否启用水位告警以及告警的有高中低三挡水位值,当p2p内部缓存的水位到达这个值的时候会收到iv_avt_notify_cb回调- 使用过程中主动调用
iv_avt_get_send_stream_buf查询当前水位值 - 使用过程中主动调用
iv_avt_get_send_stream_status查询当前的瞬时网速和1秒内的平均网速 - 用户根据以上3种方法的查询结果自行开发并实现码率自适应
下面给出一种实现思路,仅供参考。
- 当发现p2p的水线超过一定值时,降低视频码率,例如当水位超过低水位时将视频码率降为原来的80%。网络正常的情况下p2p水位值很低,2mbps码率的视频水位值一般在100KB一下,该数值仅供参考,送入体积较大的I帧、网络波动等都会影响水位值。
- 推流过程中每间隔一定时间(例如1秒)调用
iv_avt_get_send_stream_status获取获取网速信息。由于瞬时速度的波动较大,这里建议使用1秒内的平均传输速度,设置一定长度的队列(例如长度为5,如果调用间隔比较短可以适当加长窗口),将该数值存入队列同时删除队列内最旧的一个数值,去掉一个最高值去掉一个最低值,计算平均值。算出的平均值可用于控制码率,一般而言此数值接与视频码率相近,当发现平均网速低于视频码率时主动降低视频码率到一个比平均网速更低的值。 - 用户可结合以上方法实或借鉴cubic拥塞控制算法等的思想现自己的码率自适应策略。对于p2p透传数据请参考
iv_avt_p2p_set_buf_watermark,iv_avt_p2p_get_send_buf,iv_avt_p2p_get_send_status接口,具体实现思路类似。
调用iv_avt_send_stream发送音视频数据返回错误, 不同的错误码的原因不同;
几种常见的错误码原因如下:
*错误码为-303时, 表示此时内部缓存满, 送入数据失败, 一般是网络原因导致此时的网络速度低于数据发送速度;
*错误码为-305时, 表示此时的visitor, channel, video_res_type三个参数中至少有一个值与iv_avt_start_real_play_cb通知的值不一致;
*错误码为-306时, 表示当前码率启动推流时送入的第一个视频帧不是IDR帧;
*错误码为-308时, 表示送入的音视频格式与iv_avt_get_av_enc_info_cb设置的格式不一致,或者本身送入的数据帧格式有问题,导致流媒体协议封装失败;
*出现错误码-303时, 在这个错误之前一般都会有水位报警, 需要降低码率, 码率控制方法操作问题1;
*出现错误码-305时, 需要用户检查自己的代码参数配置是否存在问题;
*出现错误码-306时, 需要用户推送的第一个视频帧为IDR帧, 也可以不用理会, 等待编码器正常产生IDR帧, SDK会把返回错误码的数据帧丢弃;
*出现错误码-308时, 首先需要用户检测iv_avt_get_av_enc_info_cb回调中设置的格式与实际数据帧是否匹配, 如果匹配还出现该错误, 需要用户将发生保存的数据保存下来, 分析该数据的格式是否正确;
在小程序或者APP端, 观看设备的直播时, 画面卡顿、不流畅或花屏;
卡顿的原因有很多种, 需要逐一排除, 其排查方法如下:
*将APP/小程序端收到的音视频流保存在本地, 格式一般为flv;使用第三方播放器(推荐PotPlayer或者VLC)观看本地保存的音视频数据, 如果仍然出现卡顿, 则是从原因1开始分析, 否则从原因2开始;
*原因1: 这种卡顿一般是因为视频数据有缺失, 从本地保存的音视频流中提取出H264/H265裸数据(推荐使用ffmpeg), 使用elecard分析H264/H265裸数据, 找到卡顿的时间点, 确认是否有丢帧(可根据silce header中的frame_num值判断), 一般都是有丢帧的, 丢帧一般都是在设备端引起的; 在设备端查找该时间点发生的音视频数据, 调用iv_avt_send_stream时是否有错误, 或者编码器生成的数据是否有丢帧(可将编码器的GOP实时值打印出来判断);
*原因2:这种卡顿一般是网络带宽低于数据码率或者时序有问题引起的, 先判断卡顿点设备端是否有水位报警, 然后使用flv分析工具分析数据的时序是否有问题, 如果时序没有问题则需要在设备端做码率控制;
*如果是设备端带宽原因引起的卡顿, 需要做码率自适应; *如果是设备端丢帧导致的, 则需要用户检查代码中的丢帧逻辑是否有问题; *如果是读取编码器数据有问题, 则需要用户检查业务逻辑中CPU是否占用太高或者取数据线程优先级太低;
在小程序或者APP端, 观看设备的直播时, 画面延时大或者黑屏;
- 画面延时大, 一般是音视频帧的PTS出现异常导致的, IoT Video SDK要求送入的音视频帧PTS单位必须是毫秒, 如果配置的单位不是毫秒, 则会在观看时出现异常;
- 画面延时大, 还有可能是设备端缓存的音视频数据太多, 需要用户检查业务中缓存的数据是否太多;
- 画面延时大, 还可能是播放器缓存的音视频数据太多, 多半伴有音视频PTS的同步问题, 需要在APP端或者小程序端检查音视频帧PTS中差值是否太大;
- 黑屏一般也是PTS出现问题, 最常见的是PTS出现了回环, 不是单调递增的, 导致播放出现问题;
- 如果是PTS问题, 需要设备端用户检查送入的音视频帧PTS配置是否有问题, 设备端IoT Video SDK在发送时不会做对音视频帧做同步缓存或者修改其PTS;
- 如果是设备端缓存数据多引起的问题, 则需要用户检查自己的业务逻辑问题, 设备端IoT Video SDK只会因为网络延迟大的原因缓存数据, 其他则不会缓存;
- 还有一种场景是, 有些摄像头设备带有PTZ功能, 在转动时为了滤除马达的声音, 不发送音频而是等待设备静止后发送, 这样也会破坏PTS的连续性, 造成延时很大, 推荐采用发送静音帧的方式来解决该问题;
复杂网络环境下的音视频对讲的表现各种不同,包括但不限于以下情形
- 设备网络正常,控制台可以看到设备在线,但无论刷新小程序或重启小程序、重启APP等均无法加载实时画面
- 设备连接wifi网络时手机能够正常看到画面,切换为有线网络后无法观看(或由wifi网络全换为3G/4G/5G网络,或链接了新的路由器等,或其他切换网络的情形)
- 设备连接某个运营商的网络时手机能够正常看到画面,切换另一个运营商后无法观看
- 设备本身(或所在的网络)开启了VPN功能,导致手机无法加载实时画面
- 设备连接在某个特定的路由器(交换机等网络设备)时无法观看,更换路由器后恢复正常
- 手机观看几分钟后画面断开,刷新后画面恢复正常,几分钟后又断开,如此反复
- 设备网络连接正常,控制台日志显示短时间内上报了大量 _sys_xp2p_info 属性,手机端无法加载实时画面
以上现象可分为以下几类
- 网络运营商策略:如运营商禁止UDP协议,运营商直接丢弃MTU超过某个大小的数据包而不进行分片,运营商封禁某些端口,运营商黑(白)名单,运营商在高峰期有特殊策略等
- 防火墙、路由器、交换机策略:同上
- VPN 问题:VPN 代理软件进行全局转发或其他规则
- 港澳台地区或国外网络:受互联网接入限制或政策法规限制等
此类问题优先建议从根源触发进行解决,例如:更换网络、联系网络运营商或网络管理员修改规则策略、关闭VPN软件或修改VPN规则等 当以上方法无法解决问题时请按如下步骤在设备端进行尝试
- iv_avt_init 设置初始化参数
iv_avt_init_parm_s.p2p_init_params.protocol = IV_AVT_P2P_UDP和iv_avt_init_parm_s.p2p_init_params.mtu_size = 1460,观察手机端能否正常出图 - protocol 类型保持不变,逐步减小 mtu_size(步长可以根据实际情况设置为20或更大),观察手机端能否正常出图。绝大多数数网络设备的默认MTU都是1500,但个别运营商可能会修改此参数和策略,一般而言设置为1400可满足绝大多数场景
- 若 mtu_size 减小至 1000 仍无法出图,请修改
protocol = IV_AVT_P2P_TCP,mtu_size = 0,观察手机端能否正常出图 - 正常网络环境下调用 iv_avt_init 初始化后会在10秒内收到 iv_avt_notify_cb 回调函数发来的 IV_AVT_EVENT_P2P_PEER_READY 事件,若未收到请重复1到3步进行尝试
- 正常网络环境下会偶尔收到
IV_AVT_EVENT_P2P_PEER_ERROR或IV_AVT_EVENT_P2P_PEER_CONNECT_FAIL事件属于正常现象(频率一般不高于每小时1次),如果短期内频繁(如1分钟1次甚至10秒钟1次)收到说明用户所在网络环境复杂,导致难以维持正常连接,请重复1到3步进行尝试
字符串相关的物模型, 包括属性, 行为或者事件, 上传失败但又没有错误码返回;
*最常见的原因是物模型中字符串使用json封装或者传入其他特殊字符, 物模型的值最终会被封装到一个大json消息体中, 如果传入的字符串本身就是json或者有特殊字符, 破坏了整个消息体的json完整性, 上报的消息不合法会被后台丢弃;
*如果需要使用字符串传输json信息, 推荐使用base64编码后再传输;
CPU使用率高如何优化
一般都是由加密算法造成的,在低端芯片上更为明显。
云存和P2P视频传输默认都开启加密功能,云存和P2P视频传输目前采用的加密算法分别为AES-CBC-128和AES-CTR-128。
下面给出部分加密算法在不同平台的跑分测试结果

- 用户自行适配 mbedtls 的硬件加速相关接口,并替换SDK内默认的 mbdetls 库
- 关闭加密功能(不推荐)
- MediaInfo 查看音视频文件的格式信息 下载地址 https://mediaarea.net/MediaInfo
- EasyIce 分析ts视频文件或视频流 下载地址 https://www.easyice.cn
- Elecard StreamEye Tools 分析h264视频文件 下载地址 https://www.elecard.com
- Elecard HEVC Analyzer 分析h265视频文件 下载地址 https://www.elecard.com
- flvAnalyser Flv分析工具 下载地址https://github.com/zymill/flvAnalyser
- VLC、PotPlayer、ffplay等视频播放器
- mp4box mp4文件分析工具 下载地址 https://github.com/gpac/mp4box.js
- Bento4 mp4文件分析工具 下载地址 http://www.bento4.com/
- 使用 VLC、PotPlayer 等播放器,选择播放在线视频,输入云存链接即可播放
- 使用ffplay,输入命令并替换云存链接
ffplay <replace your link address>,加入-loglevel trace参数可显示详细信息,一定程度上有助于排查云存视频问题 - 使用chrome浏览器打开 https://www.hlsplayer.net/ 等m3u8在线播放器,输入云存的播放地址并播放
- 使用chrome浏览器打开 https://www.hlsplayer.net/ 等m3u8在线播放器
- 按【F12】打开开发者工具,输入云存的播放地址并播放
- 如图所示
,可以在【Network】标签页中看到若干ts文件
- 在这些ts文件上右键选择【Copy】->【Copy link address】
- 将复制的链接放入任意下载器中进行下载(chrome直接访问该链接也可下载)
自行编写python脚本进行下载,这里给出简易下载脚本,仅供参考
from urllib.parse import urlparse
import requests
def get_m3u8(url):
r = requests.get(url)
if (r.status_code != 200):
return None
return r.content.decode("utf-8")
def make_ts_list(url, m3u8):
ts_list = []
m3u8_url = urlparse(url)
url_head = m3u8_url.scheme + '://' + m3u8_url.hostname
m3u8_lines = m3u8.split("\n")
for each_line in m3u8_lines:
if not each_line.startswith('#') and each_line != '':
ts_list.append('%s%s' %(url_head, each_line))
return ts_list
def download_ts(ts_list):
for each_ts in ts_list:
ts_url = urlparse(each_ts)
pos = ts_url.path.rfind('/') + 1
filename = ts_url.path[pos:]
print("download " + filename)
r = requests.get(each_ts)
if (r.status_code != 200):
return
with open(filename, "wb") as fw:
fw.write(r.content)
print("download finish")
def main():
aim_url = "https://zylcb.iotvideo.tencentcs.com/timeshift/live/timeshift.m3u8"
m3u8 = get_m3u8(aim_url)
ts_list = make_ts_list(aim_url, m3u8)
download_ts(ts_list)
if (__name__ == "__main__"):
main()
- chrome浏览器安装“网页资源嗅探器”等类似插件(此类插件众多,这里不做推荐)
- 打开 https://www.hlsplayer.net/ 等m3u8在线播放器
- 输入云存的播放地址并播放,嗅探器会自动识别视频并下载
- 不要使用ffmpeg,vlc等工具进行下载,这类工具会进行二次封装或二次格式转换,导致原始信息丢失。
准备工作:
- 按前文所述方法下载云存视频
- 准备相关工具软件
使用【MediaInfo】打开视频文件即可看到基本信息


使用【EasyICE】打开视频,点击【数据包】标签页,找到任意几个连续的视频帧,计算它们的pts间隔是否正确


同样地,音频帧也可以按照这种方式检查,但需要注意,云存会将所有音频非aac音频转换为aac格式,aac每个音频帧为1024个采样点,假设音频采样率为44.1KHz,那么每个音频帧的时长为 1024/44100=0.02322s=23.22ms
接下来检查音视频时间戳是否同步,随意找几个视频帧附近的音频,观察音频帧和视频帧的PTS误差是否过大。

使用【Elecard StreamEye Tools】打开视频
假设GOP为15帧,如图所示这里I帧P帧分布不均匀,明显有大量视频帧丢失,云存视频播放到这里就会花屏

准备工作:
- APP端保存接收到的视频流
- 准备相关工具软件



