文章目录

  • 流程介绍
  • 三种常见的视频流协议介绍(RTMP、RTSP、HLS)
  • RTMP(Real Time Messaging Protocol)实时消息传输协议
  • RTSP(Real Time Streaming Protocol)实时流传输协议
  • HLS(HTTP Live Streaming)
  • 在浏览器中如何播放视频流
  • 播放 RTMP 视频流
  • 使用 ffmpeg + nginx-http-flv-module + flv.js 在浏览器中通过 http 播放视频(最推荐的方式)
  • 播放 HLS 视频流
  • 使用 ffmpeg + nginx-rtmp-module + video.js 在浏览器中通过 http 播放视频
  • 播放 RTSP 视频流
  • 总结


资源
本文所用到的两个流媒体服务器(Windows10)与代码都在这里,下载不需C币
如果需要c币下载点网盘下载,提取码 6mh7
Windows10 下 nginx 的 rtmp 服务器搭建教程Windows10 下 nginx 的 nginx-http-flv-module 服务器免费下载

流程介绍

直播、视频回放大致流程:获取视频流或本地音视频文件,将流推入到流媒体服务器当中,在 web 端使用合适的 js 拉流并播放音视频:

Java 搭建流媒体服务器 html5流媒体服务器搭建_rtmp

三种常见的视频流协议介绍(RTMP、RTSP、HLS)

RTMP(Real Time Messaging Protocol)实时消息传输协议

RTMP是由Adobe公司提出的,是一种设计用来进行实时数据通信的网络协议,属于TCP/IP五层中的应用层,基于TCP协议,默认使用端口1935。RTMP中的基本数据单元称为消息(Message),传输的过程中消息会被拆分为更小的消息块(Chunk)单元,再将分割后的消息块通过 TCP 协议传输,接收端再将接收到的消息块恢复成流媒体数据。RTMP协议一般传输的是 flv,f4v 格式流(注意:RTMP 是协议,flv、f4v 是视频封装格式)。

RTMP 的特点:

  • RTMP 是专为流媒体开发的协议,对底层的优化比其它协议更加优秀,同时它 Adobe Flash 支持好,基本上所有的编码器(摄像头之类)都支持 RTMP 输出。支持 Flash 的浏览器都能播放 RTMP 协议传输的流。
  • RTMP 的延迟相对较低,一般延时在 1-3s 之间,一般的视频会议,互动式直播,是完全是够用的。
  • 基于 TCP 传输,使用非公共端口,可能会被防火墙阻拦。
  • RTMP 为 Adobe 私有协议,很多设备无法播放,特别是在 iOS 端,需要使用第三方解码器才能播放;
  • 直接播放 RTMP 流需要浏览器支持 Flash。

RTSP(Real Time Streaming Protocol)实时流传输协议

RTSP是TCP/IP协议体系中的一个应用层协议,该协议定义了一对多应用程序如何有效通过IP网络传送多媒体数据。RTSP在体系结构上位于RTP和RTCP之上,它使用TCP或RTP完成数据传输。HTTP与RTSP相比,HTTP传送HTML,而RTP传送的是多媒体数据。HTTP请求由客户机发出,服务器做出响应;RTSP可以是双向的,即客户机和服务器都可以发出请求。

Java 搭建流媒体服务器 html5流媒体服务器搭建_ffmpeg_02

RTSP与RTP最大的区别在于:RTSP是一种双向实时数据传输协议,它允许客户端向服务器端发送请求,如回放、快进、倒退等操作。当然RTSP可基于RTP来传送数据,还可以选择TCP、UDP、组播UDP等通道来发送数据,具有很好的扩展性。它是一种类似于HTTP协议的网络应用协议。

HLS(HTTP Live Streaming)

HLS是由苹果公司提出的基于Http协议的的流媒体网络传输协议。其工作原理是把整个流分成一个个ts文件来下载,每次只下载一个ts文件。在开始一个流媒体会话时,客户端会下载一个包含元数据的m3u8文件,用于寻找可用的媒体流。

Java 搭建流媒体服务器 html5流媒体服务器搭建_ffmpeg_03

下图是 m3u8 文件与 ts 切片文件,是使用 ffmpeg 将本地文件推流到 nginx-rtmp 模块生成的:

Java 搭建流媒体服务器 html5流媒体服务器搭建_http_04


Java 搭建流媒体服务器 html5流媒体服务器搭建_http_05


HLS 协议特点:

  • 跨平台性:支持iOS/Android/浏览器,通过http请求即可,通用性强。
  • 穿墙能力强:由于HLS是基于HTTP协议的,基本不会遇到被防火墙屏蔽的情况。
  • 切换码率快(清晰度):自带多码率自适应,客户端可以选择从许多不同的备用源中以不同的速率下载同样的资源,允许流媒体会话适应不同的数据速率。客户端可以很快的选择和切换码率,以适应不同带宽条件下的播放。
  • 负载均衡:HLS基于无状态协议(HTTP),客户端只是按照顺序使用下载存储在服务器的普通TS文件,做负责均衡如同普通的HTTP文件服务器的负载均衡一样简单。
  • 实时性差:苹果官方建议是请求到3个ts切片文件之后才开始播放。所以一般很少用HLS做为互联网直播的传输协议。假设列表里面的包含5个ts文件,每个ts文件包含5秒的视频内容,那么整体的延迟就是25秒。苹果官方推荐的ts时长时10s,所以这样就会大概有(3 x 10)秒的延迟。
  • 文件碎片化严重:对于点播服务来说, 由于ts切片文件通常较小, 海量碎片在文件分发, 一致性缓存, 存储等方面都有较大挑战。

