GitChat·架构 | 如何从零开始搭建高性能直播平台?

RTMP理解 rtmp协议整体结构,注意事项,一般实现方法 阅读详情

GitChat 作者:七夜

前言

现在直播已经成为移动互联网时代一个新的重要流量入口,从YY、斗鱼到花椒直播,直播已经成为人们分享交流的新方式,应用场景众多,主要分为:

  • 金融类直播:金融直播可应用于实时解盘,在线专家讲座,专家在线直播技术分析、指导投资者等使用场景。

  • 大型赛事,演唱会类直播:可应用于大型演唱会,音乐会,游戏,体育赛事等类直播场景。

  • 互动类直播:娱乐类互动,如YY等。

  • 会议类直播:大型会议直播。

等4大类。在本文中,我将先从rtmp协议开始,一步步带领大家搭建一个简易高性能的直播平台。

RTMP协议详解

RTMP协议Real Time Message Protocol(实时信息传输协议)的首字母缩写,是由Adobe公司开发的一种用于解决多媒体数据传输流多路复用和分包的网络协议。它工作在TCP协议之上,因此是一种提供可靠交付的协议,在传输时不会出现丢包情况,从而保证了用户体验(QoE)。虽然TCP协议为了提供可靠交付付出了一些额外的开销做为代价,占用了一些带宽和处理器资源,但是随着网络带宽的提高和硬件的发展,这些开销会显得越来越微不足道。因此RTMP协议在为了有很好的发展前景。

官方定义:

The Real-Time Messaging Protocol (RTMP) was designed for

high-performance transmission of audio, video, and data between Adobe

Flash Platform technologies, including Adobe Flash Player and Adobe

AIR. RTMP is now available as an open specification to create products

and technology that enable delivery of video, audio, and data in the

open AMF, SWF, FLV, and F4V formats compatible with Adobe Flash

Player.

协议分类

  • RTMP协议工作在TCP之上,是应用层协议, 默认的端口是1935。

  • RTMPE在RTMP的基础上增加了加密功能。

  • RTMPT工作在HTTP之上,默认端口是80或443,可穿透防火墙。

  • RTMPS类似RTMPT,增加了TLS/SSL的安全功能。

  • RTMFP为RTMP协议的UDP版本。

虽然协议变种有很多,但实际在我们的直播应用中最常见的是原生的RTMP协议,因此本篇文章以该协议的1.0版本为基础,对其它演进协议感兴趣的同学可以关注本文的后续知识。

交互流程

RTMP的交互流程可以分为握手过程、控制命令传输与数据传输。

enter image description here

  • 握手过程

    RTMP 连接以握手开始,RTMP 握手由三个固定长度的块组成。客户端 (发起连接请求的终端) 和服务器端各自发送相同的三块。便于演示,本文将从客户端发送的这些块指定为 C0、C1 和 C2;将从服务器端发送的这些块分别指定为 S0、S1 和 S2。

    RTMP握手以客户端发送 C0 和 C1 块开始,客户端要等收到S1之后才能发送C2,客户端要等收到S2之后才能发送其他信息(控制信息和真实音视频等数据),服务端要等到收到C0之后发送S1, 服务端必须等到收到C1之后才能发送S2, 服务端必须等到收到C2之后才能发送其他信息(控制信息和真实音视频等数据)。以下为RTMP握手的时序图介绍。

    enter image description here

流程图中所提到的各种状态如下:

状态描述
未初始化客户端在C0中发送协议版本,如服务端支持,则回发送S0和S1,如果不能,则连接结束
版本发送客户端等待S1包,服务端等待C1包,当接收到想要的包,客户端发送C2,服务端发送S2,此时阶段变成了ACK的发送
ACK发送客户端和服务端分别等待S2和C2
握手完成客户端和服务交换消息

理论上来讲只要满足以上条件,如何安排6个Message的顺序都是可以的。但在实际实现中为了尽量减少通信的次数,客户端发送C0+C1,服务端发送S0+S1+S2,再客户端在发送C2结束握手。

enter image description here

  • 控制命令传输

    握手结束以后,RTMP协议进入控制命令传输过程,客户端通过发送connnect命令与服务器实现双向连接。连接成功后,通过发送createStream命令建立网络流。

  • 数据传输

    网络流建立成功后,推流(将直播内容推送至服务器的过程)过程会发送publish命令发布音视频内容,拉流(服务器已有直播内容,用指定地址进行拉取的过程)过程会发送play命令播放内容。

协议格式

URI格式

rtmpt://127.0.0.1/{app}/{stream_name}

  • {app}为音频/视频和其他内容定义的一个容器。
  • {stream_name}为具体的一个流名称。

消息(Message)格式

enter image description here

消息是RTMP协议中基本的数据单元,不能种类的消息包含有不能的消息类型(Message Type)。RTMP协议一共规范了十多种消息类型。其中类型为8,9的消息分别用于传输音频和视频数据。消息头包含以下信息:

  • Message Type: 消息类型,占用1个字节。

  • Length: 有效负载的字节数,占用3个字节。该字段是用大字节序表示的。

  • Timestamp: 时间戳,占用4个字节,用大字节序表示。

  • Message Stream Id: 消息流ID,标识消息所使用的流,用大字节序表示。

消息块格式

在网络上传输数据时,消息需要被拆分成较小的数据块才适合在相应的网络环境上传输。RTMP协议中规范了对消息拆分成消息块,每个消息块首部(ChunkHeader)有三部分组成:用于标识本块的ChunkBasicHeader,用于标识本块负载所属消息的ChunkMessageHeader,以及当时间戳溢出时才出现的ExtendedTimestamp。

消息分块

