直播点播系统快速搭建指南.md

Posted by lizhao on 07-09,2019

直播点播系统快速搭建指南

[toc]

我之前将自己做过的直播遇到的问题记录下来,发到 CSDN 上面,发现踩到这些坑的人挺多的,或许自己写的格式或者其他方面不是讲的特别清楚,导致挺多人还是加我 QQ 我一些内容。所以这边重新整理了一份完整版供大家参考。

阅读前先看看

  1. 小黑框是指 cmd 窗口
  2. 按住 shift 的时候右键,可以快速打开当前目录的小黑框
  3. 在小黑框中的一些正在执行指令(如 FFmpeg),强制关闭可以使用 Ctrl+C
  4. 打开小黑框,输入 ipconfig ,可以查看自己电脑的 IP

IPv4 地址 . . . . . . . . . . . . : 192.168.3.134

  1. 我当前电脑的 ip 是 192.168.3.134,后面遇到 192.168.3.134 的时候,记得替换成自己的
  2. 全局变量,这些目录,请替换成自己的路径
    1. String ROOT_PATH = "E:\workdir\doc\csdn";// 根路径
    2. String SAFEWARE_PATH = ROOT_PATH + "\safeware";// 安装包路径
    3. String RELEASE_PATH = ROOT_PATH + "\release";// 配置好的的软件
    4. String NGINX_WEB_PATH = RELEASE_PATH + "\Nginx-web";// Nginx-web 路径
    5. String NGINX_GRYPHON_PATH = RELEASE_PATH + "\Nginx-Gryphon";// Nginx-RTMP 服务器路径
    6. String FFMPEG_PATH = RELEASE_PATH + "\FFmpeg";// FFmpeg 软件路径
  3. 希望大家把各个环节先测试好,然后再去集成测试。不然出错都不知道哪一块出错
  4. 里面用到的所有文件我都上传了,可以从以下途径获取
  5. 我发现原来的简介没写清楚是 windos 环境下的,如果因为这个问题的话,希望联系我退款哈(这个购买了无法直接从系统退款)

系统流程图

使用 FFmpeg 推送视频流信息到 Nginx 服务器上 Nginx 会导出 RTMP 和 M3U8 这 2 种视频源,然后使用 videojs ,在 GitChat 上面无法显示识别该格式,后附图片

graph LR
A(FFmpeg)-->B(Nginx)
B(Nginx)-->C(RTMP)
B(Nginx)-->D(M3U8)
C(RTMP)-->E(videojs)
D(M3U8)-->E(videojs)

enter image description here

快速测试

打开 release/quick-test,看到下面几个文件,直接双击一遍

a-start-Nginx-web.bat
b-start-Nginx-Gryphon.bat
c-start-FFmpeg-push-RTMP.bat
d-start-FFmpeg-push-M3U8.bat
e-open-VLC.bat

可以使用 VLC 播放

RTMP://127.0.0.1:1935/live/stream
http://127.0.0.1:11242/hls/video.M3U8

也可以直接打开下面的网页

M3U8 的网页记得点击一下网页的二维码,就能播放了

RTMP 的网页记得将网页 flash 打开,打开方法可以看"常见问题"-"11"

http://127.0.0.1:11240/video-local/videojs-M3U8/M3U8.html
http://127.0.0.1:11240/video-local/videojs-RTMP-above6/RTMP.html
http://127.0.0.1:11240/video-local/videojs-RTMP-above6/RTMP.html

目录结构

