iOS开发网络知识

基于docker搭建nginx+rtmp+hls(ffmpeg)直播服务

最开始的时候有尝试手动搭,但是问题无数,而且使用体验并不好,本次使用docker搭建

docker环境

docker的安装这里不做记录,网上有很多教程,而且这个很少出问题

安装nginx+rtmp

  • nginx-rtmp github :https://github.com/tiangolo/nginx-rtmp-docker
  • 这里使用docker仓库里tiangolo/nginx-rtmp的,如果不需要更改配置的话,直接拉下来运行即可。
# 拉取镜像
docker pull tiangolo/nginx-rtmp
# 根据镜像运行容器
docker run -d -p 1935:1935 --name nginx-rtmp tiangolo/nginx-rtmp
  • 但是有时,我们需要自定义nginx-rtmp服务器的设置,需要映射nginx-rtmp中的video到容器外部,那样需要制作我们自己的docker文件和nginx.conf。

Dockerfile

FROM tiangolo/nginx-rtmp
COPY nginx.conf /etc/nginx/nginx.conf

nginx.conf 这里开启了普通的rtmp推流 和 hls推流。hls推流会把flv文件切片生成多个ts。

worker_processes auto;
rtmp_auto_push on;
events { }

# 多个端口 直播流配置
rtmp {
  server {
    listen 1936;
    application live {
      live on;
      # 非常重要, 设定让ngnix断开阻塞中的连接, 才能触发exec_record_done
      # 以及客户端的LFLiveKit reconnectCount自动重新连接才会好用
      drop_idle_publisher 5s;
            #record all;
            #record_path /tmp;
            #record_max_size 10485760K;
            #record_unique off;
            #record_append on;
    }
  }
}

rtmp {
  server {
    #端口
    listen 1935;

    # RTMP 直播流配置
    application rtmplive {
      # 非常重要, 设定让ngnix断开阻塞中的连接, 才能触发exec_record_done
      # 以及客户端的LFLiveKit reconnectCount自动重新连接才会好用
      drop_idle_publisher 5s;
      live on;
    }

    # HLS 直播流配置
    application hls {
      live on;
      record all;
      record_path /tmp;
      record_max_size 10485760K;
      record_unique off;
      record_append on;
      hls on;
      hls_path /tmp;
      hls_fragment 5s;
    }
  }
}

# HLS 拉流配置 http://123.57.164.21:8080/hls/cs.m3u8
http {
  server {
    listen 8080;

    location /hls {
      types {
        application /vnd.apple.mpegurl m3u8;
        video /mp2t ts;
      }
      #访问权限开启,否则访问这个地址会报403
      autoindex on;
      #视频流存放地址,与上面的hls_path相对应,这里root和alias的区别可自行百度
      alias /tmp;
      expires -1;
      add_header Cache-Control no-cache;
      #防止跨域问题
      add_header 'Access-Control-Allow-Origin' '*';
      add_header 'Access-Control-Allow-Credentials' 'true';
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
      add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
    }
  }
}

把Dockerfile和nginx.conf放在同级目录,CD到这个目录,运行下面的命令,创建镜像和运行容器。

//创建容器
docker build -t nginx-rtmp .

//运行容器。注意这里面开启了1935推流端口 和 8080拉流端口。
docker run -d -p 1935:1935 -p 8080:8080 -v /tmp/video:/tmp --privileged=true --name nginx-rtmp nginx-rtmp
注意:-v /tmp/video:/tmp 的意思是把容器内部的/tmp文件夹 映射到外部/tmp/video 文件夹。这样在容器外部就能看到视频直播的文件了。特别需要注意 /tmp/video 文件夹的权限设置成777.

然后我们可以用一些推流工具,来进行推流直播,比如手机端的易推流。我们也可以自己开发工具来推流,比如IOS的话,可以用LFLiveKit框架,进行视频Rtmp推流。

然后可以使用VLC, 或者易推流来拉流。我们也可以自己开发工具来推流,比如IOS的话,可以用Ijkplayer框架,来进行Rtmp视频拉流。如果是hls拉流的话,原生AVPlayer就能直播播放出来(AVPlayer原生支持HLS)。

我们可以看到推流到服务器以后,在服务器上的tmp目录下,生成flv 和 很多ts切片文件。

因为ngnix启动了hls,所以我们可以通过hls来拉流。通过html,直接用safari浏览器就可以打开观看(hls拉流地址:http://123.57.164.21:8080/hls/cs.m3u8)。

html 代码

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8"> 
<title>HTML5播放视频</title> 
</head>
<body>
 
<video width="352" height="288" controls>
  <source src="http://123.57.164.21:8080/hls/cs.m3u8" type="application/vnd.apple.mpegurl">
  浏览器不支持 video 标签。
</video>
</body>
</html>

附录:Rtmp 和 HLS对比

注意:这样其实存在一个问题,推流是由本地推到服务器,拉流也是本地从服务器上拉,这样会多耗一倍的带宽,最好的解决方案是,由服务器进行推流,终端进行拉流,所以下面继续安装ffmpeg进行推流

安装ffmpeg进行本地推流

这里使用docker仓库里tiangolo/nginx-rtmp的,直接拉下来运行即可

# 拉取镜像
docker pull jrottenberg/ffmpeg
# 根据镜像运行容器
docker run -it --name app_ffmpeg -p 8080:8080 -v /home/app_ffmpeg/:/mnt/app/ --entrypoint=‘bash’ jrottenberg/ffmpeg
# 把文件导入到docker容器目录中
docker cp /usr/video/a.mp4 app_ffmpeg:/tmp/workdir
# 查看容器,启动容器,进入容器
docker ps -a
docker start app_ffmpeg
docker attach app_ffmpeg
# 然后就可以推流啦(这里就可以使用局域网IP进行推流)
ffmpeg -re -stream_loop -1 -i a.mp4 -vcodec copy -acodec copy -f flv rtmp://172.17.10.10:1935/live/cs