RTMP传输媒体数据的过程中,发送端首先把媒体数据封装成消息,然后把消息分割成消息块,最后将分割后的消息块通过TCP协议发送出去。接收端在通过TCP协议收到数据后,首先把消息块重新组合成消息,然后通过对消息进行解封装处理就可以恢复出媒体数据。

开源技术选型

目前直播服务器有开源和商业两种版本,商业版本主要又FMS(Flash Media Server)与Wowza。本文章仅针对开源版本做介绍,相应的开源项目主要分为Red5与 Nginx-Rtmp两类:

Red5

简介

GitHub:https://github.com/Red5/red5-server (1k+ stars)

enter image description here

Red5是一个采用Java开发开源的Flash流媒体服务器。它支持:把音频(MP3)和视频(FLV)转换成播放流; 录制客户端播放流(只支持FLV);共享对象;现场直播流发布;远程调用。Red5使用RTMP, RTMPT, RTMPS, 和RTMPE作为流媒体传输协议,在其自带的一些示例中演示了在线录制,flash流媒体播放,在线聊天,视频会议等一些基本功能。

官方给出的主要特性:
Red5 is an Open Source Flash Server written in Java that supports:

  • Streaming Video (FLV, F4V, MP4, 3GP)
  • Streaming Audio (MP3, F4A, M4A, AAC)
  • Recording Client Streams (FLV and AVC+AAC in FLV container)
  • Shared Objects
  • Live Stream Publishing
  • Remoting
  • Protocols: RTMP, RTMPT, RTMPS, and RTMPE

Additional features supported via plugin:

  • WebSocket (ws and wss)
  • RTSP (From Axis-type cameras)
  • HLS

安装与简单应用实例(Mac下安装)

前置条件(jdk已安装)。

enter image description here

  • 创建安装目录:

mkdir -p /Users/ypzdw/gitchat/rtmp/red5

  • 设置主目录环境变量:

export RED5_HOME=/Users/ypzdw/gitchat/rtmp/red5

  • 下载red5应用,并解压到RED5_HOME:

https://github.com/Red5/red5-server/releases/download/v1.0.7-RELEASE/red5-server-1.0.7-RELEASE.tar.gz

enter image description here

目录简介:由于 Red5 是在 Tomcat 中运行的,因此 Red5 项目与普通 JAVAEE 项目结构类似
conf:red5配置目录
lib:存放的是一些依赖jar包
weapps:用来存放应用程序,与tomcat下的webapps目录作用类似。

  • 运行:

cd /Users/ypzdw/gitchat/rtmp/red5
./red5.sh &

  • 简单实例

经过前面的介绍,这里将用red5介绍一个简单的实例。打开http://127.0.0.1:5080 出现red5 管理控制台。

enter image description here

选择”Publisher” demo,该项目提供了主播端与听课端。

enter image description here

主播端:“1”中 Name表示流名,publish可以发布一个直播。

enter image description here

直播收听端:“1”中Name为收听的流名;“2”中 Location为直播端地址;“3”中Log可以观察到整个直播的交流日志。

enter image description here

enter image description here

  • 停止应用:

cd /Users/ypzdw/gitchat/rtmp/red5
./red5-shutdown.sh

Nginx-Rtmp

Github:https://github.com/arut/nginx-rtmp-module (5k+ stars)

enter image description here

简介

俄罗斯人民开发的一款NGINX的流媒体插件,除了直播发布音视频流之外具备流媒体服务器的常见功能:

  • RTMP在线直播。

  • 基于HTTP的FLV/MP4 VOD点播。

  • HLS (HTTP Live Streaming) M3U8的支持。

  • 基于http的操作(发布、播放、录制)。

  • 可以很好的协同现有的流媒体服务器以及播放器一起工作。

  • 在线调用ffmpeg对流媒体进行转码。

  • H264/AAC音视频编码格式的支持。

  • linux/BSD/MAC系统的支持。

官方承诺的功能:

  • RTMP/HLS/MPEG-DASH live streaming
  • RTMP Video on demand FLV/MP4, playing from local filesystem or HTTP
  • Stream relay support for distributed streaming: push & pull models
  • Recording streams in multiple FLVs
  • H264/AAC support
  • Online transcoding with FFmpeg
  • HTTP callbacks (publish/play/record/update etc)
  • Running external programs on certain events (exec)
  • HTTP control module for recording audio/video and dropping clients
  • Advanced buffering techniques to keep memory allocations at a minimum level for faster streaming and low memory footprint
  • Proved to work with Wirecast, FMS, Wowza, JWPlayer, FlowPlayer, StrobeMediaPlayback, ffmpeg, avconv, rtmpdump, flvstreamer and many more
  • Statistics in XML/XSL in machine- & human- readable form
  • Linux/FreeBSD/MacOS/Windows

