https://blog.csdn.net/liuhongxiangm/article/details/106923734
https://www.jianshu.com/p/9f2fb27062cb
https://www.jianshu.com/u/e978e5624a8c
https://www.jianshu.com/p/5d77641b17b2
https://tech.souyunku.com/?p=43607
https://github.com/open-webrtc-toolkit
https://blog.csdn.net/liuhongxiangm/article/details/106924834
https://blog.csdn.net/impingo/article/details/104911067
https://github.com/open-webrtc-toolkit/owt-server/issues
Open WebRTC Toolkit(OWT) Server User Guide
https://software.intel.com/sites/products/documentation/webrtc/conference/
https://cloud.tencent.com/developer/article/1453567
https://www.jianshu.com/p/0aea0fe8d992
https://zhuanlan.zhihu.com/p/72810939?from_voters_page=true
https://blog.csdn.net/impingo/article/details/104344621
https://blog.piasy.com/2019/04/14/OWT-Server-Quick-Start/index.html
https://github.com/winlinvip/owt-docker#debug
https://github.com/winlinvip/owt-docker
https://github.com/winlinvip/owt-docker/blob/master/CodeVideo.md#gdb-debug
https://cloud.tencent.com/developer/article/1614507
报错
gyp ERR! stack Error: EEXIST: file already exists, mkdir '/home/test/code/dddd/owt-server/source/agent/video/videoMixer/videoMixer_sw/b
scripts/installDeps.sh --only svt_hevc
参考
https://github.com/open-webrtc-toolkit/owt-server/issues/378
https://blog.piasy.com/2019/12/14/OWT-Server-Data-Flow-and-Recording/index.html
视频数据的流程为:
MediaSink::deliverVideoData ->
VideoFrameConstructor::deliverVideoData_ -> // (1)
ViEReceiver::ReceivedRTPPacket -> // (2)
RtpReceiverImpl::IncomingRtpPacket -> // (3)
ViEReceiver::OnReceivedPayloadData -> // (4)
VideoReceiver::IncomingPacket ->
VCMReceiver::InsertPacket -> // (5)
VideoReceiver::Decode -> // (6)
VideoFrameConstructor::Decode -> // (7)
FrameSource::deliverFrame ->
VideoFramePacketizer::onFrame -> // (8)
VideoFramePacketizer::receiveRtpData -> // (9)
WebRtcConnection::deliverVideoData_ -> // (10)
WebRtcConnection::sendPacket ->
WebRtcConnection::write ->
DtlsTransport::write // (11)
要点如下:
VideoFrameConstructor
有两个关键成员:webrtc::ViEReceiver m_videoReceiver
和 webrtc::vcm::VideoReceiver m_video_receiver
;webrtc::ViEReceiver
有两个关键成员:RtpReceiver rtp_receiver_
和 webrtc::vcm::VideoReceiver video_receiver_
;m_video_receiver
和 video_receiver_
指向同一个对象;VideoFrameConstructor::deliverVideoData_
里调用 ViEReceiver::ReceivedRTPPacket
,进而把 RTP 包交给 RtpReceiver
,由其负责 RTP 解包逻辑;RtpReceiverImpl::IncomingRtpPacket
调用 RTPReceiverVideo::ParseRtpPacket
(RTPReceiverStrategy
接口的实现),其中会根据不同的 payload type,创建不同的 RtpDepacketizer
去提取载荷内容;ViEReceiver::OnReceivedPayloadData
;VideoReceiver::IncomingPacket
,进而交给 VCMReceiver::InsertPacket
,进而交给了 jitter buffer;VideoFrameConstructor::deliverVideoData_
里调用完 m_videoReceiver->ReceivedRTPPacket
后,还会调用 m_video_receiver->Decode
,以从 jitter buffer 中取出已完整收到的视频帧(未解码);VideoFrameConstructor
还实现了 webrtc::VideoDecoder
接口,在 VideoFrameConstructor::OnInitializeDecoder
中会把自己注册给 webrtc::vcm::VideoReceiver
,所以调用 VideoReceiver::Decode
实际上会调用到 VideoFrameConstructor::Decode
;当然,VideoFrameConstructor
只是做视频数据的转发,无需实现真正的解码逻辑;通过这一「伪解码」的过程,OWT 就利用 WebRTC 的 VCM 来实现了视频 RTP 的解包过程,拿到了完整的视频帧(未解码);FrameDestination
实现类为 VideoFramePacketizer
,故视频帧就送到了 VideoFramePacketizer::onFrame
;其中需要实现视频帧的 RTP 封包逻辑,它是调用 webrtc::RtpRtcp
类来实现的,需要指出的是,调用 m_rtpRtcp->SendOutgoingData
时,第一个参数传的一律都是 webrtc::kVideoFrameKey
,这是因为这个参数在 WebRTC H.264 封包的实现代码里并未使用,所以这里图省事就这么传了(这一点是请教 OWT 研发人员后得到的解答);VideoFramePacketizer::init
函数中创建 webrtc::RtpRtcp
时,设置了 outgoing_transport
为 WebRTCTransport
对象(core/owt_base/WebRTCTransport.h
),故 RTP 封包完成后,会调用到 WebRTCTransport<dataType>::SendRtcp
,进而调用到 RTPDataReceiver::receiveRtpData
(即 VideoFramePacketizer::receiveRtpData
,VideoFramePacketizer
实现了 RTPDataReceiver
接口,并在构造函数里创建 WebRTCTransport
时传入了自己);VideoFramePacketizer
的 video_sink_
是订阅端的 WebRtcConnection
,故欲发送的视频数据就到了 WebRtcConnection::deliverVideoData_
里;DtlsTransport
发送给订阅端;搞清楚了音视频数据的转发流程后,我们发现 OWT 对音视频 RTP 包做了解包和重新封包。其实音频倒也谈不上解包和封包,因为音频数据编码后都比较小,一个 RTP 包就能容纳,所以没有像视频那样复杂的封包和解包逻辑。
但实际上 SFU 是不需要做 RTP 解包的,收到发布端的 RTP 包后直接转发给订阅端即可,OWT 这里做解包,应该是给 MCU 功能用的。
经 OWT 官方指正,OWT 做 RTP 解包并非是为了 MCU 功能考虑,而是一个基础设计原则:
将传输层事务在接入节点终结掉,媒体在集群中流转以“媒体帧”为封装单元,所有操作均在“帧交互层”以上进行。
SFU 是否组帧,效果上并没有简单明确的好坏之分:
端到端的全程延迟取决于每一帧什么时候被完整拼出来,而不是第一个包什么时候到达。理论上看并不会因为中间组过一次帧而显著增加“最后一块拼图”的到达时间,增加的只是将收齐的rtp包序列拼装成帧及将帧打成包序列的CPU计算过程的时间,这个时间一般是毫秒以内。另一方面将传输拆成帧接力的两段的话,可以比盲转更早发现丢包并请求重传,实际上是帮助减小了“最后一块拼图”的延迟。但实际弱网环境时刻在变化,很难模拟,需要实际测试一下效果,并调整各阶段的对抗手段,来达到相对较好的抗丢包效果。
https://blog.piasy.com/2020/05/05/VSCode-Remote-Debug-in-Docker/index.html
Author: Ran;
Date: 2019-08-27;
本文在编写时使用的版本为 4.2,现在 OWT 可能已经发布发更新的版本,如果您想使用更新的版本,请仔细阅读相关文档。
https://github.com/open-webrtc-toolkit/owt-deps-webrtc
https://github.com/open-webrtc-toolkit
推荐使用 Ubuntu 18.04
或 CentOS 7
。本文中使用 Ubuntu 18.04
。
10G 以上可用硬盘空间。由于在进行构建时需要大量内存,因此推荐内存大小为 4G。或内存与交换空间总计最少为 4G。平时使用时 2G 即可。
由于安装过程中需要安装大量的依赖,同时由于不可描述的政治原因,国内下载这此依赖库比较缓慢甚至无法下载。因此第一步进行代理的APT源与代理的配置。
APT源设置
编辑:
vim /etc/apt/source.list
将原有内容注释掉,再添加如下内容:
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
使用代理
执行:
export http_proxy=http://${代理HOST}:${代理PORT}
export https_porxy=http://${代理HOST}:${代理PORT}
注意:代理设置会在退出终端后消失。
你可以编辑:vim ~/.bashrc
添加上述命令以使每次登录时使代理生效。
配置Git代理
由于Git的代理设置是独立的,因此要手动设置。
执行:
git config --global http.proxy http://${代理HOST}:${代理PORT}
git config --global https.proxy http://${代理HOST}:${代理PORT}
以上设置是会持续失效的。当需要取消设置代理时,执行:
git config --global --unset http.proxy
git config --global --unset https.proxy
执行:
git clone https://github.com/open-webrtc-toolkit/owt-server.git
会在当前文件夹下生成包含源代码的owt-server
文件夹。
切换分支(可选)
在owt-server/
目录下。
使用4.2.x
分支的代码进行开发。
切换到该分支。
执行:
git checkout 4.2.x
查看状态:
git status
可以看到我们已经在4.2.x
分支了。
在owt-server/scripts/
目录下。
该目录包含安装时所需的脚本文件。
执行:
./installDepsUnattended.sh
会自动安装所需的一切依赖。由于国内网络原因,可以一次无法安装完成。
手动恢复安装(可选)
复制 installDepsUnattended.sh
:
cp installDepsUnattended.sh installRestDeps.sh
编辑:
vim installRestDeps.sh
文件中的这一部分:
if [[ "$OS" =~ .*centos.* ]]
then
. installCentOSDeps.sh
if [ "$NIGHTLY" != "true" ]; then
installRepo
installYumDeps
fi
elif [[ "$OS" =~ .*ubuntu.* ]]
then
. installUbuntuDeps.sh
if [ "$NIGHTLY" != "true" ]; then
install_apt_deps
fi
fi
install_node
check_proxy
if [ "$NIGHTLY" != "true" ]; then
if [ "$DISABLE_NONFREE" = "true" ]; then
install_mediadeps
else
install_mediadeps_nonfree
fi
install_node_tools
install_zlib
install_libnice014
install_openssl
install_openh264
install_libre
install_libexpat
install_usrsctp
install_libsrtp2
install_licode
if [[ "$OS" =~ .*ubuntu.* ]]
then
install_svt_hevc
fi
fi
${NO_INTERNAL} || install_webrtc
是各个依赖的安装。你可以记录下每个安装成功依赖,并删去相应的部分。以供在安装中断后进行增量安装。(不会写shell只能用这种比较笨的方法)
在 owt-server/scripts/
目录下。
首先检查你的 Node
版本:
node -v
如果不为 8.15.0
,则执行:
nvm use 8.15
如果没有安装 nvm
,则执行:
./install_nvm.sh
然后再执行上一条命令。
构建.node库
在 owt-server/scripts/
目录下。
构建基于 Node
库 node-gyp
。整个过程完全自动。
执行:
./build.js
可以看到各个参数的说明。
首先来看各个可用的 build
目标:
./build.js -l
其各个目标的具体定义都在 ./build.json
中。
执行:
./build.js -t mcu -c
./scripts/build.js -t mcu --check --debug --rebuild
只构建软编解码的视频处理模块。添加 -c
参数会对生成的模块进行检查。
构建时会查找 build.json
中指示的路径下的 .gyp
文件。其中定义了构建模块所需的文件与编译选项等。
如果有某个模块检查没有通过,你可以只重建该模块:
./build.js -r -t ${目标模块} -c
打包Node模块
在 owt-server/scripts/
目录下。
与构建过程类似,执行:
./pack.js
查看各个参数说明。
查看各个可用的打包目标:
./pack.js -l
执行:
./pack.js -t all -i --sample-path ${样例目录}
打包所有模块。添加-i
参数以安装各个模块依赖的Node
模块。
打包会根据各个目标目录下的dist.json
文件进行。在查看各个可用目标时会打印出这些文件的路径。
${样例目录}说明见下。
生成的文件会在owt-server/dist/
目录下。
有关样例,你需要下载owt-client-javascript
项目。
在某个目录下:
git clone https://github.com/open-webrtc-toolkit/owt-client-javascript.git
下载该项目。
找到owt-client-javascript/src/samples/conference
目录。
将其完整路径填入${样例目录}。
以生成演示用的样例项目。
同样,你可以只打包只某个模块。
在owt-server/dist/bin/
目录下。
首先初始化MongoDB
与RabbitMQ
:
./init-all.sh
如果没有成功启动MongoDB
,则需要手动启动:
service mongodb start
然后再执行上一条命令。
此时会打印出 SampleServiceKey
与 SampleServiceID
。将其填入 owt-server/dist/extras/basic_sample/samplertcservice.toml
中的相应位置。如已填过,直接替换即可。
启动所有节点:
./start-all.sh
如果没有成功启动,可以检查 owt-server/dist/logs
下的日志。
访问 https://${HOST}:3004
以查看演示页面。由于使用了自验证证书,因此需要进行不安全访问确认操作。
关闭所有节点:
./stop-all.sh
重启所有节点:
./restart-all.sh
你可以只启动/重启/关闭某个节点。以下以启动video
节点为例。
./deamon.sh start video-agent
你可以打开deamon.sh
文件以看到有哪些节点以及这些节点的启动参数