首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >SRS支持Haivision编码器,及解决HLS纯音频爆音

SRS支持Haivision编码器,及解决HLS纯音频爆音

作者头像
Winlin
发布2022-03-18 17:10:43
发布2022-03-18 17:10:43
7890
举报
文章被收录于专栏:SRS开源服务器SRS开源服务器

Haivision是另外一只野鸡编码器,黑爷要支持十万火急,所以看了下,Haivision的协议序列不是FMLE也不是FFMPEG也不是Flash,是自己的一个私有协议:

如果看不太明白,那么下面是个总结。

FFMPEG的消息序列,也就是推流的协议了:

代码语言:javascript
复制
C/S: Handshake
C: ConnectApp() tcUrl=xxx
S: Ack Size 2500,000
S: Set Peer Bandwidth 2500,000
S: Set Chunk Size 60,000
C: Set Chunk Size 60,000
S: ConnectApp() _result
S: onBWDone()C: releaseStream+FCPublish(s0)
C: createStream()
S: releaseStream _result
C: _checkbw()
S: FCPublish() _result
S: createStream() _result
C: publish(s0)
S: onFCPublish()
S: onStatus()

Haivision的消息序列:

代码语言:javascript
复制
C/S: Handshake
C: Set Chunk Size 4096+ ConnectApp() tcUrl=xxx
S: Ack Size 2500,000
S: ConnectApp() _result + Set Peer Bandwidth + Set Chunk Size 60,000C: _checkbw()
S: _checkbw() _result
C: createStream()
S: createStream() _result
C: FCPublish()
S: FCPublish() _result
C: publish()
S: onFCPublish()
S: onStatus()
----OK------
C: Stream Begin
C: @setDataFrame()
C: AudioData
C: VideoData

可见是完全不同的,花了2个小时才支持,看来不仅仅是国内喜欢自己搞,国外也是一样坑爹啊。。。

其他信息可以参考:https://github.com/ossrs/srs/issues/844


第二个重要的问题,是解决了HLS纯音频爆音的问题,爆音的问题查明白了,是因为采样率导致的时间戳不能整除,所以会有误差,Safari比较精确,所以会有噗噗的声音。

验证如下,先看8000HZ采样率,一个AAC帧是1024个采样,所以一个AAC帧是:

代码语言:javascript
复制
1024/8000.0=0.128s=128ms
如果是16000HZ采样率,则每个AAC帧是:1024/16000.0=0.064s=64ms

SRS配置如下:

代码语言:javascript
复制
listen              1935;
max_connections     1000;
daemon              off;
srs_log_tank        console;
http_api {
   enabled         on;
   listen          1985;
}
http_server {
   enabled         on;
   listen          8080;
}
vhost __defaultVhost__ {
   hls {
       enabled         on;
       hls_fragment    2;
       hls_window      60;
       hls_vcodec vn;
       hls_path        ./objs/nginx/html;
       hls_m3u8_file   [app]/[stream].m3u8;
       hls_ts_file     [app]/[stream]-[seq].ts;
   }
}

使用FFMPEG转码,输出16KHZ的音频:

代码语言:javascript
复制
ffmpeg -re -i doc/source.200kbps.768x320.flv \
-vn -acodec libfdk_aac -ar 16000 -ac 2 -b:a 48k \
-f flv -y rtmp://127.0.0.1/live/livestream

用Safari访问:http://localhost:8080/live/livestream.html ,可以发现,没有爆音。

转码时,输出44100HZ的音频:

代码语言:javascript
复制
ffmpeg -re -i doc/source.200kbps.768x320.flv \
-vn -acodec libfdk_aac -ar 44100 -ac 2 -b:a 48k \
-f flv -y rtmp://127.0.0.1/live/livestream

可以听到每隔4秒左右会有噗噗,或者滋滋的杂音,每隔一片就会有。得仔细听才会有。

原因是什么?在44100HZ时,每个AAC帧是:

代码语言:javascript
复制
1024/44100.0=0.02321995s=23.21995ms

如果取整,则每个帧会有0.2ms的误差,Safari比较敏感,所以容易出现问题。

如何解决这个问题?NGINX将多个AAC帧合并成一个TS Packet,然后累计计算时间。 如果直接每帧计算时间:

代码语言:javascript
复制
90000*1024/44100.0=2089.795918367347

这样误差可以降低到1/90。

例如,一个audio的信息是:

代码语言:javascript
复制
(lldb) p audio->timestamp
(int64_t) $8 = 23
(lldb) p audio->timestamp*90
(long long) $9 = 2070

但是通过samples个数重新计算的结果是:

代码语言:javascript
复制
int64_t dts = 90000 * aac_samples / srs_flv_srates[format->acodec->sound_rate];
(lldb) p dts
(int64_t) $6 = 2089

200ms之后:

代码语言:javascript
复制
(lldb) p audio->timestamp
(int64_t) $14 = 209
(lldb) p audio->timestamp*90
(long long) $15 = 18810
(lldb) p dts
(int64_t) $16 = 18808

结果,没有噗噗的爆音了。

详细信息参考:https://github.com/ossrs/srs/issues/547#issuecomment-294350544

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-04-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 SRS开源服务器 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档