常用指令与语法

  • Core

    rtmp

    语法:rtmp { … }
    上下文:nginx根上下文
    描述:保存所有 RTMP 配置的块

    server

    语法:server { … }
    上下文:rtmp
    描述:声明一个 RTMP 实例。
    rtmp {
    server {
    }
    }

    listen

    语法:listen (addr[:port]|port|unix:path)
    上下文:server
    描述:给 NGINX 添加一个监听端口以接收 RTMP 连接。
    server {
    listen 1935;
    }

    application

    语法:application name { … }
    上下文:server
    描述:创建一个 RTMP 应用,application 名不支撑正则表达式。
    server {
    listen 1935;
    application myapp {
    }
    }

    timeout

    语法:timeout value
    上下文:rtmp, server
    描述:Socket 超时。这个值主要用于写数据时。
    timeout 60s;

    ping

    语法:ping value
    上下文:rtmp, server
    描述:RTMP ping 间隔。零值的话将 ping 关掉。RTMP ping 是一个用于检查活动连接的协议功能。发送一个特殊的包到远程连接,然后在 ping_timeout 指令指定的时间内期待一个回复。如果在这个时间里没有收到 ping 回复,连接断开。ping 默认值为一分钟。ping_timeout 默认值为 30 秒。
    ping 3m;
    ping_timeout 30s;

  • Access

    allow

    语法:allow [play|publish] address|subnet|all
    上下文:rtmp, server, application
    允许来自指定地址或者所有地址发布/播放。allow 和 deny 指令的先后顺序可选。
    allow publish 127.0.0.1;
    deny publish all;
    allow play 192.168.0.0/24;
    deny play all;

    deny

    语法:deny [play|publish] address|subnet|all
    上下文:rtmp, server, application
    描述:参考 allow 的描述。

  • Exec

    exec_push

    语法:exec_push command arg*
    上下文:rtmp, server, application
    描述:定义每个流发布时要执行的带有参数的外部命令。发布结束时进程终止。第一个参数是二进制可执行文件的完整路径。执行外部命令时可以使用参数替换:
    $name - 流的名字。
    $app - 应用名。
    $addr - 客户端地址。
    $flashver - 客户端 flash 版本。
    $swfurl - 客户端 swf url。
    $tcurl - 客户端 tc url。
    $pageurl - 客户端页面 url。也可以在 exec 指令中定义 Shell 格式的转向符用于写输出和接收输入。

    exec_pull

    与exec_push类似,主要工作在play端。

  • Live

    live

    语法:live on|off
    上下文:rtmp, server, application
    描述:切换直播模式,即一对多广播。
    live on;

    meta

    语法:meta on|off
    上下文:rtmp, server, application
    描述:切换发送元数据到客户端。默认为 on。
    meta off;

    interleave

    语法:interleave on|off
    上下文:rtmp, server, application
    描述:切换交叉模式。在这个模式下,音频和视频数据会在同一个 RTMP chunk 流中传输。默认为 off。
    interleave on;

    wait_key

    语法:wait_key on|off
    上下文:rtmp, server, application
    描述:使视频流从一个关键帧开始。默认为 off。
    wait_key on;

    wait_video

    语法:wait_video on|off
    上下文:rtmp, server, application
    描述:在第一个视频帧发送之前禁用音频。默认为 off。可以和 wait_key 进行组合以使客户端可以收到具有所有其他数据的视频关键帧。然而这通常增加连接延迟。您可以通过在编码器中调整关键帧间隔来减少延迟。
    wait_video on;

    publish_notify

    语法:publish_notify on|off
    上下文:rtmp, server, application
    描述:发送 NetStream.Publish.Start 和 NetStream.Publish.Stop 给用户。默认为 off。
    publish_notify on;

    drop_idle_publisher

    语法:drop_idle_publisher timeout
    上下文:rtmp, server, application
    描述:终止指定时间内闲置(没有音频/视频数据)的发布连接。默认为 off。注意这个仅仅对于发布模式的连接起作用(发送 publish 命令之后)。
    drop_idle_publisher 10s;

    sync

    语法:sync timeout
    上下文:rtmp, server, application
    描述:同步音频和视频流。如果用户带宽不足以接收发布率,服务器会丢弃一些帧。这将导致同步问题。当时间戳差超过 sync 指定的值,将会发送一个绝对帧来解决这个问题。默认为 300 ms。
    sync 10ms;

    play_restart

    语法:play_restart on|off
    上下文:rtmp, server, application
    描述:使 nginx-rtmp 能够在发布启动或停止时发送 NetStream.Play.Start 和 NetStream.Play.Stop 到每个用户。如果关闭的话,那么每个用户就只能在回放的开始和结束时收到这些通知了。默认为 on。
    play_restart off;

  • Record

    record

    语法:record [off|all|audio|video|keyframes|manual]*
    上下文:rtmp, server, application, recorder
    描述:切换录制模式。流可以被记录到 flv 文件。本指令指定应该被记录的:
    off - 什么也不录制
    all - 音频和视频(所有)
    audio - 音频
    video - 视频
    keyframes - 只录制关键视频帧
    manual - 用不自动启动录制,使用控制接口来启动/停止
    在单个记录指令中可以有任何兼容的组合键。
    record all;

    record_path

    语法:record_path path
    上下文:rtmp, server, application, recorder
    描述:指定录制的 flv 文件存放目录。
    record_path /tmp/rec;

    record_suffix

    语法:record_suffix value
    上下文:rtmp, server, application, recorder
    描述:设置录制文件后缀名。默认为 ‘.flv’。
    record_suffix _recorded.flv;
    录制后缀可以匹配 strftime 格式。以下指令
    record_suffix -%d-%b-%y-%T.flv
    将会产生形如 mystream-24-Apr-13-18:23:38.flv 的文件。所有支持 strftime 格式的选项可以在 strftime man page 里进行查找

    record_append

    语法:record_append on|off
    上下文:rtmp, server, application, recorder
    描述:切换文件附加模式。当这一指令为开启是,录制时将把新数据附加到老文件,如果老文件丢失的话将重新创建一个。文件中的老数据和新数据没有时间差。默认为 off。
    record_append on;

  • Relay

    pull

