流媒体服务器

nginx(nginx-rtmp-module)+ obs 实现直播

优点:

  1. obs的跨平台性非常好,代码质量也非常高,功能非常完善和强大,基本上大部分的pc端的直播产品都是基于obs开发来的。
  2. nginx + obs这套环境搭载非常简单,加上代码编译基本上一天之类怎么都弄完了
  3. nginx-rtmp-module 代码可读性非常强。

缺点:

  1. 延迟太高了,局域网测试基本上都是10s的延迟
  2. nginx-rtmp-module还是只能是demo级的解决方案,如果要做成产品,必须要改修改很多地方,网上也有比较好的基于nginx-rtmp-module的开源方案,个人比较推荐nginx-http-flv-module

整体的架构

  1. 一些非流媒体数据,比如传输一些二进制文件,所以会需要自定义媒体服务转发服务。
  2. 第三方的流媒体服务更多是做cdn,解决延迟和并发的问题,阿里,百度,网易都有提供,百度的延迟很高,不推荐。

发现的问题:

  1. nginx-rtmp-module导致cpu 100%

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    static ngx_int_t
    ngx_rtmp_mp4_parse(ngx_rtmp_session_t *s, u_char *pos, u_char *last)
    {
    uint32_t *hdr, tag;
    size_t size, nboxes;
    ngx_uint_t n;
    ngx_rtmp_mp4_box_t *b;

    while (pos != last) {
    if (pos + 8 > last) {
    ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
    "mp4: too small box: size=%i", last - pos);
    return NGX_ERROR;
    }

    hdr = (uint32_t *) pos;
    size = ngx_rtmp_r32(hdr[0]);

    //部分视频的size可能为0,只有视频没有音频流
    if(0 == size) return NGX_ERROR;
    //导致while死循环,添加这行代码解决

    tag = hdr[1];

    if (pos + size > last) {
    ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
    "mp4: too big box '%*s': size=%uz",
    4, &tag, size);
    return NGX_ERROR;
    }

    b = ngx_rtmp_mp4_boxes;
    nboxes = sizeof(ngx_rtmp_mp4_boxes) / sizeof(ngx_rtmp_mp4_boxes[0]);

    for (n = 0; n < nboxes && b->tag != tag; ++n, ++b);

    if (n == nboxes) {
    ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
    "mp4: box unhandled '%*s'", 4, &tag);
    } else {
    ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
    "mp4: box '%*s'", 4, &tag);
    b->handler(s, pos + 8, pos + size);
    }

    pos += size;
    }

    return NGX_OK;
    }

找问题的方法,perf可以找到占用cpu的函数

1
2
3
4
#原来不是内置的程序,之前有安装过,使用yum安装
yum -y install perf
#使用方法
perf top -p "nginx work process的pid"

nginx配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
events {
worker_connections 1024;
}

rtmp {
server {
listen 1935;
application live {
live on;
}
}
}

http {

开源方案存在的问题主要是,延迟,和稳定性,点播对各种稀奇古怪媒体文件的兼容性处理,并发,cdn的问题可以选一家好点的云主机厂商解决。

easydarwin + EasyPusher

优点:

  1. easydarwin 支持Windows、Linux、macOS平台,代码质量很高,本身是基于苹果开源的 Darwin Streaming Server的go语言重写版本,算是把 Darwin Streaming Server重新又维护了起来,并增加了非常多的实用功能,分为商业版本和开源版本
  2. EasyPusher也提供了Android,iOS,PC客户端,并且开源
  3. 局域网延迟比起ng要小很多,大概就1-2s
  4. 有web端的管理后台
  5. 商用产品非常多,最开始是基于摄像头,监控项目发展而来的,稳定性方面没什么问题。

缺点:

  1. 商业版本功能强大,但是要收费。

整体的架构

甲方要求

  1. 局域网内pc端画面同步到移动端,延迟100毫秒内,他们现有产品我实测只有20毫秒,不知道他们自己测试过没有,我自己搭建的开源方案简单优化只有要1.4s

  2. 甲方现有方案已经没有人维护了,要找人继续搞起走。

  3. 如果这个外包能成功接下来,我再来分析一把他们的源码,感觉真心写的不错,把延迟控制的这么小,单从安装包来看,应该是用c/c++写的,没有用c#,qt这些框架。

  4. 最初我很武断的认为延迟在100ms内是很难的事情,虽然是局域网,结果就是啪啪打脸,对技术还是不够严谨。