前言

公众号看到关于ffmpeg视频流推送文章,各种协议,推流,rtsp,.m3u8,一时看的云里雾里,经过一下午的不停捣鼓,勉强算是跑通了流程;总结一下大概就是:后端服务器调用ffmpeg接流(一般摄像头或其他设备会有一个推流地址,类似于rtsp://rtspstream:71b263fc8cea55aaaa8f30f2f9e57602@zephyr.rtsp.stream/movie),通过nginx配置接收转换到本地服务器静态资源,最终生成.m3u8和ts切片文件,再提供给前端拉流访问。
大概流程如图

alt 属性文本

必要的配置

默认安装的nginx缺少nginx-http-flv-module和nginx-http-flv-module模块,所以需要重新编译安装,

1
2
3
4
5
./configure \
--prefix=/usr/local/nginx \
... \
--add-module=/usr/local/nginx/nginx-1.13.7/moduleFile/nginx-rtmp-module # 添加rtmp模块
--add-module=/usr/local/nginx/nginx-1.13.7/moduleFile/nginx-http-flv-module # 添加flv模块

nginx添加rtmp配置,需要注意防火墙安全组设置,端口是否开放

1
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
rtmp {
server {
listen 1935;
ping 30s;
chunk_size 4000;
notify_method get;

application live { # 推流地址rtmp://ip:1935/live/密钥,同拉流播放地址
live on;
record all; # 是否开启记录 alloff, all,用于录制直播视频以便回放重播
record_unique on; # 记录值唯一
record_max_size 200M; # 记录文件大小
record_path /www/tmp/video; # 记录文件位置
record_suffix -%Y-%m-%d-%H_%M_%S.flv; # 记录文件命名
# on_publish http://127.0.0.1:8686/auth; # 开始推流的回调地址
#on_done 'http://when live stop call this url'; # 结束推流的回调地址
#on_play http://127.0.0.1:8686/auth; # 开始播放的回调地址
}

application hls { # 推流地址rtmp://ip:1935/hls/密钥,开启HLS协议进行m3u8直播
live on;
hls on; # 开启hls, hls的推流会产生一个m3u8的ts视频文件索引,同时保存一个个视频片段缓存,可以拿到再次播放。
hls_path /www/tmp/hls; # 视频切片ts文件存放的位置
hls_sync 100ms;
hls_fragment 5s; # 视频切片的大小,ts文件大小
hls_cleanup on; #对多余的切片进行删除
hls_playlist_length 600s; #保存m3u8列表长度时间,默认是30秒
}

#application vod { # 用于视频点播flv/mp4
# play /www/tmp/videos; # 本地视频MP4文件存放地址,作为流播放视频: rtmp://ip:1935/vod/视频名称.mp4
#}
#application vod_http { # 播放远程http链接的视频,rtmp://ip:1935/vod_http/视频名称.mp4
# play http://localhost:8080/vod/;
#}
}
}

实际推流时rtmp://47.116.44.235:1935/hls/test2会推送到/hls生成文件资源到/www/tmp/hls目录下
alt 属性文本

安装ffmpeg,调试时可能会报错Encoder (codec h264) not found for output stream,需要为ffmpeg增加h264编解码功能模块,参照 https://www.cnblogs.com/EasyNVR/p/11505865.html

实际调试运行

实际真实推流地址可能没有,前期可以通过ffmpeg将本地mp4或其他视频文件转换模拟流推送测试

1
ffmpeg -re -i /opt/files/other/media/test_2.mp4 -c:v copy -c:a copy -f flv rtmp://47.116.44.235:1935/hls/test2

也可以不走nginx配置地址直接转换到指定目录生成资源文件

1
ffmpeg -re -stream_loop -1 -i test.mp4 -rtsp_transport tcp -vcodec h264 -f hls -hls_time 10 -hls_list_size 0 /www/tmp/hls/test.m3u8

实际真实推流地址

1
ffmpeg -i rtsp://rtspstream:71b263fc8cea55aaaa8f30f2f9e57602@zephyr.rtsp.stream/movie -c:v copy -c:a copy -f flv rtmp://47.116.44.235:1935/hls/test

执行过程中会在/www/tmp/hls/目录下不断生成资源文件,最终提供给前端拉流读取

alt 属性文本

前端访问

前端使用video-player测试查看,在线预览地址: https://portal.fuyunfeng.top/plugins_v2/index.html#/video-player

1
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<template>
<div class="m-video-player">
<video-player
class="video-player vjs-custom-skin"
ref="videoPlayer"
:playsinline="true"
:options="playerOptions"
>
</video-player>
</div>
</template>
<script>
export default {
name: 'MVideoPlayer',
props: {
src: {
type: String
},
cover_url: {
type: String
},
autoplay: {
type: Boolean,
default: false
}
},
data() {
return {
// 配置信息
playerOptions: {
playbackRates: [0.7, 1.0, 1.5, 2.0], // 播放速度
autoplay: this.autoplay, // 如果true,浏览器准备好时自动播放视频
muted: false, // 默认情况下将会消除任何音频。
loop: false, // 导致视频一结束就重新开始。
preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
language: 'zh-CN',
aspectRatio: '16:10', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
sources: [{
withCredentials: true,
type: "application/x-mpegURL", // m3u8视频的类型,而mp4的为video/mp4
// src: "/hls/live/1/index.m3u8",
// src: 'http://47.116.44.235:1936/hls/test2.m3u8'
src: 'https://portal.fuyunfeng.top/hls/test2.m3u8'
}],
// poster: this.cover_url, // 你的封面地址
width: document.documentElement.clientWidth,
notSupportedMessage: '此视频暂无法播放,请稍后再试', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
controlBar: {
timeDivider: true, // 当前时间和持续时间的分隔符
durationDisplay: true, // 显示持续时间
remainingTimeDisplay: false, // 是否显示剩余时间功能
fullscreenToggle: true // 是否显示全屏按钮
}
}
}
},
mounted() {
console.log('mounted');
}
}
</script>
<style lang="stylus" scoped>
.m-video-player {
& .video-js {
& .vjs-big-play-button {
top: 49%;
left: 46%;
}
}
}
</style>

alt 属性文本

也可以通过安装PotPlayer播放器预览查看

alt 属性文本

至此大概流程完结,但网上查看实际推拉流程序应该有专门的RTMP服务器确保 FFmpeg 进程持续不断地运行以接收和转发流,如nohup后台启动或者自定义shell脚本监测程序自动运行,后续待测试。