E:\workdir\doc\csdn
├─release
│  ├─FFmpeg
│  │  │  LICENSE.txt
│  │  │  README.txt
│  │  │  
│  │  ├─bin
│  │  │      FFmpeg.exe					FFmpeg 程序
│  │  │      ffplay.exe
│  │  │      ffprobe.exe
│  │  │      
│  │  └─doc
│  │          
│  ├─Nginx-Gryphon
│  │  │  Nginx.exe						Nginx 启动程序
│  │  ├─conf
│  │  │  │  Nginx-win-RTMP.conf			Nginx-RTMP 配置
│  │  │  └─ Nginx-win.conf
│  │  │      
│  │  ├─temp   
│  │  │  └─app
│  │  │      
│  │  │      
│  │  └─Nginx-RTMP-module				Nginx 插件--RTMP 模块
│  │   	 │  AUTHORS
│  │     │  config
│  │     └─ stat.xsl
│  │          
│  ├─Nginx-web							Nginx 服务器,用来存放 videojs
│  │  │  Nginx.exe						Nginx 启动程序
│  │  │  
│  │  ├─conf
│  │  │      Nginx.conf					Nginx 配置文件
│  │  ├─html
│  │  │  │  50x.html
│  │  │  │  index.html
│  │  │  │  
│  │  │  └─video						videojs 目录
│  │  │      ├─common
│  │  │      │      qrcode.jpg
│  │  │      ├─doc
│  │  │      ├─other
│  │  │      │      M3U8.html
│  │  │      │      test.html
│  │  │      │      videojs-contrib-hls.js
│  │  │      │      videojs-contrib-hls.min.js
│  │  │      │      videojs-ie8.min.js
│  │  │      │      videojs-media-sources.min.js
│  │  │      │      videojs.hls.min.js
│  │  │      │      
│  │  │      ├─videojs-M3U8				videojs--M3U8 测试
│  │  │      │      M3U8.html
│  │  │      │      video-js.css
│  │  │      │      video.js
│  │  │      │      videojs-http-streaming.js
│  │  │      │      
│  │  │      ├─videojs-RTMP-above6		videojs--6.0 版本以上的 RTMP 测试
│  │  │      │      RTMP.html
│  │  │      │      video-js.css
│  │  │      │      video-js.swf
│  │  │      │      video.js
│  │  │      │      videojs-flash.js
│  │  │      │      
│  │  │      └─videojs-RTMP-below6		videojs--6.0 版本以下的 RTMP 测试
│  │  │              RTMP.html
│  │  │              video-js.css
│  │  │              video-js.swf
│  │  │              video.js
│  │  └─temp
│  │      ├─client_body_temp
│  │      ├─fastcgi_temp
│  │      ├─proxy_temp
│  │      ├─scgi_temp
│  │      └─uwsgi_temp
│  ├─quick-test			
│  │      ├─a-start-Nginx-web.bat
│  │      ├─b-start-Nginx-Gryphon.bat
│  │      ├─c-start-FFmpeg-push-RTMP.bat
│  │      ├─d-start-FFmpeg-push-M3U8.bat
│  │      └─e-open-VLC.bat			
│  └─VLC
│      └─VLC.exe						VLC 启动程序
│       
│                  
└─safeware
		FFmpeg.zip						FFmpeg 安装包
		Nginx-Gryphon.zip				ngin-RTMP 服务器
		Nginx-RTMP-module.rar			Nginx 插件--RTMP
		Nginx-web.zip					Nginx 服务器,用来存放 videojs
		orange.mp4						测试视频
		VLC-3.0.5-win32.exe				VLC32 位系统安装包
		VLC-3.0.5-win64.exe				VLC64 位系统安装包

Nginx

基本使用

enter image description here

介绍

Nginx (engine x) 是一个高性能的 HTTP 和反向代理服务,也是一个 IMAP/POP3/SMTP 服务。

安装