在浏览器中如何播放视频流

播放 RTMP 视频流

现成的 RTMP 协议直播源

  • 香港财经:rtmp://202.69.69.180:443/webcast/bshdlive-pc(不卡很流畅)
  • 湖南卫视:rtmp://58.200.131.2:1935/livetv/hunantv(比较卡)
  • 知乎上提供的 RTMP 直播源

播放该协议流,在页面中可使用 video.js + videojs-flash,但是单独使用 video.js 是不可行的,同时浏览器需要开启对 Flash 的支持,代码:

Video.js 是一个通用的在网页上嵌入视频播放器的 JS 库,就是一个视频播放工具,Video.js 自动检测浏览器对 HTML5 的支持情况,如果不支持 HTML5 则自动使用 Flash 播放器。

<head>
	<link href="https://cdn.bootcdn.net/ajax/libs/video.js/7.9.2/alt/video-js-cdn.css" rel="stylesheet">
	<script src="https://cdn.bootcdn.net/ajax/libs/video.js/7.9.2/video.js"></script>
	<script src="https://cdn.bootcdn.net/ajax/libs/videojs-flash/2.2.1/videojs-flash.js"></script>
</head>

<body>
    <video id="video" class="video-js vjs-default-skin vjs-big-play-centered" preload="none">
        <source src="" type="">
    </video>
</body>

<script type="text/javascript">
	var options = {
        width: 600, //视频播放器显示的宽度
        height: 400, //视频播放器显示的高度
        autoplay: false, //自动播放
        poster: "", //视频开始播放前显示的图像的URL
        src: "", //要嵌入的视频资源的url
        preload: "none", //预加载
        techOrder: ["html5", "flash"],
        loop: false, //是否循环播放
        controls: true //可否控制进度条、音量
    };

    //初始化video播放器
    var myPlayer = videojs('video', options, function onPlayerReady() {
        console.log('播放器已经准备好了!');
    });
    
    //加载rtmp流,开始播放
    myPlayer.src({
        type: "rtmp/flv",
        src: "rtmp://58.200.131.2:1935/livetv/hunantv"
    });
    myPlayer.load("rtmp://58.200.131.2:1935/livetv/hunantv");
    myPlayer.play();
</script>

如果播放本地文件的话直接这样写即可:

<video id="video" class="video-js vjs-default-skin vjs-big-play-centered">
    <source src="video/test1.mp4" type="video/mp4">
</video>

当然你的页面是要跑在服务器上的,可使用 nodejs 搭建环境,也可以使用 HBuilder 运行。

本例中使用 Edge 浏览器播放,因为播放 RTMP 视频流需要 Flash 支持,所以该方式通用性差。但不是没有解决方案,使用 ffmpeg 将 rtmp 视频流转成 flv 格式视频,浏览器再通过 flv.js 播放播放视频。
|

Java 搭建流媒体服务器 html5流媒体服务器搭建_http_06

使用 ffmpeg + nginx-http-flv-module + flv.js 在浏览器中通过 http 播放视频(最推荐的方式)

  • ffmpeg 是一个完整的,跨平台的,集录制、能够转换音视频格式的工具。具有将不同格式的音视频转为你所需要的格式、将本地的音视频文件推流至流媒体服务器、将直播流下载下来等功能。
  • nginx-http-flv-module 是一个音视频传输模块,需要集成在 nginx 中运行,也就是一个流媒体服务器。github 中文说明
  • flv.js B站开源出来的、一个使用纯 js 编写的 FLV(HTML5 Flash Video) 播放器。
  1. 首先使用 ffmpeg 将现成的 rtmp 流推至流媒体服务器:
  2. Java 搭建流媒体服务器 html5流媒体服务器搭建_rtsp_07

  3. 在页面上通过 http 请求进行拉流:
<head>
    <link rel="stylesheet" type="text/css" href="demo.css" />
    <script src="js/flv.js"></script>
</head>
<body>
    <div class="mainContainer">
        <div class="url-input">
            <label for="sURL">Stream URL:</label>
            <input id="sURL" type="text" value="http://127.0.0.1:8081/live?app=flvapp&stream=test" />
        </div>

        <div class="video-container">
            <div>
                <video name="videoElement" class="centeredVideo" controls autoplay>
                    Your browser is too old which doesn't support HTML5 video.
                </video>
            </div>
        </div>

        <div class="controls">
            <button onclick="flv_load()">Load</button>
            <button onclick="flv_start()">Start</button>
            <button onclick="flv_pause()">Pause</button>
            <button onclick="flv_destroy()">Destroy</button>
        </div>
    </div>
