# 一、流媒体基础
流媒体 Streaming Media
# 1.1 流媒体简介
流媒体指采用流式传输的方式在因特网/内联网播放的媒体格式。
是指将一连串的多媒体数据压缩后,经过互联网分段发送数据,在互联网上即时传输影音,以供用户观赏的一种技术。
在流媒体技术出现之前,人们必须要先下载多媒体内容到本地计算机,等待完整的多媒体内容下载完成之后,才能够欣赏多媒体的内容。流媒体技术的出现,使人们只需经过几秒或十几秒的启动延时即可欣赏媒体内容,而无需再等待媒体内容完全下载完成了。
流媒体技术发端于美国,又称流式媒体,是一种新的媒体传送方式。流式传输方式将整个A/V及3D等多媒体文件经过特殊的压缩方式分成一个个压缩包,由视频服务器向用户计算机连续、实时传送。用户不必像采用下载方式那样等到整个文件全部下载完毕,而是只需经过几秒或几十秒的启动延时即可在用户的计算机上利用解压设备对压缩的A/V、3D等多媒体文件解压后进行播放和观看。这种对多媒体文件边下载边播放的流式传输方式不仅使启动延时大幅度地缩短,而且对系统缓存容量的需求也大大降低。
简单地说,流协议就是在两个通信系统之间传输多媒体文件的一套规则,它定义了视频文件将如何分解为小数据包以及它们在互联网上传输的顺序。
# 1.2 流媒体特征
流媒体包括声音流、视频流、文本流、图像流、动画流等,在时间上连续的媒体数据。
1、流媒体具有较强的实时性和交互性;
通过因特网或内部IP实时播放音视频和多媒体内容,或对其进行点播。流技术可以实现对音频记录的信息进行实况转播,常称之为Webcasting。使用流技术也可以方便地实现对预录的媒体进行点播,也就是说,以“流”的格式存储和发布在网页上的媒体,可以再任意时间被人接入。
2、用户侧的媒体启动时间大幅度缩短;
由一个流媒体服务器发送流媒体,客户端一边接收,一边对媒体进行处理和回放。客户端的软件常被称为播放器,一旦它收到足够的数据,就开始回放流媒体,而不是等到收到整个文件后才播放。数据在传输时被暂存在一个缓存器中。这样的技术有其独特的优点。
3、不能在客户端对其进行录制;
接收、处理和回放一个播放的文件,不在客户端驻留播放的内容,即不能在客户端对其进行录制。这是流媒体的一个重要特征,即提供版权保护,不让客户随意复制。在没有得到授权的情况下,客户端不能改变也不能转发媒体内容。
4、流媒体技术对客户端的缓存容量要求大大降低;
与传统的(完整)媒体传输方式相比,在流媒体文件的播放过程中,由于不再需要把所有的文件都放入缓存系统,因此对缓存容量的要求是很低的。
# 1.3 流式传输
流媒体技术的特征就是流式传输,它使得流媒体数据可以像流水一样传输。
流式传输主要包括两种实现方式:顺序流式传输(progressive streaming)和实时流式传输(real time streaming)。需要根据具体需求决定采用哪种方式进行流式传输,下面就对这两种传输方式进行简单介绍。
# 顺序流式传输
在顺序流式传输模式下,用户在观看在线媒体的同时,也在下载文件。在这个过程中,用户只能观看已经下载完成的媒体内容,而不能直接观看未下载的部分。因此,用户会在一段延时后,才能看到服务器传送过来的媒体内容。由于标准的HTTP服务器就可以发送这种形式的媒体文件,因此流式传输也经常被称为HTTP流式传输。
由于顺序流式传输能够较好地保证节目的播放质量,因此比较适合在网站上发布的、可供用户点播的、高质量的视频。
顺序流式传输的文件存放在标准HTTP或FTP服务器上,易于管理,基本上与防火墙无关。
根据以上信息,能够知道“顺序流式传输”主要提现了流媒体技术的基本功能:无需下载完整的媒体文件,即可欣赏媒体内容。
# 实时流式传输
使用实时流式传输时,必须要保证与流媒体对应的带宽,以使媒体内容可以被用户实时观看到。用户在观看过程中,可以任意观看当前媒体内容之前或后面的内容。但是在这种传输方式中,如果网络状况不理想,会导致收到的图像质量比较差。
实时流式传输需要特定的服务器(如 Windows Media Server),这些服务器可以对媒体进行更多的控制,所以系统设置、管理比标准HTTP服务器更加复杂。
实时流式传输还需要特殊的网络协议,如 RTSP(realtime streaming protocol) 或 MMS(microsoft media server)。防火墙有时会对这些协议进行屏蔽,导致用户看不到不实时内容。
根据以上信息,能够知道“实时流式传输”更强度的是媒体传输的“实时性”,因此目前流行的视频直播行业,应属于“实时流式传输”功能的应用。
# 1.4 流媒体系统组成
流媒体系统包括以下五个内容:
编码工具:用于创建、捕捉和编辑多媒体数据,形成流媒体格式;
流媒体数据;
服务器:存放和控制流媒体的数据;
主要包括流媒体的编码、转码、分发、存储等功能,是向用户提供视频服务的关键平台。
网络:适合多媒体传输协议(甚至是实时传输协议)的网络;
播放器:客户端通过播放器浏览流媒体文件。
以上五个部分有些是服务器需要的,有些是客户端需要的,而且不同的流媒体标准和不同公司的解决方案中,会在有些内容上有所不同。
# 1.5 点播模式、直播模式
流媒体服务器的主要有两种播放模式:点播模式、直播模式。
- 点播模式:以流式协议(RTP/RTSP、RTMP等)将视频文件传输到客户端,供用户在线观看;
- 直播模式:从视频采集、压缩软件接收实时视频流,再以流式协议直播给客户端。
# 1.6 码率、码流
码率、码流是同一个概念,是数据传输时单位时间传送的数据量,一般用单位kbps
表示。
视频码率就是指视频文件在单位时间内使用的数据量。
简单理解就是要播放一秒的视频需要多少数据,从这个角度就不难理解通常码率越高视频质量也越好,相应的文件体积也会越大。
码率、视频质量、文件体积是正相关的。但当码率超过一定数值后,对图像的质量影响就不大了。几乎所有的编码算法都在追求用最低的码率达到最少的失真(最好的清晰度)。
# 二、常见流媒体协议
常见流媒体协议有RTMP/HLS/HTTP-FLV/RTSP/DASH/WebRTC等协议。
- RTMP(推流端、拉流端)
- RTSP(推流端)
- HLS(拉流端)
- FLV(拉流端)
# 2.1 协议比较
协议 | http-flv | hls | RTMP |
---|---|---|---|
传输方式 | http流 | http流 | tcp流 |
视频封装格式 | flv | ts文件 | flv tag |
延迟 | 低(1-2s左右) | 高 | 低(1s左右) |
数据分段 | 连续流 | 切片文件 | 连续流 |
H5播放 | 可通告HTML5解封包播放(flv.js) | 可通告HTML5解封包播放(hls.js) | 不支持 |
- rtmp和http-flv的视频格式都是flv格式的,只是传输协议而不同。rtmp是tcp的传输协议,而http-flv是http长链接的传输协议。
- RTMP的Payload是FLV;而RTSP的Payload是RTP。
# 2.2 RTMP
RTMP(Real Time Message Protocol)实时消息传递协议
RTMP是由Adobe
公司提出的一种应用层的协议,RTMP协议是要靠底层可靠的传输层协议来保证信息传输的可靠性的。
RTMP用于在服务器和Flash播放器之间实时传输视频,音频和数据。
RTMP是Adobe的私有协议,没有完全公开,一般传输的是flv
、f4v
格式流。
# 应用场景
RTMP应用较广,特别在直播领域。国内主流的CDN平台和OTT平台基本都支持RTMP,大部分的硬件或软件编码器也都支持RTMP推流格式。
# 特点
- 基于TCP,实时性高、稳定性高,主要用于直播。
- 低延迟,RTMP使用独占的
1935
端口,无需缓冲,可以实现低延迟。 - 灵活性,RTMP 支持整合文本、视频和音频,支持 MP3 和 AAC 音频流,也支持MP4、FLV 和 F4V 视频。
# 缺点
HTML5不支持,浏览器需要安装插件- flash插件。
标准HTML5播放器不支持RTMP流,需要使用
Flash Player
作为播放器客户端。容易受到带宽问题的影响,RTMP流经常会出现低带宽问题,造成视频中断。
HTTP不兼容
无法通过HTTP流式传输RTMP,必须需要实现一个特殊的服务器,并使用第三方内容交付网络或使用流媒体视频平台。
还记得几年前,当您尝试播放视频时,您的计算机会告诉您更新您的 Flash 插件吗?这背后的技术其实就是RTMP。
随着 Flash 开始被淘汰并且基于 HTTP 的协议成为流式传输到播放设备的新标准,RTMP在流媒体协议中的地位越来越低。但是丝毫不影响RTMP的使用,因为在端到端直播和点播中,它仍然是王者!
# 2.3 RTSP
RTSP (Real-Time Stream Protocol)实时流协议
RTSP是 RealNetworks
于1996年与 Netscape
和哥伦比亚大学联合开发的协议,基于文本的多媒体播放控制协议。
RTSP旨在建立和维护原始数据源(客户端)和流服务器之间的连接,允许控制流媒体服务器内的娱乐和通信系统,允许暂停和播放功能。
RTSP协议是公有协议,有专门的机构维护RTSP协议。一般传输的是ts、mp4格式流。
RTSP协议定义了一对多模式下如何有效地通过IP网络传送多媒体数据。RTSP在体系结构上位于RTP和RTCP之上,它使用TCP或UDP(RTP)协议完成数据传输。
# RTP、RTCP
RTP(Real-time Transport Protocol) 实时传输协议
RTCP(Real-time Transport Control Protocol) 实时传输控制协议
RTP(实时传输协议) RTP(实时传输协议)通常用于实时数据的传输工作(一般使用UDP来传送数据)。
当应用程序开始一个RTP会话时,将开启两个端口:一个给RTP,一个给RTCP。RTP本身并不能为“按顺序传输数据包”提供可靠的传输送制,也不提供流量控制和拥塞控制服务,而是依赖RTCP提供这些服务。通常RTP算法并不作为一个独立的网络层来实现,而是作为应用程序代码的一部分来实现的。
RTCP(实时传输控制协议)
RTCP(实时传输控制协议)在RTP传输实时数据时,提供流量控制和拥塞控制服务。在RTP会话期间各参与者会周期性地传送RTCP包,RTCP包中含有已发送的数据包的数量、丢失的数据包数量等统计资料,因此,服务器可以利用这些信息动态地改变传输速率,甚至改变有效载荷类型。
RTP和RTCP配合使用,能通过有效的反馈和最小的开销,使传输效率最佳化,因此特别适合在互联网上传输实时数据。
RTSP主要在内网使用,每个摄像头可以当成一个RTSP的Server,若需要看视频,需要主动去摄像头去拉流,摄像头自己是不会主动推流的。
# 应用场景
RTSP实时效果非常好,适合视频会议,视频监控等方向。
这种可靠性和控制性的结合使RTSP成为闭路电视 (CCTV) 和类似 监控系统的热门选择。因此,它是许多IP摄像机的首选协议。
# 特点
实时传输协议。
轻松自定义流,可以通过结合不同的协议来开发自己的视频流解决方案。
延时低,厂商直接提供,网络负载均衡。
分段流式传输
RTSP流使观看者能够在下载完成之前访问的视频内容,而不必下载完整的视频以流式传输内容。
# 缺点
不支持移动端,浏览器兼容性差,需要低版本浏览器,且安装插件。
HTTP不兼容
没有简单的解决方案可以在Web浏览器中播放RTSP流,因为RTSP旨在通过私有网络流式传输视频,必须借用额外软件。
# 2.4 HLS
HLS(HTTP Live Streaming)基于HTTP的自适应码率流媒体传输协议
HLS是苹果Apple
公司提出的基于HTTP的流媒体网络传输协议。
类似于MPEG-DASH,但是HLS更加简洁,它的基本原理也是服务端把文件或媒体流按照不同的码率切分成一个个小片段进行传输,客户端在播放码流时,可以根据自身的带宽及性能限制,在同一视频内容的不同码率的备用源中,选择合适码率的码流进行下载播放。
在传输会话开始时,客户端首先需要下载描述不同码流元数据的M3U8索引文件。包括一个m3u(8)的索引文件、TS媒体分片文件和key加密串文件,通过给出的ts文件地址去依次播放。在播放的时候,客户端会不断请求m3u8文件,检查ts列表是否有新的ts切片。
HLS 只请求基本的 HTTP 报文。与实时传输协议(RTP)不同,HLS 可以穿过任何允许 HTTP 数据通过的防火墙或者代理服务器。它也很容易使用内容分发网络来传输媒体流。这是HLS应用在直播上的一大优势。
# M3U(8)
M3U(Moving Picture Experts Group Audio Layer 3 Uniform Resource Locator)mp3 URL
M3U
和 M3U8
文件都是苹果公司使用的HLS协议格式的基础。
- M3U使用Latin-1字符集编码。M3U是纯文本文件。
- M3U8文件是M3U文件的一种,只不过它的编码格式是UTF-8。
# 应用场景
主要用于PC和Apple终端的音视频服务。
HLS流可以用于直播,也可以用于点播。
# 特点
基于HTTP,
分片、延迟高
把整个流分成一个个小的基于HTTP的文件下载,所以不适用直播,延迟会比其他协议的高,对网络质量要求高。
视频插入广告,可以在M3U8视频中任意位置插入一些广告。
# 缺点
- 延时比较大,
# 2.5 HTTP-FLV
HTTP-FLV就是对RTMP协议的封装,相比于RTMP,它是一个开放的协议,它具备了RTMP的实时性和RTMP不具备的开发性。
HTTP-FLV 是将音视频数据以 FLV 文件格式进行封装,再将 FLV 格式数据封装在 HTTP 协议中进行传输的一种流媒体传输方式。
随着flv.js
出现(感谢B站),使得浏览器在不依赖flash的情况下,播放flv视频,从而兼容了移动端。在直播领域,通常采用 RTMP 推流,HTTP-FLV 播放的方案。
# FLV
FLV(Flash video)
FLV 是在sorenson
公司的压缩算法的基础上开发出来的,是 Adobe
公司推出的一种全新的流媒体视频格式。
FLV是被众多新一代视频分享网站所采用,是增长最快、最为广泛的视频传播格式。它利用了网页上广泛使用的Flash Player 平台,将视频整合到Flash动画中。
FLV格式不仅可以轻松的导入Flash中,速度极快,并且能起到保护版权的作用,并且可以不通过本地的微软或者REAL播放器播放视频。
FLV流媒体格式是随着Flash MX的推出发展而来的视频格式。由于它形成的文件极小、加载速度极快,使得网络观看视频文件成为可能,它的出现有效地解决了视频文件导入Flash后,使导出的SWF文件体积庞大,不能在网络上很好的使用等问题。
# 优点
基于HTTP,穿透性强
一些防火墙会墙掉 RTMP 或者其他的一些协议,但是防火墙对 HTTP 非常友好,不会墙掉 HTTP,因此基于 HTTP 传输的成功率更高。
# HTTP-FLV 的实现原理
HTTP-FLV 利用 HTTP/1.1 分块传输机制发送 FLV 数据。虽然直播服务器无法知道直播流的长度,但是 HTTP/1.1 分块传输机制可以不填写 conten-length 字段而是携带 Transfer-Encoding: chunked 字段,这样客户端就会一直接受数据。
# 2.6 WebRTC
WebRTC (Web Real-Time Communications)
WebRTC是一项实时通讯技术(引擎),它允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点(Peer-to-Peer)的连接,实现视频流和(或)音频流或者其他任意数据的传输。WebRTC 包含的这些标准使用户在无需安装任何插件或者第三方的软件的情况下,创建点对点(Peer-to-Peer)的数据分享和电话会议成为可能。
WebRTC是Google
推出的做Web视频会议的框架(2010年5月,Google以6820万美元收购VoIP软件开发商Global IP Solutions的GIPS引擎,并改为名为“WebRTC”)。
WebRTC使用GIPS引擎,实现了基于浏览器的视频会议、多人视频通话,并支持722,PCM,ILBC,ISAC等编码,同时使用谷歌自家的VP8视频解码器;同时支持RTP/SRTP传输等。
WebRTC实现了基于网页的视频会议,标准是WHATWG 协议,目的是通过浏览器提供简单的javascript就可以达到实时通讯(Real-Time Communications (RTC))能力。
同时随着Flash的禁用,WebRTC也在低延迟直播中也有应用。
WebRTC提供了视频会议的核心技术,包括音视频的采集、编解码、网络传输、显示等功能,并且还支持跨平台:windows,linux,mac,android。
FFmpeg是一个基础库,二WebRTC是一个引擎,引擎回有很多基础库为它提供原子能力。目前的音视频领域FFmpeg是无可取代的。
# 2.7 GB-281281
公安联合摄像头厂家定制的协议,专门适用于安防领域。
# 2.8 SRT
# 三、流媒体服务器
流媒体服务器主要包括流媒体的编码、转码、分发、存储等功能,是向用户提供视频服务的关键平台。
Java在用于视频开发时主要采用的技术框架是FFmpeg和OpenCV。
# 3.1 流媒体服务器工作流程
# 3.2 FFmpeg
FF是Fast Forward的意思,翻译成中文是“快进”。
FFmpeg官方下载网址:http://ffmpeg.org/download.html (opens new window)
FFmpeg的基本用法参考文档 (opens new window)
FFmpeg项目是由法国人Fabrice Bellard
发起的,此人也是著名的CPU模拟器项目QEMU的发起者,同时还是圆周率算法纪录的保持者。
FFmpeg堪称自由软件中最完备的一套多媒体支持库(C/C++
),它几乎实现了所有当下常见的数据封装格式、多媒体传输协议以及音视频编解码器,堪称多媒体业界的瑞士军刀。
可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。
# FFmpeg主要组成部分
FFmpeg从功能上划分为几个模块,分别为核心工具(libutils)、媒体格式(libavformat)、编解码(libavcodec)、设备(libavdevice)和后处理(libavfilter, libswscale, libpostproc),分别负责提供公用的功能函数、实现多媒体文件的读包和写包、完成音视频的编解码、管理音视频设备的操作以及进行音视频后处理。
模块 | 描述 |
---|---|
libavformat | 用于各种音视频封装格式的生成和解析,包括获取解码所需信息以生成解码上下文结构和读取音视频帧等功能,包含demuxers和muxer库; |
libavcodec | 用于各种类型声音/图像编解码; |
libavutil | 包含一些公共的工具函数; |
libswscale | 用于视频场景比例缩放、色彩映射转换; |
libpostproc | 用于后期效果处理; |
ffmpeg | 是一个命令行工具,用来对视频文件转换格式,也支持对电视卡实时编码; |
ffsever | 是一个HTTP多媒体实时广播流服务器,支持时光平移; |
ffplay | 是一个简单的播放器,使用ffmpeg 库解析和解码,通过SDL显示; |
# Java使用FFmpeg推流
FFmpegUtil.java
package com.ffmpeg.service;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.util.IdUtil;
import lombok.SneakyThrows;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
public class FFmpegUtil {
{
/** ffmpeg 命令详解
* ffmpeg [[options][`-i’ input_file]] {[options] output_file}
* options:
* -i: url 输入文件网址
* -vcodec: 设置视频编解码器 -codec:v -c:v
* (强制使用codec编解码方式,如-vcodec xvid 使用xvid压缩 如果用copy表示原始编解码数据必须被拷贝)
* -acodec: 设置音频编解码器 -codec:a -c:a
* -f: fmt 强制输入或输出文件格式
*/
}
@SneakyThrows
public static void srs(){
String osName = System.getProperties().getProperty("os.name");
System.out.println(osName);
ClassPathResource classPathResource = new ClassPathResource("ffmpeg"+ File.separator+"win64"+ File.separator);
String basePath = classPathResource.getAbsolutePath();
String myStream = IdUtil.simpleUUID();
String command = basePath + "ffmpeg -re " +
"-rtsp_transport tcp " +
"-i rtsp://admin:123456@192.168.13.199:554 " +
"-c:v copy -c:a copy " +
"-f flv rtmp://192.168.13.170/live/"+myStream;
System.out.println("rtmp://192.168.13.170/live/"+myStream);
Process process = Runtime.getRuntime().exec(command);
BufferedReader br = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line = null;
while((line = br.readLine()) != null) {
System.out.println("视频推流信息[" + line + "]");
}
}
public static void main(String[] args) {
srs();
}
}
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
51
52
# 3.3 OpenCV
OpenCV官方文档:https://docs.opencv.org (opens new window)
OpenCV是一个基于Apache2.0许可(开源)发行的跨平台计算机视觉和机器学习软件库。
OpenCV用C++
语言编写,它的主要接口也是C++语言,但是依然保留了大量的C语言接口。该库也有大量的Python、Java and MATLAB/OCTAVE(版本2.5)的接口。这些语言的API接口函数可以通过在线文档获得。如今也提供对于C#、Ch、Ruby的支持。
可以运行在Linux、Windows、Android和Mac OS操作系统上,根据不同环境,需要进行库的切换。
# 应用领域
- 人机互动
- 物体识别
- 图像分割
- 人脸识别
- 动作识别
- 运动跟踪
- 机器人
- 运动分析
- 机器视觉
- 结构分析
- 汽车安全驾驶
# 3.4 JavaCV
JavaCV官方网址:http://bytedeco.org/ (opens new window)
JavaCV Github官方网址:https://github.com/bytedeco/javacv (opens new window)
JavaCV入门教程目录 (opens new window)
JavaCV开发详解专栏文章目录 (opens new window)
JavaCV音视频实战宝典 (opens new window)
JavaCV依赖包说明 (opens new window)
JavaCV
是一款基于JavaCPP
调用方式(JNI的一层封装),由多种开源计算机视觉库组成的包装库(JAVA
)。
对各种常用计算机视觉库封装后的一组jar包,封装了ffmpeg
、OpenCV
、libdc1394
、OpenKinect
、videoInput
和ARToolKitPlus
等计算机视觉领域研究人员常用库。
JavaCV基于Apache License Version 2.0协议和GPLv2两种协议。
JavaCV支持Windows、Linux、MacOS,Android、IOS在内的Java平台上调用这些接口。
通过javacv来处理直播点播,事实上javacv性能足够,底层ffmpeg也是通过c实现,使用java调用c跟使用c++去调用c差不了多少毫秒延迟。
# JavaCV应用场景
JavaCV开发包是用于支持java多媒体开发的一套开发包,首先适用于本地多媒体(音视频)调用以及音视频,图片等文件后期操作(图片修改,音视频解码剪辑等等功能)。其次,既然是封装了计算机视觉领域的库,可以在诸如流媒体、图像处理、深度学习、机器学习、人工只能等领域应用。
应用场景 | 描述 |
---|---|
嵌入式领域 | javacv用在树莓派等等的一些基于arm 芯片的板子上,外挂摄像头或者音频设备就可以实现音视频上传,图像处理,图像识别等操作。 |
流媒体 | 音视频处理为主,利用javacv 的流媒体优势,可以轻松实现音视频采集,推流,编解码,装封装等操作。 |
深度学习 | deeplearn4j 为主的利用java大数据能力进行深度学习。 |
人脸检测识别 | opencv 图像处理、图像检测识别;javacv官网的首页demo就是人脸检测的例子,opencv能做到的它都可以。 |
文字识别 | 利用Tesseract-OCR 可以轻松实现字符库训练,字符识别。还可以借助javacv特有的流媒体属性和嵌入式开发特性实现摄像头的字符识别,视频图像的字符识别等场景。 |
# JavaCV使用
maven引入
<!-- JavaCV全量包 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.8</version>
</dependency>
2
3
4
5
6
调用本地摄像头窗口视频
import javax.swing.JFrame;
import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.javacv.FrameGrabber.Exception;
import org.bytedeco.javacv.OpenCVFrameGrabber;
/**
* 调用本地摄像头窗口视频
* @author eguid
* @date 2016年6月13日
* @since javacv1.2
*/
public class JavavcCameraTest{
public static void main(String[] args) throws Exception, InterruptedException{
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);//新建opencv抓取器,一般的电脑和移动端设备中摄像头默认序号是0,不排除其他情况
grabber.start();//开始获取摄像头数据
CanvasFrame canvas = new CanvasFrame("摄像头预览");//新建一个预览窗口
canvas.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//窗口是否关闭
while(canvas.isDisplayable()){
/*获取摄像头图像并在窗口中显示,这里Frame frame=grabber.grab()得到是解码后的视频图像*/
canvas.showImage(grabber.grab());
}
grabber.close();//停止抓取
}
}
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
# JavaCV精简依赖包
如何只依赖本地平台所需的最小依赖包?
由于javacv跨平台,那么全部javacv依赖包下载下来后,整个javacv的包会特别巨大,接近1G。显然很多平台依赖包我们并不需要,而且我们开发时只需要自己本身开发平台的依赖包就可以了,所以我们以windows x86_64平台下的ffmpeg和opencv为例,来讲讲如何精简依赖包。
<!-- JavaCV全量包 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.8</version>
</dependency>
2
3
4
5
6
为了防止出错,我们使用了JavaCV全量包,但是这个包太大,我们需要精简。
javacv核心依赖包(基础库,必须)
如果要使用javacv调用任何其他native库,都必须要javacv核心库,核心库包含两个依赖:javacv
+javacpp
核心最小精简依赖。
<properties>
<javacv.version>1.5.5</javacv.version>
<system.windowsx64>windows-x86_64</system.windowsx64>
</properties>
<!-- javacv封装库 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>${javacv.version}</version>
</dependency>
<!-- javacpp跨平台本地接口映射库 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp-platform</artifactId>
<version>${javacv.version}</version>
</dependency>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ffmpeg最小依赖
这里的ffmpeg最小依赖包,只包含一个平台架构包。
ffmpeg最小依赖包,必须包含上面的javacv+javacpp核心库。
<!-- 最小ffmpeg依赖包 ,必须包含下面的javacv+javacpp -->
<!-- ffmpeg核心库 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>4.3.2-${javacv.version}</version>
<classifier>${system.windowsx64}</classifier>
</dependency>
<!-- javacv封装库 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>${javacv.version}</version>
</dependency>
<!-- javacpp跨平台本地接口映射库 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp-platform</artifactId>
<version>${javacv.version}</version>
</dependency>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
opencv最小依赖
opencv依赖项比较复杂,它本身依赖了很多外部包,甚至在视频采集和编解码这块需要依赖ffmpeg。由于opencv一般用途只在图像处理识别这块,所以这里我们写的opencv最小依赖包是只包含采集摄像头图像、图像处理和图像识别所需包。
<!-- 最小opencv依赖包 ,必须包含下面的javacv+javacpp -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.5.1-${javacv.version}</version>
<classifier>${system.windowsx64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.13-${javacv.version}</version>
<classifier>${system.windowsx64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>flycapture</artifactId>
<version>2.13.3.31-${javacv.version}</version>
<classifier>${system.windowsx64}</classifier>
</dependency>
<!-- javacv+javacpp核心库-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>${javacv.version}</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp-platform</artifactId>
<version>${javacv.version}</version>
</dependency>
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
# 基于JavaCV相关开源项目
项目一:EasyMedia
EasyMedia Gitee项目地址:https://gitee.com/52jian/EasyMedia (opens new window)
项目二:AStream
AStream Gitee项目地址:https://gitee.com/yefengr/astream (opens new window)
AStream详情介绍文档 (opens new window)
项目三: videojc
videojc Gitee项目地址:https://gitee.com/DiamonCheng/videojc (opens new window)
# JavaCV使用流程图
总结:
FlV的形式,延迟在3~5秒左右;
HlS的形式,延迟最低在6秒左右;
# 3.5 Nginx + FFmpeg
FFmpeg是非常好的音视频解决方案,Nginx本身是一个非常出色的HTTP服务器。组合在一起即可以搭建一个功能相对比较完善的流媒体服务器。
这两个东西通过一个Nginx的模块
nginx-rtmp-module
,这个流媒体服务器可以支持RTMP和HLS。(FFmpeg + Nginx + nginx-rtmp-module)这两个东西通过一个Nginx的模块
nginx-http-flv-module
,这个流媒体服务器可以支持RTMP、HLS和FLV。(FFmpeg + Nginx + nginx-http-flv-module)
# 前置
市面上通用的摄像机比如海康、大华等的视频流都是RTSP格式的,要想在移动端或者Web端进行播放时,还比较麻烦,于是就想到能不能将RTSP格式的视频流实时转成RTMP的流。
Adobe 在 2020 年 12 月 31 日之后停止对 flash 播放器 的官方支持,主流浏览器随后将移除 flash 播放器,使用 flash 播放器的插件将不再可用。所有浏览器不再支持flash插件之后,rtmp的视频流就不能在浏览器中播放了。这个时候可以采用将rtmp重新封装成http-flv的视频流,采用flv.js来进行播放。
# 原理
- FFmpeg配合Nginx + 插件nginx-rtmp-module做流媒体服务器的原理:
- 视频源提供
RTSP
流,FFmpeg将RTSP流转换为RTMP
流,并推送到Nginx; - Nginx通过RTMP模块(
nginx-rtmp-module
)提供RTMP
流输出; - 然后客户端通过flash插件,访问Nginx来收看实时视频流。
- 视频源提供
- FFmpeg配合Nginx + 插件nginx-http-flv-module做流媒体服务器的原理:
- 视频源提供
RTSP
流,FFmpeg将RTSP流转换为FLV
流,并推送到Nginx; - Nginx通过RTMP模块(
nginx-http-flv-module
),提供HTTP-FLV
流输出; - 然后客户端通过
flv.js
,访问Nginx来收看实时视频流。
- 视频源提供
# 部署FFmpeg
FFmpeg是一个开源免费的软件,可以进行各种媒体格式转换;
FFmpeg下载地址:Download FFmpeg (opens new window)
下载
选择
window
版本下的Windows builds from gyan.dev
项;选择release下的第一个链接;
将下载的ffmpeg-4.4-full_build.7z文件解压到自定义文件夹,该文件夹内的bin文件内包含3个.exe文件;
将bin文件夹位置添加到环境变量中;
在Path中,添加本地安装目录下的
bin
目录路径;CMD输入
ffmpeg
验证是否安装完成;
# 部署Nginx+FLV
下载
nginx
nginx-http-flv-module
整合重新编译后生成的nginx工具。(需要重新编译nginx,将两者合二为一)
好人提供的nginx编译后的依赖包福利 (opens new window)
- 包括nginx源码、zlib、openssl、pcre、perl、nasm、sed、nginx-http-flv-module、vs2017下载工具、VLC、ffmpeg(推流工具,到时候测试用) 、已经编译好的nginx 。
启动
进入Nginx目录,点击nginx.exe
启动服务;
启动成功后打开浏览器访问http://localhost:80 (opens new window)查看Nginx是否正常;
访问http://localhost:80/stat (opens new window)查看推流状态;
# 推流
FFmpeg命令
ffmpeg [[options][`-i’ input_file]] {[options] output_file}
options:
-i: url 输入文件网址
-vcodec: 设置视频编解码器 -codec:v -c:v
(强制使用codec编解码方式,如-vcodec xvid 使用xvid压缩 如果用copy表示原始编解码数据必须被拷贝)
-acodec: 设置音频编解码器 -codec:a -c:a
-f: fmt 强制输入或输出文件格式
推流测试-(本地视频 → RTMP)
通过FFmpeg进行推流测试-本地视频
ffmpeg -re -i ./test.mp4 -vcodec copy -acodec copy -f flv "rtmp://127.0.0.1:1935/live/test"
推流测试-(RTSP → FLV)
ffmpeg -re -i "rtsp://admin:000ppp@@@@192.168.100.111:554/video3" -vcodec copy -acodec copy -f flv "rtmp://127.0.0.1:1935/live/camera2"
ffmpeg -i "rtsp://admin:000ppp@@@@192.168.100.111:554/video3" -f flv -r 25 -s 1920*1080 -an "rtmp://127.0.0.1:1935/live/camera2"
ffmpeg -re -i "rtsp://admin:000ppp@@@@192.168.100.111:554/video3" -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -acodec copy -f flv "rtmp://127.0.0.1:1935/live/camera2"
# 拉流
使用VLC拉流测试
打开VLC
,媒体 -> 打开网络串流 -> 网络
rtmp://127.0.0.1:1935/live/test
使用ffplay拉流测试
ffplay rtmp://127.0.0.1:1935/live/test
http-flv播放地址
地址拼接如下:
http://127.0.0.1:80/live?port=1935&app=live&stream=test
html页面集成flv.js进行video播放
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>video</title>
<link rel="icon" href="../image/terrain.ico" type="image/x-icon">
<link rel="stylesheet" href="../dependent/video-js.css">
</head>
<script src="https://cdn.bootcss.com/flv.js/1.4.0/flv.min.js"></script>
<body>
<div>
<video id="vVideo" width="600" height="500" controls muted autoplay />
</div>
<script>
//原生H5支持的媒体格式主要有MP4、OGG、WebM、M3U8
if (flvjs.isSupported()) {
var videoElement = document.getElementById('vVideo');
var flvPlayer = flvjs.createPlayer({
type: 'flv',
url:'http://127.0.0.1:80/live?port=1935&app=live&stream=test'
});
flvPlayer.attachMediaElement(videoElement);
flvPlayer.load();
flvPlayer.play();
}
</script>
</body>
</html>
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
# 3.6 SRS
SRS(Simple Realtime Server)
SRS是一个简单高效的实时视频服务器,支持RTMP、WebRTC、HLS、HTTP-FLV、SRT等多种实时流媒体协议。**C++**语言编写。
直播是SRS的典型场景。
# SRS网址汇总
官方文档
- SRS官网:https://ossrs.net (opens new window)
- SRS官方文档:SRS 4.0 官方文档 (opens new window)
- 在线SRS播放器:srs-player (opens new window)
- Docker部署SRS (opens new window)
- SRS 点播FLV流 (opens new window)
代码
- SRS Github官方地址:https://github.com/ossrs/srs (opens new window)
- SRS Gitee官方地址:https://gitee.com/ossrs (opens new window)
视频
# SRS特性
- 简单:基于协程技术,无异步回调难以维护的问题,SRS支持云原生标准(Docker镜像、K8s部署、可观测性日志和监控指标等),提供云SRS无门槛应用;
- 实时:SRS聚焦于实时流媒体网关,实现实时流媒体协议的接入和互相转换以及不断迭代,比如RTMP、HLS、WebRTC、HTTP-FLV和SRT等;
- 高效:SRS是高性能流媒体服务器,是同类服务器的2~3倍性能,提供非常完整的概念和一致性设计,实现高效的流媒体应用;
# SRS架构图
# SRS支持协议
# SRS发展历程
# SRS使用案例
丽江热线 (opens new window),丽江广播电视台。
监控系统
某工厂的监控系统主要组成:
- 采集端:采集端采用IPC摄像头安装在工厂重要监控位置,通过网线或者wifi连接到监控中心交换机。
- 监控中心:中心控制服务器,负责管理采集端和流媒体服务器,提供PC/Android/IOS观看平台。
- 流媒体服务器:负责接收采集端的流,提供观看端RTMP/HLS的流。
- 观看端:PC/Android/IOS。要求PC端的延迟在3秒内。Android/IOS延迟在20秒之内。
主要流程包括:
- 采集端启动:IPC摄像头像监控中心注册,获得发布地址,并告知监控中心采集端的信息,譬如摄像头设备名,ip地址,位置信息之类。
- 采集端开始推流:IPC摄像头使用librtmp发布到地址,即将音频视频数据推送到RTMP流媒体服务器。
- 流媒体服务器接收流:流媒体服务器使用SRS,接收采集端的RTMP流。FMS-3/3.5/4.5都有问题,估计是和librtmp对接问题。
- 观看端观看:用户使用PC/Android/IOS登录监控中心后,监控中心返回所有的摄像头信息和流地址。PC端使用flash,延迟在3秒之内;Android/IOS使用HLS,延迟在20秒之内。
- 时移:监控中心会开启录制计划,将RTMP流录制为FLV文件。用户可以在监控中心观看录制的历史视频。
视频监控
案例1:传统的视频监控客户端都是Windows pc桌面客户端,现在较多的公司都需要实现通过web去查看远程的视频监控,此时可以通过RTSP/GB28181推流推送到SRS流媒体服务器,然后通过RTMP或者HTTP-FLV协议进行拉流查看远程的摄像头。
案例2:传统的推流端都需要安装应用软件才能实现推流,但是目前也是有web化的趋势,需要通过浏览器网页将音视频画面推送给听众,此时就可以通过WebRTC推流到SRS流媒体服务器,然后观众通过RTMP、HTTP-FLV等方式观看直播。
使用flvjs实现摄像头flv流低延时实时直播 (opens new window)
最近项目需要把监控摄像机的RTSP流在放在浏览器上播放,但由于目前浏览器并不支持RTSP,需要转码才行。之前试过Nginx作为流媒体服务器,这次尝试使用FFmpeg将码流推送SRS流媒体服务器,实现浏览器端播放。
# 四、流媒体播放插件
# 4.1 video.js
video.js Github官方地址:https://github.com/videojs/video.js/releases (opens new window)
video.js官方英文文档:https://docs.videojs.com/index.html (opens new window)
video.js 播放DEMO:http://xieze.gitee.io/videojs/ (opens new window)
video.js DEMO代码:https://gitee.com/xieze/videojs/blob/master/index.html (opens new window)
video.js 介绍参考文档 (opens new window)
Video.js是一款web视频播放器,支持html5和flash两种播放方式。更有自定义皮肤,插件,组件,语言还有丰富的选项配置。
引入video.js
,前端可处理HLS
格式视频流。
# 4.2 flv.js
Github官方地址:https://github.com/Bilibili/flv.js/ (opens new window)
flv.js 官方demo地址:http://bilibili.github.io/flv.js/demo/ (opens new window)
flv.js 官方文档:https://github.com/bilibili/flv.js/tree/master/docs (opens new window)
flv.js介绍参考文档 (opens new window)
Flv.js 是 HTML5 Flash 视频(FLV)播放器,纯原生 JavaScript 开发,没有用到 Flash。
由 bilibili
网站开源。它的工作原理是将 FLV 文件流转码复用成 ISO BMFF(MP4 碎片)片段,然后通过 Media Source Extensions 将 MP4 片段喂进浏览器。
原生video标签只支持Ogg、MPEG4、WebM三种格式,默认需要安装flash插件才可以播放。flv.js
插件可直接转码,vue项目直接使用,但推流端视频编码必须是H.264。
# 特征
- FLV 容器,具有 H.264 + AAC 编解码器播放功能
- 多部分分段视频播放
- HTTP FLV 低延迟实时流播放 FLV 通过WebSocket 实时流播放
- 兼容 Chrome, FireFox, Safari 10, IE11 和 Edge
- 十分低开销,并且通过你的浏览器进行硬件加速
# websocket-flv
浏览器的http有连接限制,一般而言,浏览器http连接数最大不超过6个连接,比如常用的chrome浏览器的最大http连接数是6个,大部分浏览器http连接数限制如下图所示:
与大部分http接口使用短连接不同的是,http-flv是长连接,而且不会释放,会一直占用http连接,所以浏览器端过多使用http长连接(超过6个)之后会导致浏览器http连接阻塞,无法发送任何http连接,也无法请求任何http接口。
websocket-flv
是为了解决http-flv
的一些弊端而出现的流媒体传输技术。
现代浏览器(chrome、safari、firefox、edge、IE11+等)都可以直接播放websocket-flv格式视频。
利用浏览器的mse特性,来使用基于flv.js转封装技术的播放器来播放JavaCV实现的websocket-flv直播。
# 4.3 xgplayer
西瓜播放器xgplayer: http://h5player.bytedance.com (opens new window)
西瓜播放器 Github官方地址: https://github.com/bytedance/xgplayer (opens new window)
西瓜播放器快速上手文档 (opens new window)
西瓜播放器使用代码示例 (opens new window)
西瓜播放器(xgplayer
)是一个Web视频播放器类库,它本着一切都是组件化的原则设计了独立可拆卸的 UI 组件。更重要的是它不只是在 UI 层有灵活的表现,在功能上也做了大胆的尝试:摆脱视频加载、缓冲、格式支持对 video 的依赖。尤其是在 mp4 点播上做了较大的努力,让本不支持流式播放的 mp4 能做到分段加载,这就意味着可以做到清晰度无缝切换、加载控制、节省视频流量。同时,它也集成了对 flv、hls、dash 的点播和直播支持。
# 起步
安装
npm install xgplayer -S
1使用
Step 1:
<div id="vs"></div>
1Step 2:
import Player from 'xgplayer' let player = new Player({ id: 'vs', url: 'https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/byted-player-videos/1.0.0/xgplayer-demo.mp4' })
1
2
3
4
5
6这是最简单的播放器配置方法,基本功能可以跑起来,如果想使用高级功能参考插件一节或者文档。更多配置 (opens new window)
# 五、各大主流厂商RTSP大全
数据来源于项目EasyMedia (opens new window),自行替换用户名密码、ip端口。
一. 海康、中威摄像机、萤石云
格式1:
主码流:rtsp://admin:12345@192.168.1.64:554/Streaming/Channels/1
子码流:rtsp://admin:12345@192.168.1.64:554/Streaming/Channels/2
格式2:
主码流:rtsp://admin:12345@192.168.1.64:554/Streaming/Channels/101
子码流:rtsp://admin:12345@192.168.1.64:554/Streaming/Channels/102
第三码流:rtsp://admin:12345@192.168.1.64:554/Streaming/Channels/3
2
3
4
5
6
7
8
9
二. 大华
rtsp://admin:12345@192.168.1.64:554/cam/realmonitor?channel=1&subtype=0
三. 英飞拓
球机:
单播和组播地址一致
高码流(主码流)RTSP地址:rtsp://admin:admin@192.168.1.64/1/1080p
低码流(子码流)RTSP地址:rtsp://admin:admin@192.168.1.64/1/D1
半球和枪机:(亭子、车道)
单播:
高码流(主码流)RTSP地址:rtsp://192.168.1.64:554/1/h264major
低码流(子码流)RTSP地址:rtsp://192.168.1.64:554/1/h264minor
组播:
高码流(主码流)RTSP地址:rtsp://192.168.1.64:554/1/h264major/multicast
低码流(子码流)RTSP地址:rtsp://192.168.1.64:554/1/h264minor/multicast
2
3
4
5
6
7
8
9
10
11
12
13
14
15
四. 三星
单播:
高码流rtsp地址:rtsp://admin:admin001@192.168.1.64:554/onvif/profile2/media.smp(720P)
低码率rtsp地址:rtsp://admin:admin001@192.168.1.64:554/onvif/profile3/media.smp
组播:
高码流rtsp地址:rtsp://admin:admin001@192.168.1.64:554/onvif/multicast/profile2/media.smp (720p)
低码流rtsp地址: rtsp://admin:admin001@192.168.1.64:554/onvif/multicast/profile3/media.smp
2
3
4
5
6
7
8
9
五. 宇视:
主码流:rtsp://admin:admin@192.168.8.8:554/video1
辅码流:rtsp://admin:admin@192.168.8.8:554/video2
三码流:rtsp://admin:admin@192.168.8.8:554/video3
2
3
六. LG
单播和组播地址一致
高码流(主码流)RTSP地址:rtsp://admin:admin@192.168.1.64:554/Master-0
低码流(子码流)RTSP地址:rtsp://admin:admin@1192.168.1.64:554/Slave-0
2
3
4
七、 派尔高网络摄像机:
RTSP主码流地址为:rtsp://192.168.1.64/h264
第一从码流RTSP地址为:rtsp://192.168.1.64/h264_2
第二从码流RTSP地址为:rtsp://192.168.1.64/h264_3
2
3
4
八、 安讯士网络摄像机:
单播:rtsp://root:123456@192.168.1.64/axis-media/media.amp?videocodec=h264&resolution=1280x720&fps=25
组播:rtsp://root:123456@192.168.1.64/onvif-media/media.amp?profile=profile_1_h264&streamtype=multicast
http://root:123456@192.168.1.64/axis-cgi/alwaysmulti.sdp?camera=1
2
3
4
5
九. 非凡
rtsp://admin:12345@192.168.1.64:554/streaming/channels/101
十. 金三立
rtsp://Admin:111111@192.168.1.64/stream/av0_0
# 六、相关资料
# Nginx相关
nginx源码下载地址 (opens new window)
官方nginx 1.7.11.3 Gryphon下载地址 (opens new window)
nginx-rtmp-module下载地址 (opens new window)
官方nginx-http-flv-module下载地址 (opens new window)
好人提供的nginx编译后的依赖包福利 (opens new window)
# FFmpeg
ffmpeg的基本用法 (opens new window)
# JavaCV
OpenCV官方文档:https://docs.opencv.org (opens new window)
JavaCV官方网址:http://bytedeco.org/ (opens new window)
JavaCV Github官方网址:https://github.com/bytedeco/javacv (opens new window)
JavaCV入门教程目录 (opens new window)
JavaCV开发详解专栏文章目录 (opens new window)
JavaCV音视频实战宝典 (opens new window)
# video.js
video.js Github官方地址:https://github.com/videojs/video.js/releases (opens new window)
video.js官方英文文档:https://docs.videojs.com/index.html (opens new window)
video.js 播放DEMO:http://xieze.gitee.io/videojs/ (opens new window)
video.js DEMO代码:https://gitee.com/xieze/videojs/blob/master/index.html (opens new window)
video.js 介绍参考文档 (opens new window)
# flv.js
Github官方地址:https://github.com/Bilibili/flv.js/ (opens new window)
flv.js 官方demo地址:http://bilibili.github.io/flv.js/demo/ (opens new window)
flv.js 官方文档:https://github.com/bilibili/flv.js/tree/master/docs (opens new window)
flv.js介绍参考文档 (opens new window)
# xgplayer
西瓜播放器xgplayer: http://h5player.bytedance.com (opens new window)
西瓜播放器 Github官方地址: https://github.com/bytedance/xgplayer (opens new window)