使用方式非常的简单,从官网下载(http://Nginx.org/en/download.html)或者直接使用目录下的安装包 Nginx-web.rar,解压到目录 RELEASE_PATH(看图 1 序号 1)

运行

打开小黑框,切到 NGINX_WEB_PATH 目录(Nginx.exe 所在目录),输入 Nginx,即可运行(看图 1 序号 2.3)

按指定的配置文件运行

同时也支持按照指定的配置文件进行

Nginx -c conf/Nginx.conf 
测试方法

打开浏览器,输入 127.0.0.1,如果能出来一个页面,就是成功运行了(看图 1 序号 5)

关闭

找到进程 Nginx,一次会有 2 个进程,先右键关掉下面的那个,然后关掉上面那个 (看图 1 序号 4)

配置文件

在 NGINX_WEB_PATH\conf 目录下面,有一个 Nginx.conf,里面可根据实际情况进行配置,把一些内容删掉,就留下这些了。

主要看下 http--server

worker_processes  1; #允许生成的进程数,默认为 1
# events 块:配置影响 Nginx 服务器或与用户的网络连接。
# 有每个进程的最大连接数,选取哪种事件驱动模型处理连接请求,
# 是否允许同时接受多个网路连接,开启多个网络连接序列化等。
events {
    worker_connections  1024; # 最大连接数,默认为 512
}

# http 块:可以嵌套多个 server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。
# 如文件引入, mime-type 定义,日志自定义,是否使用 sendfile 传输文件,连接超时时间,单连接请求数等。
http {
    include       mime.types;   #文件扩展名与文件类型映射表
    default_type  application/octet-stream; #默认文件类型,默认为 text/plain
    sendfile on;   #允许 sendfile 方式传输文件,默认为 off,可以在 http 块,server 块,location 块。
    keepalive_timeout 65;  #连接超时时间,默认为 75s,可以在 http, server, location块。

	# server 块:配置虚拟主机的相关参数,一个 http 中可以有多个 server。
    server {
        listen       80; # 监听的端口
        server_name  localhost;#监听地址      

		# location 块:配置请求的路由,以及各种页面的处理情况。
        location / {
            root   html;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

在本项目中的使用

(可以先不操作这一块内容)

在项目中,将这个作为 web 容器,用来运行显示播放网页的。把 videojs 章节的最终文件 video 拷贝到 NGINX_WEB_PATH/html 文件夹下(可忽略)。

修改配置文件中的端口 http--server--listen,端口前后一致就行,这里设置的是 11240

listen       11240; # 监听的端口

修改配置后,需要重启下 Nginx,如果没开那就启动就好

然后访问 http://127.0.0.1:11240,有 Nginx 界面出来就可以关掉 Nginx,暂时用不到了。

Nginx-RTMP

这里我们使用的是配置了 RTMP 模块的 Nginx

Nginx 本身是在 linux 上面的,要是想加入 RTMP 模块,可以下载源码放到 linux 上面编译,或者在 windows 上面直接搭建编译环境。本身也为这个项目发愁,也就没必要搞这些事情了。这边是直接使用其他小哥搞的一个软件 Nginx-win-Gryphon,里面集成了挺多的模块。不过我们用到的是 RTMP 模块,满足我们的需求的。

基本使用

这个本质还是 Nginx,请看上一节

环境搭建

  1. 已经有了 Nginx-Gryphon.zip(http://Nginx-win.ecsds.eu/download/ 选择 Nginx 1.7.11.3 Gryphon)和 Nginx-RTMP-module.zip(https://github.com/arut/Nginx-RTMP-module)(自己下载或者我提供的哈)

  2. 解压 Nginx-Gryphon.zip 文件到 RELEASE_PATH 下

  3. 解压 Nginx-RTMP-module.zip 到 NGINX_GRYPHON_PATH 下

注意有可能有 2 层 Nginx-RTMP-module,记得删掉其中一层

这时候可以启动运行 Nginx-Gryphon 下,看是否能成功运行

  1. 复制 NGINX_GRYPHON_PATH/conf/Nginx-win.conf,命名为 Nginx-win-RTMP.conf,直接在该文件中进行以下修改,或者复制我下面这份配置内容到文件
    • 在 http 同级添加 RTMP{},这里可选择 RTMP 或 hls
    • 开启 RTMP 需要在 http-server 下添加 location/stat 和 location/control 和 location/stat.xsl
    • 开启 hls 需要在 http-server 下添加 location /hls
    • 修改端口 11242
worker_processes  2;
events {
    worker_connections  8192;
}

# 修改处--RTMP 和 hls 配置
RTMP {
    server {
        listen 1935;
        chunk_size 4000;
		# 开启 RTMP
        application live {
             live on;
        }
		# 开启 M3U8
		application hls {    
			live on;    
			hls on;    
			hls_path /temp/app;    
			hls_fragment 5s;    
        }    
    }
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        off;
    server_names_hash_bucket_size 128;

    client_body_timeout   10;
    client_header_timeout 10;
    keepalive_timeout     30;
    send_timeout          10;
    keepalive_requests    10;

    server {
        listen       11242; # 修改出 11242
        server_name  localhost;

		
		# 修改处--hls 配置
		location /hls {    
			#server hls fragments
			add_header Access-Control-Allow-Origin *;
		    add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept";
		    add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
			types{    
				application/vnd.apple.mpegurl M3U8;    
				video/mp2t ts;    
			}    
			alias /temp/app;    
			expires -1;    
        }   
		
		# 修改处--RTMP 配置 下面 3 个
        location /stat {
            RTMP_stat all;
            RTMP_stat_stylesheet stat.xsl;
        }
        location /stat.xsl {
            root Nginx-RTMP-module/;
        }
        location /control {
            RTMP_control all;
        }

		# For Naxsi remove the single # line for learn mode, or the ### lines for full WAF mode
        location / {
            root   html;
            index  index.html index.htm;
        }
     
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

    }
}
  1. 在 NGINX_GRYPHON_PATH/temp 文件下面新建文件夹,重命名为 app

  2. 启动 Nginx-Gryphon,使用指定配置文件的方式

Nginx -c conf/Nginx-win-RTMP.conf

本项目中的用法

搭好环境,然后把下面的 FFmpeg 看完,在"推流测试(FFmpeg+Nginx-RTMP 测试)"中写到

FFmpeg

FFmpeg 的名称来自 MPEG 视频编码标准,前面的“ FF ”代表“ Fast Forward ”,FFmpeg 是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。可以轻易地实现多种视频格式之间的相互转换。

安装

直接解压安装包(http://FFmpeg.org/download.html),解压文件到 RELEASE_PATH 下

测试

小黑框切到 FFMPEG_PATH/bin 路径下面,输入以下指令,查看是否有版本显示

FFmpeg -version

显示内容

E:\workdir\doc\csdn\release\FFmpeg\bin>FFmpeg -version
FFmpeg version N-93005-gd92f06eb66 Copyright (c) 2000-2019 the FFmpeg developers
built with gcc 8.2.1 (GCC) 20181201
configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt
libavutil      56. 26.100 / 56. 26.100
libavcodec     58. 44.100 / 58. 44.100
libavformat    58. 26.100 / 58. 26.100
libavdevice    58.  6.101 / 58.  6.101
libavfilter     7. 48.100 /  7. 48.100
libswscale      5.  4.100 /  5.  4.100
libswresample   3.  4.100 /  3.  4.100
libpostproc    55.  4.100 / 55.  4.100

运行

前面说到这个工具可以对音视频进行处理,搞一个视频 SAFEWARE_PATH 下面有一个测试视频 orange.mp4,就拿他开刀了,输入指令试试:

这个路径记得改成自己的视频所在位置
FFmpeg -y -ss 10 -i E:\workdir\doc\csdn\safeware\orange.mp4 -to 15 -acodec copy -vcodec copy -copyts E:\workdir\doc\csdn\safeware\output.mp4

对比一下,发现剪辑出来 10 到 15 的视频

指令说明

下面是几个常见指令,我列出的这些只是这篇文章够用了,其实 FFmpeg 指令很多,我全列出来也没意思,需要的话去查查文档

-i 输入内容
-f 设定输出格式
-acodec: 音频选项, 一般后面加 copy 表示拷贝
-vcodec: 视频选项,一般后面加 copy 表示拷贝
-vprofile baseline //H.264 有四种画质级别,分别是 baseline, extended, main, high : 
					//   1 、 Baseline Profile :基本画质。支持 I/P 帧,只支持无交错( Progressive )和 CAVLC ; 
					 //  2 、 Extended profile :进阶画质。支持 I/P/B/SP/SI 帧,只支持无交错( Progressive )和 CAVLC ;(用的少) 
					 //  3 、 Main profile :主流画质。提供 I/P/B 帧,支持无交错( Progressive )和交错( Interlaced ), 
					 //   也支持 CAVLC 和 CABAC 的支持; 
					 //  4 、 High profile :高级画质。在 main Profile 的基础上增加了 8x8 内部预测、自定义量化、 无损视频编码和更多的 YUV 格式; 
					//H.264 Baseline profile 、 Extended profile 和 Main profile 都是针对 8 位样本数据、 4:2:0 格式(YUV)的视频序列。在相同配置情况下,High profile ( HP )可以比 Main profile ( MP )降低 10%的码率。 
					//根据应用领域的不同,Baseline profile 多应用于实时通信领域,Main profile 多应用于流媒体领域,High profile 则多应用于广电和存储领域。
					//fmpeg 如何控制 profile&level
-ar  freq 设置音频采样率					
-an		静音
-ac channels 设置通道 缺省为 1					
-strict strictness 跟标准的严格性
-r 表示每一秒几帧 
-y 生成出来的文件强制替换
-ss 开始时间
-to 结束时间

Java 调用 FFmpeg

这边用的方法就是很捞的 runtime.exec

这一块内容,等部署完毕,再回头看,现在看只是增加复杂度

package com.lizhaoblog.cutfilm;

public class FFmpegTest {

    private static final String FFMPEG_PATH = "E:\\workdir\\doc\\csdn\\release\\FFmpeg\\bin\\FFmpeg";// FFMPEG 的路径
    private static final String VIDEO_INPUT = "RTMP://live.hkstv.hk.lxdns.com/live/hks2";// FFMPEG 的路径
    private static final String VIDEO_OUTPUT = "RTMP://192.168.3.134:1935/live/stream";// FFMPEG 的路径

    public static void main(String[] args) throws Exception {
        Runtime runtime = Runtime.getRuntime();
        String cmdStr = buildCmdStr(FFMPEG_PATH, VIDEO_INPUT, VIDEO_OUTPUT);
        Process process = runtime.exec(cmdStr);
    }

    private static String buildCmdStr(String FFmpegPath, String input, String out) {
        //       E:\workdir\doc\csdn\release\FFmpeg\bin\FFmpeg -i RTMP://live.hkstv.hk.lxdns.com/live/hks2
        //       -f flv -acodec copy -vcodec copy RTMP://192.168.3.134:1935/live/stream
        StringBuilder cmdStr = new StringBuilder();
        cmdStr.append(FFmpegPath);
        cmdStr.append(" -i ");
        cmdStr.append(input);
        cmdStr.append(" -f flv -acodec copy -vcodec copy ");
        cmdStr.append(out);
        return cmdStr.toString();
    }
//    E:\workdir\doc\csdn\release\FFmpeg\bin\FFmpeg -i RTMP://live.hkstv.hk.lxdns.com/live/hks2           -f flv -acodec copy -vcodec copy RTMP://192.168.3.134:1935/live/stream
    private void deadCode() {
        /*
         * 返回对创建的进程的管理对象
         */
        //Process p = runtime.exec("mspaint.exe");
        //Thread.sleep(10000);
        //杀死刚才创建的进程,打开资源管理器,10 秒钟后进程消失
        //p.destroy();
        //        Process p = runtime.exec("mspaint.exe");
        //        String cmdStr = getCmdStr("E:\\app-data\\renren-download\\Friends-Season1\\", "friends-s01e01", 0, 300, 1);
        //        //        String cmdStr = " D:\\workdir\\program\\FFmpeg-ori\\bin\\FFmpeg -y -ss 00:00:00 -i E:\\app-data\\renren-download\\Friends-Season1\\friends-s01e01.mp4  -to 450 -acodec copy -vcodec copy  -copyts output.mp4";
        //        System.out.println(cmdStr);
        //        Process process = runtime.exec(cmdStr);
    }
}

VLC 软件

VLC 多媒体播放器(最初命名为 VideoLAN 客户端)是 VideoLAN 计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持 DVD 影音光盘,VCD 影音光盘及各类流式协议。它也能作为 unicast 或 multicast 的流式服务器在 IPv4 或 IPv6 的高速网络连接下使用。它融合了 FFmpeg 计划的解码器与 libdvdcss 程序库使其有播放多媒体文件及加密 DVD 影碟的功能。

在这里我们主要是用来测试播放网络串流

安装

SAFEWARE_PATH 下面有一个安装包 VLC-3.0.6-winxx.exe,运行,无限下一步就安装完成

测试

从下面的网络流中选择 2 个(一个 M3U8 一个 RTMP),记得要选择能播放的 enter image description here

推流测试(FFmpeg+Nginx-RTMP 测试)

  1. 启动 Nginx-Gryphon(带配置文件)
Nginx -c conf\Nginx-win-RTMP.conf
  1. 使用 FFmpeg 推送 RTMP 视频流,指令如下

输入信号为 RTMP://live.hkstv.hk.lxdns.com/live/hks2

输出信号为 RTMP://192.168.3.134:1935/live/stream

其他配置:音视频不转码,直接复制

E:\workdir\doc\csdn\release\FFmpeg\bin\FFmpeg -i RTMP://live.hkstv.hk.lxdns.com/live/hks2 -f flv -acodec copy -vcodec copy RTMP://192.168.3.134:1935/live/stream
  1. 使用 VLC 播放网络串流,能够播放表示 RTMP 推流这一块通过测试
RTMP://192.168.3.134:1935/live/stream
  1. 使用 FFmpeg 推 hls 视频流,指令如下

输入信号为 RTMP://live.hkstv.hk.lxdns.com/live/hks2

输出信号为 RTMP://192.168.3.134:1935/hls/videohttp://192.168.3.134:11242/hls/video.M3U8

(这里可以回头看 Nginx 的配置文件 Nginx-win-RTMP.conf 中的 RTMP-server-hls 和 http-server-hls,就能理解了)

其他配置:音视频不转码,直接复制

E:\workdir\doc\csdn\release\FFmpeg\bin\FFmpeg -i RTMP://live.hkstv.hk.lxdns.com/live/hks2 -f flv -acodec copy -vcodec copy RTMP://192.168.3.134:1935/hls/video
  1. 使用 VLC 播放网络串流,能够播放,表示么 M3U8 推流这一块通过测试
RTMP://192.168.3.134:1935/hls/video
http://192.168.3.134:11242/hls/video.M3U8

videojs

我们网页播放视频,使用到了 videojs。

video.js 是一款基于 HTML5 的网络视频播放器。它支持 HTML5 和 Flash 视频,以及 YouTube 和 Vimeo (通过插件)。支持在桌面和移动设备上播放视频。这个项目从 2010 年中期开始,现已经在 40 多万个网站上使用。

播放

这边提供了三个测试文件,对应的分别是 videojs6.0 以上播放 RTMP(仅 pc 端),videojs6.0 以下播放 RTMP(仅 pc 端),videojs 播放 M3U8 格式(pc+手机) enter image description here

通用
引入 lib

引入 video.js,video-js.css

根据实际情况引入不同的插件 videojs-flash/videojs-http-streaming

videojs 有一个免费的 cdn,可以直接在 html 的 script 中引入

<!-- unpkg -->
<link href="https://unpkg.com/video.js/dist/video-js.css" rel="stylesheet">
<script src="https://unpkg.com/video.js/dist/video.js"></script>

<!-- cdnjs -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/video.js/6.3.3/video-js.css" ref="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/video.js/6.3.3/video.js"></script>
写 video 标签

设置 id,样式(class),默认封面(poster),宽高

<video id="my-video" class="video-js vjs-default-skin vjs-big-play-centered"
       poster="../common/qrcode.jpg" width="800" height="600">
    <source src='RTMP://live.hkstv.hk.lxdns.com/live/hks2' type='RTMP/flv'/>
</video>

js 中进行播放
<script>
    var player = videojs('my-video');
    player.play();
</script>
videojs-RTMP-above6
<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Access-Control-Allow-Origin" content="*">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <title>RTMP 测试</title>

    <script src="video.js"></script>
    <script src="videojs-flash.js"></script>
    <link href="video-js.css" rel="stylesheet">
    <!--下面一行要是没有,那么就会往 https://vjs.zencdn.net/swf/5.4.2/video-js.swf 加载-->
    <script>
        videojs.options.flash.swf = "video-js.swf";
    </script>
</head>
<body>
<h3>注意: videojs 版本大于 6 的使用这个文件解析</h3>
<video id="my-video" class="video-js vjs-default-skin vjs-big-play-centered"
       poster="../common/qrcode.jpg" width="800" height="600">
    <!--这三个一般可以-->
    <!--香港卫视-->
    <!--RTMP://live.hkstv.hk.lxdns.com/live/hks-->
    <!--RTMP://live.hkstv.hk.lxdns.com/live/hks1-->
    <!--RTMP://live.hkstv.hk.lxdns.com/live/hks2-->
    <!--香港财经,RTMP://202.69.69.180:443/webcast/bshdlive-pc-->
    <!--韩国朝鲜日报,RTMP://live.chosun.gscdn.com/live/tvchosun1.stream-->
    <!--湖南卫视,RTMP://58.200.131.2:1935/livetv/hunantv-->
    <!--<source src='RTMP://live.hkstv.hk.lxdns.com/live/hks' type='RTMP/flv'/>-->
    <!--<source src='RTMP://live.hkstv.hk.lxdns.com/live/hks1' type='RTMP/flv'/>-->
    <source src='RTMP://live.hkstv.hk.lxdns.com/live/hks2' type='RTMP/flv'/>

    <!--这个等到上面的视频流通过后在去掉注释-->
    <!--<source src='RTMP://192.168.3.134:1935/live/stream' type='RTMP/flv'/>-->

</video>

<h1>如果觉得有帮助的话,欢迎关注我的公众号:小王老店</h1>
<br>
<h1>包含详细代码解析和常见问题</h1>
<img src="../common/qrcode.jpg">

<script>
    var player = videojs('my-video');
    player.play();
</script>

</body>
</html>

videojs-RTMP-below6
<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Access-Control-Allow-Origin" content="*">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <title>RTMP 测试</title>

    <script src="video.js"></script>
    <link href="video-js.css" rel="stylesheet">
    <script>
        videojs.options.flash.swf = "video-js.swf";
    </script>
</head>
<body>
<h3>注意 videojs 版本小于 6 的使用这个文件解析</h3>
<video id="my-video" class="video-js vjs-default-skin vjs-big-play-centered"
       poster="../common/qrcode.jpg" width="800" height="600">
    <!--这三个一般可以-->
    <!--香港卫视-->
    <!--RTMP://live.hkstv.hk.lxdns.com/live/hks-->
    <!--RTMP://live.hkstv.hk.lxdns.com/live/hks1-->
    <!--RTMP://live.hkstv.hk.lxdns.com/live/hks2-->
    <!--香港财经,RTMP://202.69.69.180:443/webcast/bshdlive-pc-->
    <!--韩国朝鲜日报,RTMP://live.chosun.gscdn.com/live/tvchosun1.stream-->
    <!--湖南卫视,RTMP://58.200.131.2:1935/livetv/hunantv-->
    <!--<source src='RTMP://live.hkstv.hk.lxdns.com/live/hks' type='RTMP/flv'/>-->
    <!--<source src='RTMP://live.hkstv.hk.lxdns.com/live/hks1' type='RTMP/flv'/>-->
    <source src='RTMP://live.hkstv.hk.lxdns.com/live/hks2' type='RTMP/flv'/>

    <!--这个等到上面的视频流通过后在去掉注释-->
    <!--<source src='RTMP://192.168.3.134:1935/live/stream' type='RTMP/flv'/>-->
</video>

<h1>如果觉得有帮助的话,欢迎关注我的公众号:小王老店</h1>
<h1>蹭一个关注量</h1>
<br>
<h1>包含详细代码解析和常见问题</h1>
<img src="../common/qrcode.jpg">

<script>
    var player = videojs('my-video');
    player.play();
</script>

</body>
</html>

videojs-M3U8
<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Access-Control-Allow-Origin" content="*">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <title>M3U8 测试</title>
    <script src="video.js"></script>
    <script src="videojs-http-streaming.js"></script>
    <link href="video-js.css" rel="stylesheet">
</head>
<body>
<h3>注意: videojs 版本大于 6 的使用这个文件解析</h3>
<video id="my-video" class="vjs-default-skin" controls  width="640" height="268"
       poster="../common/qrcode.jpg"
>
    <!--这 3 个一般满足要求了-->
    <source src="https://d2zihajmogu5jn.cloudfront.net/bipbop-advanced/bipbop_16x9_variant.M3U8"
            type="application/x-mpegURL">
    <!--<source src="http://ivi.bupt.edu.cn/hls/cctv6.M3U8" type="application/x-mpegURL">-->
</video>

<br>
<br>
<h1>如果觉得有帮助的话,欢迎关注我的公众号:小王老店</h1>
<h1>包含详细代码解析和常见问题</h1>
<img src="../common/qrcode.jpg">

<script>
    var player = videojs('my-video');
    player.play();
</script>

</body>
</html>

在本项目中的应用

这边提供一个三种方式的文件夹 video,把 SAFEWARE_PATH 下面的 video 复制到 NGINX_WEB_PATH/html 下面,然后启动 Nginx-web

然后访问

http://127.0.0.1:11240/video/videojs-RTMP-above6/RTMP.html
http://127.0.0.1:11240/video/videojs-M3U8/M3U8.html

出现播放界面就是成功了

联合测试

到了这里,我们已经确定 Nginx/FFmpeg/videojs 单独拿一个出来都是可以正常运行的了。

现在把这三个串起来,就完成了。

测试 RTMP 推流播放

打开 Nginx-Gryphon,使用 FFmpeg 推送 RTMP 流,RTMP://192.168.3.134:1935/live/stream,将 videojs 的 RTMP.html 中的 video-source 改成这个地址

测试 M3U8 推流播放

打开 Nginx-Gryphon,使用 FFmpeg 推送 M3U8 流,http://192.168.3.134:11242/hls/video.M3U8,将 videojs 的 M3U8.html 中的 video-source 改成这个地址

常见问题

问题 1-Nginx 文件夹无法创建

  • 报错内容:
Nginx: [emerg] CreateDirectory() "temp/app" failed (3: The system cannot find the path specified)
  • 原因:无法找到"temp/app"文件夹

  • 解决办法:在 Nginx 的目录下面手动创建一个 temp,然后在 temp 下面创建 app

问题 2-Nginx 端口被占用

  • 报错内容:
Nginx: [emerg] bind() to 0.0.0.0:11240 failed (10013: An attempt was made to access a socket in a way forbidden by its access permissions)
  • 原因:端口被占用了,

  • 解决办法:这边是 11240 被占用了,

打开小黑框,输入 netstat -ano | findstr "11240" ,找到占用程序的 pid

然后打开任务管理器,切到 tab"详细信息",按 pid 排序,找到进程,关闭,如图 enter image description here

问题 3-FFmpeg 源路径错误

  • 报错内容:
RTMP://live.hkstv.hk.lxdns.com/live/hks2234: I/O error
  • 原因:视频源无法解析,

  • 解决办法:先试下能不能用 VLC 播放

问题 4-FFmpeg 目标路径错误

  • 报错内容:
[tcp @ 000001e4230dfac0] Connection to tcp://192.168.3.134:1935 failed: Error number -138 occurred
[RTMP @ 000001e423a59300] Cannot open connection tcp://192.168.3.134:1935
RTMP://192.168.3.134:1935/hls/video: Unknown error
  • 原因:无法推送到该地址

  • 解决办法:没打开 RTMP 服务器,看下是否打开了 Nginx-Gryphon

问题 5-videojs 无法播放,通用

这里先不说具体的报错,这里说的是一个解决思路,一般都能解决了,具体报错请往下看。

  1. 先确认视频流是可以播放的,使用 VLC 测试
  2. 再确认 videojs 代码是可以播放视频的,这里先用 cctv/香港卫视等视频源
  3. 注意 videojs 需要放到 web 服务器上(tomcat/Nginx/iis 等),我们这边就是用的 Nginx,直接从文件夹中打开会出问题(网页地址栏为 file:///开头)
  4. RTMP 有用到 flash,需要在网页中打开 flash 功能,如图。具体业务逻辑可以在播放器上提示用户打开,可参考风行网 enter image description here

问题 6-CODE:4 MEDIA_ERR_SRC_NOT_SUPPORTED

  • 报错内容:
VIDEOJS: TypeError: Cannot read property 'play' of undefined
    at Player.techCall_ (video.js:10256)
    at Player.play (video.js:10312)
    at tes2.html:28
video.js:10256 Uncaught TypeError: Cannot read property 'play' of undefined
    at Player.techCall_ (video.js:10256)
    at Player.play (video.js:10312)
    at tes2.html:28
techCall_ @ video.js:10256
play @ video.js:10312
(anonymous) @ tes2.html:28
video.js:18575 VIDEOJS: ERROR: (CODE:4 MEDIA_ERR_SRC_NOT_SUPPORTED) No compatible source was found for this video. MediaError {code: 4, message: "No compatible source was found for this video."}

  • 原因:资源无法加载/未打开 flash

  • 解决办法:参考问题 5

问题 7-CODE:Uncaught (in promise) DOMException

  • 报错内容:
VIDEOJS: WARN: A plugin named "reloadSourceOnError" already exists. You may want to avoid re-registering plugins!
(anonymous) @ video.js:142
:11240/favicon.ico:1 Failed to load resource: the server responded with a status of 404 (Not Found)
M3U8.html:1 Uncaught (in promise) DOMException	
  • 原因:网页打开方式不对/资源无法加载/未打开 flash 等,很多问题都是报的这个错

  • 解决办法:参考问题 5

问题 8-CODE:Cannot read property '0' of undefined

  • 报错内容:
video.js:13002 Uncaught TypeError: Cannot read property '0' of undefined
    at Flash.buffered (video.js:13002)
    at Flash.bufferedPercent (video.js:14878)
    at Flash.<anonymous> (video.js:14835)
    at Flash.ret (video.js:18404)
    at ret (video.js:18404)

解决办法:
video.js 文件下面的  Flash.prototype.buffered 方法(13002 行),把 ranges[0][0]改成 ranges[0]。
Flash.prototype.buffered = function buffered() {
	var ranges = this.el_.vjs_getProperty('buffered');
	if (ranges.length === 0) {
	  return _utilsTimeRangesJs.createTimeRange();
	}
	// return _utilsTimeRangesJs.createTimeRange(ranges[0][0], ranges[0][1]);
	return _utilsTimeRangesJs.createTimeRange(ranges[0], ranges[0]);
};
  • 原因: videojs6.0 一下版本 flash 的问题

  • 解决办法: 这时候一般是可以播放了,video.js 文件下面的 Flash.prototype.buffered 方法(13002 行),把 ranges[0][0]改成 ranges[0]。(黑屏是视频源的问题)

video.js 文件下面的  Flash.prototype.buffered 方法(13002 行),把 ranges[0][0]改成 ranges[0]。
Flash.prototype.buffered = function buffered() {
	var ranges = this.el_.vjs_getProperty('buffered');
	if (ranges.length === 0) {
	  return _utilsTimeRangesJs.createTimeRange();
	}
	// return _utilsTimeRangesJs.createTimeRange(ranges[0][0], ranges[0][1]);
	return _utilsTimeRangesJs.createTimeRange(ranges[0], ranges[0]);
};

enter image description here

问题 9-M3U8 无法播放

  • 报错内容:没有报错
  • 原因:代码中没有自动播放
  • 解决办法:点击下播放器

问题 10-FFmpeg-Server error: Already publishing

  • 报错内容:
[RTMP @ 000002961e858700] Server error: Already publishing
RTMP://192.168.3.134:1935/live/stream: Operation not permitted
  • 原因:开了其他的 FFmpeg 推送这个地址

  • 解决办法: 看看任务管理器是否开了 FFmpeg

问题 11-打开网页的 flash

  • 看图片 enter image description here

联系方式

CSDN 博客: https://blog.csdn.net/cmqwan

码云地址: https://gitee.com/lizhaoandroid

QQ : 3060507060

微信: lizhaoandroid

公众号:小王老店/lizhaoblog

个人网站:https://www.lizhaoblog.com

个人网站:https://www.jj7cm.com

写在最后

来来回回写了好几天,将近 3 万字,希望能给大家带来一些帮助,如果不会可以联系我哈。

联系我,请直接发问题,报错截图/问题说明,这样我上线之后就能第一时间回复你了。

如果实在觉得我写的内容不太行,什么收获都没有,这个钱花的不值,请大家联系我退款哈(这个购买了无法直接从系统退款)

最后,希望随手给个好评。说到好评,我就想起 86 版西游戏广受关注好评,明年年初,中美合拍的西游记即将正式开机,我继续扮演美猴王孙悟空,我会用美猴王艺术形象努力创造一个正能量的形象,文体两开花,弘扬中华文化,希望大家多多关注。

包含源码及所有提到的软件 压缩包

  1. QQ群 720125669,群文件"直播点播系统快速搭建指南.rar"就是
  2. 从链接下载 https://www.lizhaoblog.com/file/live.7z
  3. 从链接 2 下载 http://www.jj7cm.com/file/live.7z

单独文件形式

  1. 码云live目录 https://gitee.com/lizhaoandroid/static-res.git