目录

大致流程

环境:

CentOS 7 安装 ffmpeg

docker安装nginx-rtmp

nginx-rtmp配置文件详解

例子

java案例

pom依赖

代码案例

前端案例(vue)

javacv相关文档和博客


大致流程

环境:

名称 版本
jdk 1.8
ffmpeg ffmpeg version 4.1
javacv (jar包,拉取推送视频)
<dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>1.5.1</version>
</dependency>
alfg/nginx-rtmp (docker安装) latest

CentOS 7 安装 ffmpeg

FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。我们要用它拉取rtmp 转换成可视频,放入nginx。

//1. 下载
wget https://johnvansickle.com/ffmpeg/release-source/ffmpeg-4.1.tar.xz
//2. 解压
tar -xvJf ffmpeg-4.1.tar.xz
//3. 配置在configure存在的文件夹内运行
./configure --prefix=/usr/local/ffmpeg//如果第3 行的命令打印一下信息,
/* If you think configure made a mistake, make sure you are using the latest
version from Git.  If the latest version fails, report the problem to the
ffmpeg-user@ffmpeg.org mailing list or IRC #ffmpeg on irc.freenode.net.
Include the log file "config.log" produced by configure as this will help
solve the problem.*/--------------------------如果第三行的命令打印以上信息,你就需要安装yasm------------------
//4.1 下载yasm
wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz
//4.2 解压yasm
tar zxvf yasm-1.3.0.tar.gz -c /usr/local/software/yasm
//4.3 在configure 所在的文件夹内运行下命令
./configure
//4.4 编译,安装 yasm
make
make install
//4.5 修改配置文件vim /etc/ld.so.conf
//加入一下信息
include ld.so.conf.d/*.conf
/usr/local/ffmpeg/lib/
-------------------------------------------结束-----------------------------------
//6. 编译安装ffmpeg(在ffmpeg文件夹内)
make
make install//查看是否安装成功
ffmpeg -version

docker安装nginx-rtmp

注意:我们下载的是nginx-rtmp。

这个nginx解析不了rtmp协议

nginx-rtmp配置文件详解

daemon off;
error_log /dev/stdout info;
events {worker_connections 1024;
}
rtmp {server {listen 1935;chunk_size 4000; #默认流切片大小#后端会调用该地址推送rtmp流#地址例子: rtmp://localhost:1935/stream/test application stream {live on;#ffmpeg会使用一下命令 对推送的视频流进行格式转换,以及切片#切片就是将一段视频切割成多个 ts格式的视频文件。有一个xxx.m3u8的文件管理这些ts#我们只需要让前端访问这个xxx.m3u8的文件即可播放.ts视频#并调用rtmp://localhost:1935/hls这个地址保存视频exec ffmpeg -i rtmp://localhost:1935/stream/$name-c:a libfdk_aac -b:a 128k -c:v libx264 -b:v 2500k -f flv -g 30 -r 30 -s 1280x720 -preset superfast -profile:v baseline rtmp://localhost:1935/hls/$name_720p2628kbs#-c:a libfdk_aac -b:a 128k -c:v libx264 -b:v 1000k -f flv -g 30 -r 30 -s 854x480 -preset superfast -profile:v baseline rtmp://localhost:1935/hls/$name_480p1128kbs#-c:a libfdk_aac -b:a 128k -c:v libx264 -b:v 750k -f flv -g 30 -r 30 -s 640x360 -preset superfast -profile:v baseline rtmp://localhost:1935/hls/$name_360p878kbs#-c:a libfdk_aac -b:a 128k -c:v libx264 -b:v 400k -f flv -g 30 -r 30 -s 426x240 -preset superfast -profile:v baseline rtmp://localhost:1935/hls/$name_240p528kbs#-c:a libfdk_aac -b:a 64k -c:v libx264 -b:v 200k -f flv -g 15 -r 15 -s 426x240 -preset superfast -profile:v baseline rtmp://localhost:1935/hls/$name_240p264kbs;}application hls {live on;hls on;hls_fragment_naming system;hls_fragment 5;hls_playlist_length 10;#我们推送的流会保存到nginx的目录下/opt/data/hlshls_path /opt/data/hls;  hls_nested on;hls_variant _720p2628kbs BANDWIDTH=2628000,RESOLUTION=1280x720;#hls_variant _480p1128kbs BANDWIDTH=1128000,RESOLUTION=854x480;#hls_variant _360p878kbs BANDWIDTH=878000,RESOLUTION=640x360;#hls_variant _240p528kbs BANDWIDTH=528000,RESOLUTION=426x240;#hls_variant _240p264kbs BANDWIDTH=264000,RESOLUTION=426x240;}}
}http {root /www/static;sendfile off;tcp_nopush on;server_tokens off;access_log /dev/stdout combined;# Uncomment these lines to enable SSL.# ssl_ciphers         HIGH:!aNULL:!MD5;# ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;# ssl_session_cache   shared:SSL:10m;# ssl_session_timeout 10m;server {listen 80;# Uncomment these lines to enable SSL.# Update the ssl paths with your own certificate and private key.# listen 443 ssl;# ssl_certificate     /opt/certs/example.com.crt;# ssl_certificate_key /opt/certs/example.com.key;location /hls {types {application/vnd.apple.mpegurl m3u8;video/mp2t ts;}root /opt/data;add_header Cache-Control no-cache;add_header Access-Control-Allow-Origin *;}#前端调用这个地址 播放视频#例子 http://localhost/live/test.m3u8,就会去/opt/data/hls下找这个test.m3u8的文件location /live {alias /opt/data/hls;types {application/vnd.apple.mpegurl m3u8;video/mp2t ts;}add_header Cache-Control no-cache;add_header Access-Control-Allow-Origin *;}location /stat {rtmp_stat all;rtmp_stat_stylesheet stat.xsl;}location /stat.xsl {root /www/static;}location /crossdomain.xml {default_type text/xml;expires 24h;}}
}
//在root下创建工作目录
mkdir /root/nginx-rtmp/data
mkdir /root/nginx-rtmp/conf  #将上面的那个配置文件复制到conf下用来挂载使用
//运行镜像
docker run -p 1935:1935 -p 80:80 --name nginx-rtmp \  #要用1935(默认端口)推流
-v /root/nginx-rtmp/conf/nginx.conf:/etc/nginx/nginx.conf.template \ #挂载配置文件方便修改
-v /root/nginx-rtmp/data:/opt/data/hls \ #nginx默认将我们推送的视频流放到hls所以挂在该目录。方便检查
-d alfg/nginx-rtmp

例子

视频流保存nginx中的数据例子。

这些数据是通过java推送的,java推送的demo在下面

test_XXX等文件夹中保存的数据格式

名字是毫秒单位的时间戳,这些视频新的会替换掉旧的并不会越来越多.,前端调用test.m3u8播放这些ts切片文件

java案例

pom依赖

        <dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>1.5.1</version></dependency>

代码案例


import lombok.extern.slf4j.Slf4j;
import org.bytedeco.ffmpeg.avcodec.AVPacket;
import org.bytedeco.ffmpeg.avformat.AVFormatContext;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.FrameRecorder;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;@Slf4j
public class ConvertVideoPakcet {private static final Map<String,ConvertVideoPakcet> convertVideoPakcets = new HashMap<>();private FFmpegFrameGrabber grabber = null;private FFmpegFrameRecorder record = null;private int width = -1, height = -1;// 视频参数private int audiocodecid;private int codecid;private double framerate;// 帧率private int bitrate;// 比特率// 音频参数private int audioChannels;private int audioBitrate;private int sampleRate;//控制程序循环private Boolean flag = true;private static ConvertVideoPakcet get(String deviceId){return convertVideoPakcets.get(deviceId);}public static Boolean start(String deviceId,String formUrl,String toUrl){if(null != get(deviceId)) return true;final ConvertVideoPakcet convertVideoPakcet = new ConvertVideoPakcet();convertVideoPakcets.put(deviceId,convertVideoPakcet);new Thread(()->{log.info("start device");try {convertVideoPakcet.rtsp(formUrl).rtmp(toUrl).start();} catch (IOException e) {log.error("start dvice error,{}",e);} catch (Exception e) {e.printStackTrace();}}).start();log.info("start device finish!");return true;}/*** 停止当前直播* @param id* @return*/public static Boolean stop(String id){log.info("stop device ,{}",id);ConvertVideoPakcet convertVideoPakcet = get(id);if(null != convertVideoPakcet){convertVideoPakcets.remove(id);return convertVideoPakcet.stop();}return false;}/*** 拉取摄像头或者其他rtmp视频源** @param src rtsp数据源地址* @author JW* @throws Exception*/private ConvertVideoPakcet rtsp(String src) throws Exception {// 采集/抓取器grabber = new FFmpegFrameGrabber(src);grabber.setOption("rtsp_transport", "tcp");grabber.start();// 开始之后ffmpeg会采集视频信息,之后就可以获取音视频信息if (width < 0 || height < 0) {width = grabber.getImageWidth();height = grabber.getImageHeight();}// 视频参数audiocodecid = grabber.getAudioCodec();log.warn("音频编码:{}",audiocodecid);codecid = grabber.getVideoCodec();framerate = grabber.getVideoFrameRate();// 帧率bitrate = grabber.getVideoBitrate();// 比特率// 音频参数// 想要录制音频,这三个参数必须有:audioChannels > 0 && audioBitrate > 0 && sampleRate > 0audioChannels = grabber.getAudioChannels();audioBitrate = grabber.getAudioBitrate();if (audioBitrate < 1) {audioBitrate = 128 * 1000;// 默认音频比特率}return this;}/*** rtmp输出推流到nginx媒体流服务器** @param out t\ rtmp媒体流服务器地址* @author JW* @throws IOException*/private ConvertVideoPakcet rtmp(String out) throws IOException {// 录制/推流器record = new FFmpegFrameRecorder(out, width, height);record.setVideoOption("crf", "30");record.setGopSize(2);record.setFrameRate(framerate);record.setVideoBitrate(bitrate);record.setAudioChannels(audioChannels);record.setAudioBitrate(audioBitrate);record.setSampleRate(sampleRate);AVFormatContext fc = null;
//        if (out.indexOf("rtmp") >= 0 || out.indexOf("flv") > 0) {// 封装格式flvrecord.setFormat("flv");record.setAudioCodecName("aac");record.setVideoCodec(codecid);fc = grabber.getFormatContext();
//        }record.start(fc);return this;}/*** 转封装** @author eguid* @throws IOException*/private void start() throws IOException {//刷新开始的测试数据if(null != grabber)grabber.flush();while (flag) {AVPacket pkt = null;try {// 没有解码的音视频帧pkt = grabber.grabPacket();if (pkt == null || pkt.size() <= 0 || pkt.data() == null) {continue;}// 不需要编码直接把音视频帧推出去record.recordPacket(pkt);avcodec.av_packet_unref(pkt);try {Thread.sleep(0,1000);} catch (InterruptedException e) {log.error("推流发生等待异常,{}",e);}} catch (Exception e) {log.error("推流发生异常,{}",e);}}}private Boolean stop() {//控制退出循环flag = false;if(null != record){try {record.release();} catch (FrameRecorder.Exception e) {log.error("stop record error ,{}",e);return false;}}if(null != grabber){try {grabber.release();} catch (Exception e) {log.error("stop grabber error ,{}",e);return false;}}return true;}public static void main(String[] args) throws Exception, IOException {// 运行,设置视频源地址,拉取的视频存在的地址new ConvertVideoPakcet().rtsp("rtmp://media3.scctv.net/live/scctv_800")//我们要推送到的nginx的地址.rtmp("rtmp://localhost:1935/stream/test").start();}
}