</body>
<script type="text/javascript">
    //播放
    function flv_load() {
        var mediaDataSource = {
            type: 'flv',
            isLive: false,
            withCredentials: false,
            hasAudio: true,
            hasVideo: true,
        };

        mediaDataSource['url'] = document.getElementById('sURL').value;
        flv_load_mds(mediaDataSource);
    }

    //video标签与mediaDataSource绑定
    function flv_load_mds(mediaDataSource) {
        var element = document.getElementsByName('videoElement')[0];
        if (typeof player !== "undefined") {
            if (player != null) {
                player.unload();
                player.detachMediaElement();
                player.destroy();
                player = null;
            }
        }
        player = flvjs.createPlayer(mediaDataSource, {
            enableWorker: false,
            lazyLoadMaxDuration: 3 * 60,
            seekType: 'range',
        });
        player.attachMediaElement(element);
        player.load();
    }

    //暂停后开始播放
    function flv_start() {
        player.play();
    }

    //暂停
    function flv_pause() {
        player.pause();
    }

    //销毁该播放器
    function flv_destroy() {
        player.pause();
        player.unload();
        player.detachMediaElement();
        player.destroy();
        player = null;
    }
</script>

Java 搭建流媒体服务器 html5流媒体服务器搭建_rtmp_08

播放 HLS 视频流

使用 ffmpeg + nginx-rtmp-module + video.js 在浏览器中通过 http 播放视频

现成的 HLS 协议直播源

  • CCTV1高清:http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8
  • CCTV3高清:http://ivi.bupt.edu.cn/hls/cctv3hd.m3u8
  • CCTV5+高清:http://ivi.bupt.edu.cn/hls/cctv5phd.m3u8
  • CCTV6高清:http://ivi.bupt.edu.cn/hls/cctv6hd.m3u8

之前提到的 nginx-http-flv-module 模块包含了 nginx-rtmp-module 中的所有功能,该案例使用 nginx-rtmp-module 作为流媒体服务器,因为通过 HLS 协议,页面还是发送 http 请求来播放视频。

  1. 第一步还是推流:
  2. 在页面上通过 http 请求进行拉流:
<head>
    <link href="https://cdn.bootcdn.net/ajax/libs/video.js/7.9.2/alt/video-js-cdn.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/video.js/7.9.2/video.js"></script>
</head>
<body>
    <video id="video" class="video-js vjs-default-skin vjs-big-play-centered">
        <source src="http://127.0.0.1:8081/hls/test.m3u8" type="application/x-mpegURL">
    </video>
    <hr />
    <button class="control" οnclick=operation("play")>播放</button>
    <button class="control" οnclick=operation("stop")>停止</button>
    <button class="control" οnclick=operation("reload")>重载</button>
    <button class="control" οnclick=operation("reset")>重置</button>
    <hr />
</body>
<script type="text/javascript">
    var options = {
        width: 600, //视频播放器显示的宽度
        height: 400, //视频播放器显示的高度
        poster: "", //视频开始播放前显示的图像的URL。这通常是一个帧的视频或自定义标题屏幕。一旦用户点击“播放”图像就会消失
        src: "", //要嵌入的视频资源url,The source URL to a video source to embed.
        preload: "metadata", //预加载
        techOrder: ["html5", "flash"],
        loop: false
    };

    var myPlayer = videojs('video', options, function onPlayerReady() {
        console.log('播放器已经准备好了!');
    });

    function operation(param) {
        if ("play" == param) { //开始播放
            myPlayer.play();
        } else if ("stop" == param) { //停止播放
            myPlayer.pause();
        } else if ("reload" == param) { //重新加载
            myPlayer.pause();
            myPlayer.load();
            myPlayer.play();
        } else if ("reset" == param) { //重置,视频不会播放
            myPlayer.reset();
        }
    }
</script>

Java 搭建流媒体服务器 html5流媒体服务器搭建_Java 搭建流媒体服务器_09

播放 RTSP 视频流

现成的 RTSP 协议直播源

  • http://mirror.aarnet.edu.au/pub/TED-talks/911Mothers_2010W-480p.mp4 (TED 视频)
  • rtsp://wowzaec2demo.streamlock.net/vod/mp4:*BigBuckBunny_115k.mov (一个小动画片)
  • rtsp://@202.69.69.180:443/webcast/bshdlive-pc (香港财经,不卡很流畅)

页面不能直接播放 RTSP 视频流,所以还需 ffmpeg 转一道视频流格式,后续页面还是发送 http 请求拉流。

  1. 推流:
  2. 页面拉流的链接:http://127.0.0.1:8081/live?app=flvapp&stream=test,与之前使用 flv.js 时的方式一致

总结

对于播放一般的 rtmp 流来说,不忌讳 flash那直接使用 videojs 在页面播放就好了;如果要保证浏览器通用性,则使用 ffmpeg 与流媒体服务器,转为 http 请求能拉取到的流即可;如果某个流要在多个种类的终端上播放,可以使用 HLS 协议,其具有跨平台性。