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

Posted by lizhao on 07-09,2019

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

流程图

使用 ffmpeg 推送视频流信息到 Nginx 服务器上,Nginx 会导出rtmp和m3u8这2种视频源,然后使用videojs在网页上进行播放

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

阅读前先看看

  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环境下的,如果因为这个问题的话,希望联系我退款哈(这个购买了无法直接从系统退款)

快速测试

打开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/video和http://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

公众号:小王老店

写在最后

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

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

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

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