前端案例(vue)

//安装依赖
npm install --save hls.js//标签 案例
<video ref=""videoRef" width="400" controls></video>
<script>
import Hls from 'hls.js'; export default {mounted: function() {var hls = new Hls();hls.loadSource('http://localhost/live/test.m3u8');hls.attachMedia(this.$refs.videoRef);hls.on(Hls.Events.MANIFEST_PARSED,function() {this.$refs.videoRef.play();});}
}
</script>

地址详解:

javacv相关文档和博客

一位大佬写的关于javacv的博客

javacv的 接口文档

nginx这个不是必须的,其实也可以在后端切片后。使用websocket长连接向前端推送

java + nginx + ffmpeg + vue实现摄像头,rtmp、rtsp直播流协议的实时播放相关推荐

  1. Android ijkplayer播放rtsp直播流

    因为Android ijkplayer播放rtsp直播流在加载时延迟在5-10秒实在难以接受,再修改后解决了延迟问题,目前已达到2秒甚至秒开的效果 添加的方法:VideoOptionModel vid ...

  2. Java使用FFmpeg进行推流,SRS进行拉流,实现转码

     因为公司业务需要把监控摄像机的RTSP流放在浏览器上播放,但由于目前浏览器上播放RTSP协议的视频流需要集成插件,插件只能在固定的浏览器版本上使用,缺点比较大,所以想着通过转码的方式实现在浏览器上播 ...

  3. Windows平台RTMP/RTSP直播推送模块设计和使用说明

    开发背景 好多开发者一直反馈,Windows平台,做个推屏或者推摄像头,推RTMP或者RTSP出去,不知道哪些功能是必须的,哪些设计是可有可无的,还有就是,不知道如何选技术方案,以下是基于我们设计的W ...

  4. NVIDIA DeepStream配置文件解析;摄像头源RTSP拉流源输入,RTSP推流输出

    一.DeepStream配置文件解析 参考:官方文档 DeepStream Reference Application - deepstream-app 1. DeepStream应用程序架构 下图为 ...

  5. java调用easyxml接口_【技术教程】如何通过Java程序调用RTSP拉流协议视频平台EasyNVR程序接口?...

    原标题:[技术教程]如何通过Java程序调用RTSP拉流协议视频平台EasyNVR程序接口? RTSP协议视频平台EasyNVR经过多年的积累,已经是一套成熟且完善的视频平台了,用户可以通过网页直接访 ...

  6. 麒麟操作系统|Linux下低延时RTMP|RTSP直播播放实现

    背景 国产操作系统多为以Linux为基础二次开发的操作系统.2014年4月8日起,美国微软公司停止了对Windows XP SP3操作系统提供服务支持,这引起了社会和广大用户的广泛关注和对信息安全的担 ...

  7. rtsp h256 流 web 软解播放

    rtsp h256 流 web 软解播放 本项目地址 https://github.com/huskar-t/h265 修改自项目 https://github.com/goldvideo/h265p ...

  8. 魔坊APP项目-27-直播、客户端中调整窗口大小、能播放rtmp格式直播流的播放器模块

    直播 客户端中直播的界面调整和当前窗口一致 live_list.html <!DOCTYPE html> <html lang="en"> <head ...

  9. 视频技术详解:RTMP H5 直播流技术解析

    本文聚焦 RTMP 协议的最精华的内容,接进行实际操作 Buffer 的练习和协议的学习. RTMP 是什么 RTMP 全称即是 Real-Time Messaging Protocol.顾名思义就是 ...