语法:pull url [key=value]*
上下文:application
描述:创建 pull 中继。流将从远程服务器上拉下来,成为本地可用的。仅当至少有一个播放器正在播放本地流时发生。
Url 语法:[rtmp://]host[:port][/app[/playpath]]。如果 application 找不着那么将会使用本地 application 名。如果找不着 playpath 那么就是用当前流的名字。
支持以下参数:
app:明确 application 名。
name:捆绑到 relay 的本地流名字。如果为空或者没有定义,那么将会使用 application 中的所有本地流。
tcUrl:如果为空的话自动构建。
pageUrl:模拟页面 url。
swfUrl:模拟 swf url。
flashVer:模拟 flash 版本,默认为 ‘LNX.11,1,102,55’。
playPath:远程播放地址。
live:切换直播特殊行为,值:0,1。
start:开始时间。
stop:结束时间。
static:创建静态 pull,这样的 pull 在 nginx 启动时创建。
如果某参数的值包含空格,那么你应该在整个 key=value 对周围使用引号,比如:’pageUrl=FAKE PAGE URL’。
pullrtmp://cdn2.example.com/another/a?b=1&c=d pageUrl=http://www.example.com/video.html swfUrl=http://www.example.com/player.swf live=1;

push

语法:push url [key=value]*
上下文:application
描述:push 的语法和 pull 一样。不同于 pull 指令的是 push 推送发布流到远程服务器。

push_reconnect

语法:push_reconnect time
上下文:rtmp, server, application
描述:在断开连接后,在 push 重新连接前等待的时间。默认为 3 秒。
push_reconnect 1s;

session_relay

语法:session_relay on|off
上下文:rtmp, server, application
描述:切换会话 relay 模式。在这种模式下连接关闭时 relay 销毁。当设置为 off 时,流关闭,relay 销毁,这样子以后另一个 relay 可以被创建。默认为 off。
session_relay on;

  • Notify

    on_connect

    语法:on_connect url
    上下文:rtmp, server
    描述:设置 HTTP 连接回调。当客户分发连接命令一个连接命令时,一个 HTTP 请求异步发送,命令处理将被暂停,直到它返回结果代码。当 HTTP 2XX 码(成功状态码)返回时,RTMP 会话继续。返回码 3XX (重定向状态码)会使 RTMP 重定向到另一个从 HTTP 返回头里获取到的 application。否则(其他状态码)连接丢弃。
    注意这一指令在 application 域是不允许的,因为 application 在连接阶段还是未知的。
    HTTP 请求接收到一些参数。在 application/x-www-form-urlencoded MIME 类型下使用 POST 方法。以下参数将被传给调用者:
    call=connect。
    addr - 客户端 IP 地址。
    app - application 名。
    flashVer - 客户端 flash 版本。
    swfUrl - 客户端 swf url。
    tcUrl - tcUrl。
    pageUrl - 客户端页面 url。
    除了上述参数以外,所有显式传递给连接命令的参数也由回调发送。你应该将连接参数和 play/publish 参数区分开。播放器常常有独特的方式设置连接字符串不同于 play/publish 流名字。

    on_play

    语法:on_play url
    上下文:rtmp, server, application
    描述:设置 HTTP 播放回调。每次一个客户分发播放命令时,一个 HTTP 请求异步发送,命令处理会挂起 - 直到它返回结果码。之后再解析 HTTP 结果码。
    HTTP 2XX 返回码的话继续 RTMP 会话。
    HTTP 3XX 返回码的话 重定向 RTMP 到另一个流,这个流的名字在 HTTP 返回头的 Location 获取。
    HTTP 请求接收到一些个参数。在 application/x-www-form-urlencoded MIME 类型下使用 POST 方法。以下参数会被传送给调用者:
    call=play。
    addr - 客户端 IP 地址。
    app - application 名。
    flashVer - 客户端 flash 版本。
    swfUrl - 客户端 swf url。
    tcUrl - tcUrl。
    pageUrl - 客户端页面 url。
    name - 流名。

    on_publish

    语法:on_publish url
    上下文:rtmp, server, application
    描述:同上面提到的 on_play 一样,唯一的不同点在于这个指令在发布命令设置回调。不同于远程 pull,push 在这里是可以的。

    on_done

    语法:on_done url
    上下文:rtmp, server, application
    描述:设置播放/发布禁止回调。上述所有适用于此。但这个回调并不检查 HTTP 状态码。

    on_play_done

    语法:on_publish_done url
    上下文:rtmp, server, application
    描述:等同于 on_done 的表现,但只适用于播放结束事件。

    on_publish_done

    语法:on_publish_done url
    上下文:rtmp, server, application
    描述:等同于 on_done 的表现,但只适用于发布结束事件。

    on_record_done

    语法:on_record_done url
    上下文:rtmp, server, application, recorder
    描述:设置 record_done 回调。除了普通 HTTP 回调参数它接受录制文件路径。
    on_record_done http://example.com/recorded;

    on_update

    语法:on_update url
    上下文:rtmp, server, application
    描述:设置 update 回调。这个回调会在 notify_update_timeout 期间调用。如果一个请求返回结果不是 2XX,连接禁止。这可以用来同步过期的会话。追加 time 参数即播放/发布调用后的秒数会被发送给处理程序。
    on_update http://example.com/update;

    notify_update_timeout

    语法:notify_update_timeout timeout
    上下文:rtmp, server, application
    描述:在 on_update 回调之间的超时设置。默认为 30 秒。
    notify_update_timeout 10s;
    on_update http://example.com/update;

    notify_update_strict

    语法:notify_update_strict on|off
    上下文:rtmp, server, application
    描述:切换 on_update 回调严格模式。默认为 off。当设置为 on 时,所有连接错误,超时以及 HTTP 解析错误和空返回会被视为更新失败并导致连接终止。当设置为 off 时只有 HTTP 返回码不同于 2XX 时导致失败。
    notify_update_strict on;
    on_update http://example.com/update;

    notify_relay_redirect

    语法:notify_relay_redirect on|off
    上下文:rtmp, server, application
    描述:使本地流可以重定向为 on_play 和 on_publish 远程重定向。新的流名字是 RTMP URL 用于远程重定向。默认为 off。
    notify_relay_redirect on;

    notify_method

    语法:notify_method get|post
    上下文:rtmp, server, application, recorder
    描述:设置 HTTP 方法通知。默认是带有 application/x-www-form-urlencoded 的 POST 内容类型。在一些情况下 GET 更好,例如如果你打算在 nginx 的 http{} 部分处理调用。在这种情况下你可以使用 arg_* 变量去访问参数。
    notify_method get;
    Statistics
    statistics 模块不同于本文列举的其他模块,它是 NGINX HTTP 模块。因此 statistics 指令应该位于 http{} 块内部。

    rtmp_stat

    语法:rtmp_stat all
    上下文:http, server, location
    描述:为当前 HTTP location 设置 RTMP statistics 处理程序。RTMP statistics 是一个静态的 XML 文档。可以使用 rtmp_stat_stylesheet 指令在浏览器中作为 XHTML 页面查看这个文档。
    http {
    server {
    location /stat {
    rtmp_stat all;
    rtmp_stat_stylesheet stat.xsl;
    }
    location /stat.xsl {
    root /path/to/stat/xsl/file;
    }
    }
    }

    rtmp_stat_stylesheet

    语法:rtmp_stat_stylesheet path
    上下文:http, server, location
    描述:添加 XML 样式表引用到 statistics XML 使其可以在浏览器中可视。

测试

我所在的公司的直播业务中,前期也是采用red5,但是随着用户数的不断增长,red5完全不能支撑整个业务。问题集中爆发在几个方面:

  • 对于单主播,听者超过400人时,CPU超过90%(主机为4核,32G)。

  • 人数越多,音质,画面卡顿很多,不稳定,用户体验很差。于是我们决定对red5进行替换,对各种选型进行了调研,并在red5相同环境下做了测试,发现nginx-rtmp的性能非常突出,最终选用nginx-rtmp替换Red5,到目前为止,已经无故障运行近一年。附nginx-rtmp测试数据:

ServerCPU内存连接数带宽延迟
nginx-rtmp8.3%13MB500100Mbps0.8秒
nginx-rtmp27.3%19MB1000200Mbps0.8秒
nginx-rtmp50.2%37MB2500500Mbps0.8秒
nginx-rtmp70.2%61MB4000650Mbps0.8秒

从测试结果可以得知,nginx-rtmp模块运行稳定,单CPU4000人时负载只有70%,已经接近网卡流量的极限,比Red5 在性能上高一个数量级。

快速实现一个直播平台

实战前准备
  • 硬件

阿里云ECS: CPU:2核心,内存:8G,硬盘:40G

enter image description here

  • 操作系统

CentOS 7.2 x86_64 Linux

  • 配置服务器

    超过1024的连接数测试需要打开linux的限制。且必须以root登录和执行

    设置连接数:ulimit -HSn 10240

    查看连接数:

    enter image description here

  • 域名

    非必须,如没有,可以直接使用ip也可以。但是正式环境中为了减少收听端对ip地址的依赖性,一般会使用域名而非ip地址来连接直播服务器。本文使用域名为datahq.cn.

    申请域名:国内可以选择万网或新网;国外的name.com和godaddy.com口碑不错。

    域名备案:国外的服务器和网站在上线前都需要经过工信部备案和公安部备案;如果在阿里云上购买ECS可以直接使用其的免费备案服务。

    建立直播子域名:

    enter image description here

  • 客户端

    为方便测试,本文使用Red5 作为直播的客户端

  • 直播端

    目前最好用的直播端软件是OBS(Open Broadcaster Software)。下载地址是:

    https://obsproject.com/download

    快速设置:

    视频的清晰度与码率和品质有关,码率大,品质高,那么视频的清晰度就高,同时,对带宽的要求也越大。详细的参数设定参考如下:

  • 在来源中新增“视频捕捉设备”,并设置分辨率,您可以从分辨率选择最接近的一项。本例分辨率为1280x720,如下图所示

    enter image description here

  • 通过“设置”->“视频”中设置压缩分辨率,您可以从压缩分辨率选择与自己期望最接近的一项。本例期望分辨率为960x540,如下图所示

    enter image description here

  • 直播推流设置,打开“设置”->”流”,URL输入推流地址的URL,流名称输入推流的名称,如下图所示

    enter image description here

实战
  • 架构方案

    目前,我们线上的直播架构为:

    enter image description here

  • 支撑线上峰值近10万人,并无故障运行一年有余。

  • 配置中心会定期刷新直播端与收听端APP的路由信息。

  • 直播端APP推流到Master集群。

  • 由于nginx-rtmp本身不支持集群,因此我们在架构时没有采用从Master集群Forward推流到Slave集群的方式,而是设计了当收听端拉流到slave服务器集群时,如果不存在该流,就会从Master集群主动拉取流的架构,解决了直播集群的大规模并发问题。

  • 该架构在大规模并发情况下,比Master推流到Slave流的架构节省了很大的带宽。

  • 除此之外我们对nginx-rtmp进行了源代码的修改,支撑了一些如合成,转码,高级录制等功能。

本文为了各位同学能够更快的掌握如何搭建的过程,因此没有采用以上的架构,相信通过下面的实践,各位也能够搭建相应的架构。

enter image description here

架构图中黄色标识了我们要使用的直播server。

  • 编译与部署

    创建源码存储目录:mkdir -p /root/rtmp/src。

    进入源码目录:

cd /root/rtmp/src

下载nginx源码并解压,注意nginx-rtmp对nginx版本的选择限制较多,在选择时为了少踩不需要的坑,建议根据官方提示选择对应的nginx 版本,如图本文选择nginx-1.11.5:

enter image description here

wget http://nginx.org/download/nginx-1.11.5.tar.gz
tar -zxvf nginx-1.11.5.tar.gz

下载nginx-rtmp模块源码:

wget https://github.com/arut/nginx-rtmp-module/archive/v1.1.10.tar.gz
tar -zxvf v1.1.10.tar.gz

编译nginx,如果需要调试消息则打开–with-debug:

./configure –add-module=/root/rtmp/src/nginx-rtmp-module-1.1.10 –with-debug
make
make install

enter image description here

默认编译到路径:

/usr/local/nginx

验证编译是否成功:

enter image description here

创建录制文件存储目录:

mkdir -p /usr/local/nginx/files

rtmp 模块配置(nginx.conf):

enter image description here

本文所采用的配置如下

user  root;//使用root用户运行nginx
worker_processes  1;//指明了nginx要开启的进程数,一般等于cpu的总核数,如果没有出现io性能问题,最好不要修改

error_log  logs/error.log  debug;//错误日志存放路径;日志级别为debug,调试用。
events {
    worker_connections  1024;//每个工作进程的最大连接数量;
}


http {
    include       mime.types;//设定mime类型,类型由mime.type文件定义
    default_type  application/octet-stream;
    client_max_body_size 3m;//设定通过nginx上传文件的大小
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';//日志格式设置
    access_log  logs/access.log  main;//访问日志存储路径
    sendfile        on;//指定 nginx 是否调用sendfile 函数(zero copy 方式)来输出文件
    keepalive_timeout  65;//keepalive超时时间
    server {//配置虚拟机
        listen       8080;//监听端口
        server_name  rtmp.datahq.cn 59.110.237.245;//名称
    location /stat{//配置统计页面路径
            rtmp_stat all;
            rtmp_stat_stylesheet stat.xsl;
        }
    location /stat.xsl{//统计模板路径
            root /usr/local/nginx/conf;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}
rtmp{
    server{
        listen 0.0.0.0:1935;//监听端口
        ping 30s;//活动连接检查周期
        application live{//应用名
        live on;//打开直播模式
        meta copy; //是否发送直播端元数据信息
        session_relay on;//打开会话转发模式
        drop_idle_publisher 10s;//10s没有推流,自动断开直播端
        sync 10ms;//同步流时间阀值
        record_append on;//打开直播流录制追加模式
        record_path /usr/local/nginx/files;//录制文件地址
        record all;//打开录制功能
        }
    }
}

拷贝统计模板到ngin配置目录:

cp /root/rtmp/src/nginx-rtmp-module-1.1.10/stat.xsl /usr/local/nginx/conf/

启动直播服务器:

cd /usr/local/nginx/sbin && ./nginx

打开统计页面控制台:

http://rtmp.datahq.cn:8080/stat

enter image description here

统计表各属性说明为:
clients:连接数
live streams:流名
codec:编码
bits:分辨率
size:视频画面大小
fps:每秒传输帧数
freq:音频率
chan:音频声道
State:流状态
Time:流活动时间
其它4个为输入与输出流的每秒传输速率。

  • 测试直播

    打开OBS,推流至rtmp://rtmp.datahq.cn/live,流名为demo

    打开red5,从rtmp://rtmp.datahq.cn/live拉取直播流,流名为demo

    enter image description here
    打开直播统计后台:如果看到已经有一个推流,一个拉流,并有数据传输时,说明整个直播链路已经畅通。

    enter image description here

    查看直播录制文件:

    enter image description here

    此时看下系统的负载:可以发现CPU,内存的负载都很低,可以忽略不计。

    enter image description here

  • 上线

    到本节为止,一个简单的直播平台就搭建好了,接下来我们要做的就是上线,因为没有上线,一切都是零。下面是我们在上线过程中遇到的一些坑,供各位同学参考:

    • 系统打开文件数默认太低,造成部分用户连接不上。

    • 遇到活动高峰,网络带宽成为瓶颈,造成收听用户卡顿很多。在生产环境中需要时刻关注是否升级带宽。

    • 上线尽量选择在没有直播的时候进行。

总结

今天给大家分享了直播平台搭建的一些知识,涉及到了rtmp协议,直播选型的一些注意点,大规模直播架构,nginx-rtmp直播服务器实战搭建等。如果各位有直播的需要,可以顺着本文的一些知识点进行实战。

第一次写Chat,不知道效果如何,如果大家有兴趣,我们在后续推出nginx模块开发与nginx-rtmp的分享,感谢大家的参与。


实录:《七月:从零搭建高性能直播平台实战解析》

【GitChat达人课】

  1. 前端恶棍 · 大漠穷秋 :《Angular 初学者快速上手教程 》
  2. Python 中文社区联合创始人 · Zoom.Quiet :《GitQ: GitHub 入味儿 》
  3. 前端颜值担当 · 余博伦:《如何从零学习 React 技术栈 》
  4. GA 最早期使用者 · GordonChoi:《GA 电商数据分析实践课》
  5. 技术总监及合伙人 · 杨彪:《Gradle 从入门到实战》
  6. 混元霹雳手 · 江湖前端:《Vue 组件通信全揭秘》
  7. 知名互联网公司安卓工程师 · 张拭心:《安卓工程师跳槽面试全指南》

这里写图片描述

程序员用GitChat赚钱的6种方法 GitChat出来没多久,我就开始使用了,算是有一些经验,今天给大家分享下用GitChat赚钱的6种方法 GitChat平什么 先说下GitChat这个平台,其主页是:https://gitbook.cn/,微信中可以直接搜索“GitChat”找到它的服务号,关注后可以使用。现在还有对应的APP,也可以下载使用。 GitChat是针对技术人的知识付费平台,创始人是谢工,中途被优快云收购,现在属于... 阅读详情

相关推荐

[网络安全自学篇] 四十二.DNS欺骗和钓鱼网站原理详解及防御机理

这是作者的网络安全自学教程系列,主要是关于安全工具和实践操作的在线笔记,特分享出来与博友们学习,希望您们喜欢,一起进步。前文分享了中间人攻击或ARP欺骗攻击,从ARP原理到局域网配置进行描述。这篇文章将详细讲解DNS欺骗(DNS投毒)及钓鱼网站原理知识,并通过Ettercap工具复现某购物网站的钓鱼漏洞,本文的重点是让您对ARP欺骗、DNS欺骗和钓鱼攻击有一定认识。真心希望这篇基础文章对您有所帮助,也欢迎大家讨论。

杨秀璋的专栏 2万+

GitChat,一个记录技术和躺着赚零花钱的免费平台

目录 NEW项目九:小白和你聊秋招 NEW项目八:用 PyTorch 框架做深度学习会如此简单 项目一:一个项目带你快速入门 Qt Creator 项目二:手把手实践 YOLO 深度残差神经网络拐点检测 项目三:从凸优化理解高维特征下的深度学习 项目四:YOLO V3 一步步训练自己的目标检测 项目五:机器学习必备的5个脚本工具详解 项目六:YOLO V1和YOLO V3深度学习目...

钱多多先森 2496

Unity - gamma space下还原linear space效果

还有头发之后的 (头发没有处理完整,因为使用 ASE 连连看练出来的,使用 surface shader,虽然可以生成一下 vert, frag 的方式在修改,但是我懒得去修改了,这样就是 PBR 的 BRDF 里面的部分曲线是不一样的,所以可以看到头发有一些差异)其实上面的代码判断 是否有分量 > 1.0f 的方式来判断是否 HDR 是不太合理的,因为不同的贴图格式的编码方式不同。还有比较隐蔽的一些颜色相关的常量值 (比如PBR中的 绝缘体的 F0 常量值,等等)

Jave.Lin 的学习笔记 2830

【亲测免费】 GitChat 使用指南

GitChat 使用指南 项目介绍 GitChat 是一个基于人工智能的聊天机器人,专为简化您对 GitHub 仓库的交互而设计。通过 GitChat,您能够向您的代码库提问并获得相关解答,无论是为了快速了解一个新项目还是在组织内部提供一个辅助工具,帮助工程师高效地查询私有仓库信息。该聊天机器人利用了 Vercel 的 Next.js 框架,并集成 Google 认证以及用户会话管理,以提供流畅的...

gitblog_00753的博客 908

STC15W204S最小系统开发指南:从串口通讯到自动热加载全流程

本文详细介绍了STC15W204S最小系统的完整开发流程。从芯片资源解析、最小系统搭建、串口通讯驱动编写(使用Timer2生成波特率),到实现基于魔术值触发的自动热加载功能,并最终集成Keil与STC-ISP软件,构建高效的自动化开发工作流,显著提升嵌入式调试效率。

a1b2c的博客 391

Python经常遇到导入xlwings就出错,如何解决

Python经常在导入xlwings时遇到错误。有人建议尝试重装或升级xlwings,但这些操作后仍然无法解决导入错误问题。

felix_8的博客 1740

GitChat · 架构 | 如何从零开始搭建高性能直播平台?

来自 GitChat 作者:七夜 前言 现在直播已经成为移动互联网时代一个新的重要流量入口,从YY、斗鱼到花椒直播,直播已经成为人们分享交流的新方式,应用场景众多,主要分为: 金融类直播:金融直播可应用于实时解盘,在线专家讲座,专家在线直播技术分析、指导投资者等使用场景。 大型赛事,演唱会类直播:可应用于大型演唱会,音乐会,游戏,体育赛...

weixin_34015566的博客 351

论文阅读:Visual Relationship Detection with Language Priors

Visual Relationship Detection with Language Priors(ECCV2016) 文章   尽管大多数的relationship并不常见,但是它们的object和predicate却更频繁地独立出现。paper用这个insight分别独立训练训练object和predicate的模型,然后再进行组合来预测relationship。Visual relatio...

Kivee的博客 2877

微信移动端页面开发之视频

随着抖音和各大直播平台迅猛发展,视频逐渐成为了我们日常生活的一部分。在前端开发领域,PC 端和移动端网站播放视频,已经是家常便饭的事情。 然而,作为国内最大的交流平台微信,在上面进行视频的前端开发却有着不少的困难和兼容性问题。那么如何才能在微信上面,顺利地做出效果棒、兼容性好并且让用户满意的页面呢?本场 Chat 就来说说微信中视频的前端开发: H5 Video 标签简单介绍 微信中的 Vide...

GitChat 1689

DeepSeek-V4 本地部署实战指南:4套方案从入门到企业级(附RTX 5090实测数据)

V4-Flash 便宜是便宜,输入 1 元/M token,输出 2 元/M token,但量大了还是肉疼。V4-Pro 更离谱,输入 12 元/M token,输出 24 元/M token,这价格要是天天调用,月账单轻松破万。用 4-bit 量化跑 V4-Flash,显存占用 ~22GB,延迟 ~80ms/token,并发能到 2-3 路。换句话说,同样的硬件,能跑更长的上下文、更大的并发。Flash 是「小而美」,一张 RTX 4090/5090 就能跑,门槛低,效果够用。

datayx的文章 9861

GoPro官方API实战:从蓝牙配对到Wi-Fi流媒体,构建跨平台控制应用

本文详细解析了GoPro官方API的开发实践,涵盖蓝牙配对、Wi-Fi流媒体控制等关键技术。通过实战案例,指导开发者如何构建跨平台控制应用,解决设备发现、指令解析、视频流传输等核心问题,并分享Android平台迁移经验与常见问题排查方法。

weixin_30727835的博客 397

编程语言底层之数据结构

课程简介 本课程从开发人员需要了解的基础数据结构出发,带着这些基础知识去学习一门编程语言是怎么实现的(内含视频演示),并且思考为什么这么实现,反过来再系统完善知识体系,并运用到实际工作中。通过这门课的学习将体验思考的过程,以便后面更加深入的了解学习其他开发语言知识。 相关联的系列达人课:《编程语言底层之函数执行》和《编程语言底层之系统和并发》。 作者介绍 李永京,从事互联网后端系统开发,擅长高并发...

GitChat 1824

MIKE水动力笔记17_MIKE文件转shp、统计每个单元格的面积

MIKE的工具箱中自带一个转shp的工具,然后可以拖进ArcGIS中很方便的统计每个单元格的面积和每个网格点的水深。

晏长街的博客 4152

Gitchat

本文首发于Gitchat,原作者王晓雷,经作者同意授权转发。转载请联系作者或GitChat。 背景 很多人问,对话式交互系统就是语音交互么?当然不是。语音交互本身真的算不上新概念,大家可能都给银行打过电话,“普通话服务请按1,英文服务请按2……返回上一层请按0” 这也算对话式交互系统,我想大家都清楚这种交互带来的用户体验有多低效。那么对话式交互系统已经可以取代人类提供服务了么?也没

yuanshuai1136的博客 3003

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

GitChat 项目使用教程

GitChat 项目使用教程 1. 项目的目录结构及介绍 GitChat 项目的目录结构如下: GitChat/ ├── app/ │ ├── components/ │ ├── lib/ │ ├── public/ │ ├── .env.example │ ├── .eslintrc.json │ ├── .gitignore │ ├── LICENSE │ ├─...

gitblog_00131的博客 596

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

GitChat·管理 | 一篇文章读懂项目管理中的精髓

GitChat 作者:白云城主 更多IT技术分享,尽在微信公众号:GitChat 技术杂谈 做任何事情都有方法和经验可循,这就是真正意义上的捷径。对于项目管理来说,就是把握好三个点,战略、战术、实战。未来仍然属于我们当中那些人仍然愿意弄脏双手的少数分子。

技术杂谈 1760

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Git-Chat 项目使用教程

Git-Chat 项目使用教程 1. 项目的目录结构及介绍 git-chat/ ├── README.md ├── bin/ │ └── git-chat ├── lib/ │ └── git-chat.rb ├── config/ │ └── settings.yml ├── spec/ │ └── git-chat_spec.rb └── Gemfile README.md...

gitblog_00771的博客 518

GitChat在做什么

GitChat是知识经济的新物种,面向 IT 的新产品~

安晓辉生涯——聚焦程序员的职业规划与成长 2万+

GitChat·安全 | 搭建并使用便携式 4G/LTE 伪基站研究移动安全

GitChat 作者:Seeker 本文介绍如何使用 SDR + 开源 4G/5G 项目 OpenAirInterface + 便携式掌上电脑,搭建一台可以手持或者放在口袋里随身携带,随时随地开始渗透攻击的开源伪基站

技术杂谈 4580

只需三分钟,即可轻松搭建流媒体服务器自己搞直播!支持OBS Studio、XSplit等流媒体文件,

使用OBS进行推流,点击通道,可以看到正在推流的地址信息,比如http://10.0.8.2:8080/live/01.m3u8。(推流格式:协议://ip地址:协议端口/live/名字 如http://10.0.8.2:8080/live/01.m3u8 )点击通道,可以看到正在推流的地址信息,比如http://10.0.8.2:8080/live/01.m3u8。播放(拉流)地址:rtmp://10.0.8.3:1935/live/01。rtmp://IP+端口/live/名字2。

qq_28768477的博客 1万+

Nginx-rtmp 直播媒体实时流实现

这段时间在搭建一个IPCamera项目服务器。视频点对点通话,客户端会查看设备端的音视频实时流。为了省流量,是通过P2P进行穿透。但是由于NAT设备的原因和IPV4的枯竭。有些设备是无法进行点对点传输实时流。所以需要进行服务器转发。这里为了快速实现原型,同时参考现在主流的流媒体协议。发现很多使用的是RTMP协议。下图是总体设计图,为了整合多平台,会自建RTMP流媒体服务器和使用云厂商SaaS的RTMP流媒体服务。但是由于有时候会传输一些非流媒体数据,需要传输一些二进制文件,所以会需要自定义媒体转发服务。

irainsa的博客 1644

优快云邀您加入GitChat,让知识变现!

GitChat 是什么? GitChat GitChat 是一个知识分享平台,我们的目的是通过这款产品改变 IT 知识的学习方式,让专业读者获得自主选择权,让知识分享者获得收益。 Chat 是什么? 一场 Chat 包含一篇文章和一场为该文章的读者和作者定制的专属线上交流活动。 博主们如果觉得自己的内容有价值,希望自己的内容可以影响更多的小伙伴,那就别犹豫,发布 Chat,接受预订,让读者...

优快云 官方博客 6万+

GitChat · 人工智能 | 人工智能产品测试方法探索

GitChat 作者:孙高飞 关注微信公众号:GitChat 技术杂谈 ,这里一本正经的讲技术 我想跟大家讨论一下要如何测试人工智能相关的产品。我们知道人工智能是出了名的难测试,不论是我们以前在互联网就经常看到的内容推荐系统,还是金融领域常用的信息分类系统。测试介入的都不多。

技术杂谈 5160
上一篇: 除了深度学习,机器翻译还需要啥?
下一篇: GitChat·前端 | Vue 组件库实践和设计
软件供应链安全
软件供应链安全 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 1万+粉丝 347原创
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值