最新文章

  1. (C++)字符数组的四种输入输出方式
  2. ​易生信-宏基因组积微学术论坛:基于大数据整合准确预测土壤的枯萎病发生...
  3. python3安装-Centos 安装 Python3
  4. SqlServer操作远程数据库
  5. boost::python::detail::copy_ctor_mutates_rhs相关的测试程序
  6. 页面体验提升小技巧—渐进式图片
  7. vue实现可编辑的文字_苹果还自带文字转语音,只要一键按下便可实现,今天分享给大家...
  8. Mysql主从延时解决办法
  9. 斑能不能彻底去掉_淡妆能不能只用洗面奶卸掉?
  10. (46)FPGA面试题FPGA内部结构及资源
  11. curl: (7) Failed connect to localhost:9200; Connection refused
  12. javascript实现图片轮播_手撸一个简易版轮播图(上)
  13. 如何去掉显卡的桌面右键菜单:
  14. spring 事物管理器
  15. pfSense®与OPNsense®技术比较
  16. 使用intel编译器编译WRF4.4
  17. pathon初学入门课
  18. 切绳子(二分,c语言)
  19. CentOS7安装yum
  20. python筛选股票_GitHub - mykazey/stock_pick: 这时一个通过设定选股条件来帮我们筛选股票的python程序...

热门文章

  1. n维椭球体积公式_为了方差无偏估计为什么要用n-1?
  2. 基于kali的一次无线渗透测试
  3. Rust代码检查工具Clippy原理浅析
  4. 联想台式计算机g50500i,联想台式电脑的价格及配置
  5. cadence-ALLEGRO异形焊盘封装制作及解决个别报错问题
  6. 数据分析师招聘情况之python分析
  7. 推荐:大文件查找,快速扫描,图像分析并清理硬盘垃圾文件的绝佳好工具!
  8. 旋转手机摄像头想法 -Camerax
  9. python 完全面向对象_python之面向对象
  10. 实验室暑期CTF训练赛--第三、四周