JavaCV之rtmp推流(FLV和M3U8)

JavaCV与FFmpeg

FFmpeg是一款开源的多媒体处理工具集,它包含了一系列用于处理音频、视频、字幕等多媒体数据的库和工具。
JavaCV集成了FFmpeg库,使得Java开发者可以使用FFmpeg的功能,比如视频解码、编码、格式转换等。
除了FFmpeg,Javacv封装了以下库:

  1. OpenCV: JavaCV封装了OpenCV(Open Source Computer Vision Library),这是一个广泛用于计算机视觉应用的开源库。
  2. FlyCapture: 用于 Point Grey 系列相机的库。
  3. ARToolKit: 一个增强现实(Augmented Reality)库,用于跟踪相机图像中的标记。
  4. JavaCpp: 这是JavaCV的底层库,用于在Java中调用C++代码,是整个JavaCV项目的基础。
  5. Libdc1394: 用于相机和摄像机的库。
  6. JavaCV Presets: 提供了一系列预设,将原生的C/C++函数封装为Java接口,简化了在Java中调用这些功能的过程。

准备

1、引入maven包

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

2、类与方法说明

FFmpegFrameGrabber FFmpegFrameRecorder 是 JavaCV 中用于处理视频的两个关键类,分别用于抓取视频帧和录制视频帧,底层使用了 FFmpeg 库。
我们可以使用 FFmpegFrameGrabber 打开视频文件,获取视频信息,然后不断地从视频中获取帧。
FFmpegFrameRecorder则从输入视频中抓取帧,进行解码后,将每一帧写入输出视频文件。
FFmpegFrameGrabber FFmpegFrameGrabber 配合使用,可以实现从视频源中抓取帧并将帧写入视频文件的完整流程。

2、推流流程

image.png

3、Nginx搭建rtmp服务器

(1)下载带有rtmp模块的nginx(Gryphon) http://nginx-win.ecsds.eu/download/
(2)在nginx中的conf文件夹配置rtmp。nginx-win.conf增加如下代码:

rtmp {server {listen 1935;application flv-live{live on;record off;allow play all;}}
}

添加后,cmd跳转到nginx目录,执行命令 nginx.exe -c conf/nginx-win.conf 即可

FLV直播和HLS直播

FLV(Flash Video)直播:

  1. 传输协议: FLV 使用 RTMP(Real-Time Messaging Protocol)作为传输协议。RTMP 是一种实时通信协议,通常用于传输音频、视频和数据。
  2. 实时性: FLV 提供较低的延迟,通常在数秒到十几秒之间,适用于需要更快实时性的应用场景。
  3. 支持性: FLV 需要 Flash 播放器来播放,而在现代浏览器和设备中,对 Flash 的支持逐渐减少。这导致了使用 FLV 的限制。

HLS(HTTP Live Streaming)直播:

  1. 传输协议: HLS 使用 HTTP 协议,这使得它更容易穿越防火墙和代理服务器。它通常基于标准的 HTTP 80/443 端口,因此更容易被防火墙允许。
  2. 实时性: 相对于 FLV,HLS 通常有更高的延迟,通常在 10 到 30 秒之间。这使得它不太适合需要极低延迟的实时应用。
  3. 支持性: HLS 更广泛地支持各种设备和浏览器,因为它基于标准的 HTTP 和 HTML5 规范,无需专门的插件或播放器。
  4. 自适应比特率: HLS 提供了自适应比特率功能,可以根据用户的网络情况自动调整视频质量,提供更好的观看体验。

选择 FLV 还是 HLS 取决于你的具体需求。如果需要较低的延迟,并且可以接受使用 Flash 播放器的限制,那么 FLV 可能是一个合适的选择。如果需要更广泛的设备和浏览器支持,并且可以接受稍高的延迟,那么 HLS 可能更适合。在实际应用中,有时候也会结合两者,使用不同的协议来满足不同的需求。

实现Flv推流

拿一个h264格式的mov视频来演示,先将mov转为flv并且进行推流。

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.*;public class RtmpFlv {private static final String outputUrl = "rtmp://localhost:1935/flv-live/test";private static final String inputUrl = "D:\视频.mov";public static void main(String[] args) throws FrameGrabber.Exception, FrameRecorder.Exception, InterruptedException {//设置FFmpeg日志级别avutil.av_log_set_level(avutil.AV_LOG_INFO);FFmpegLogCallback.set();//以文件路径的方式传入视频,当然也支持以流的方式传入FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputUrl);//开始捕获视频流grabber.start();//用于将捕获到的视频流转换为输出URL的mp4格式。FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputUrl, grabber.getImageWidth(), grabber.getImageHeight());recorder.setFormat("flv");recorder.setVideoBitrate(grabber.getVideoBitrate()); // 设置视频比特率recorder.setFrameRate(grabber.getVideoFrameRate()); // 设置帧率recorder.setGopSize((int) grabber.getVideoFrameRate()); // 设置关键帧间隔// CRF 是一种用于控制视频/音频质量的参数,它允许在保持目标质量的同时动态地调整比特率。较低的CRF值表示更高的质量,但也可能导致较大的文件大小recorder.setAudioOption("crf", "23");Frame frame;//设置音频编码为AACif (grabber.getAudioChannels() > 0) {recorder.setAudioChannels(grabber.getAudioChannels());recorder.setAudioBitrate(grabber.getAudioBitrate());recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);}recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);//将解码后的帧记录到输出文件中//recorder.start通常用于处理已经解码成图像的视频数据recorder.start();while ((frame = grabber.grab()) != null) {recorder.record(frame);}recorder.close();grabber.close();}
}

运行后,打开vlc软件,点击媒体-》打开串流网络 ,输入rtmp://localhost:1935/flv-live/test 进行播放

image.png

实现M3U8推流

代码和上面的大同小异,将一个H264的mp4视频转为hls,利用http播放m3u8文件。

import org.bytedeco.ffmpeg.avformat.AVFormatContext;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.*;public class RtmpM3U8 {private static final String outputUrl = "D:\nginx_rtmp\html\test.m3u8";private static final String inputUrl = "D:\视频.mp4";public static void main(String[] args) throws FrameGrabber.Exception, FrameRecorder.Exception {//设置FFmpeg日志级别avutil.av_log_set_level(avutil.AV_LOG_ERROR);FFmpegLogCallback.set();//以文件路径的方式传入视频,当然也支持以流的方式传入FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputUrl);//开始捕获视频流grabber.start();AVFormatContext avFormatContext = grabber.getFormatContext();//获取视频时长//long duration = avFormatContext.duration();//检查文件是否媒体流(视频流、音频流)if (avFormatContext.nb_streams() == 0) {//表明没有媒体流return;}//用于将捕获到的视频流转换为输出URL的mp4格式。FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputUrl, grabber.getImageWidth(), grabber.getImageHeight(),grabber.getAudioChannels());recorder.setFormat("hls");recorder.setVideoBitrate(grabber.getVideoBitrate()); // 设置视频比特率recorder.setFrameRate(grabber.getVideoFrameRate()); // 设置帧率recorder.setGopSize((int) grabber.getVideoFrameRate()); // 设置关键帧间隔// 设置HLS切片参数//将每个切片时长设置为10秒recorder.setOption("hls_time", "15");//设置切片数大小recorder.setOption("hls_list_size", "20");//设置切片循环次数为50recorder.setOption("hls_wrap", "20");//每次切片完成后,都会删除之前的切片文件。如果不设置或设置为其他值,则不会删除之前的切片文件。recorder.setOption("hls_flags", "delete_segments");//在使用 H.264 编码时,通常要求输入的像素格式为 YUV420P。如果输入的像素格式不匹配,就可能导致 avcodec_send_frame() 错误recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);//CRF 是一种用于控制视频/音频质量的参数,它允许在保持目标质量的同时动态地调整比特率。较低的CRF值表示更高的质量,但也可能导致较大的文件大小recorder.setAudioOption("crf", "23");Frame frame;//设置音频编码为AACif (grabber.getAudioChannels() > 0) {recorder.setAudioChannels(grabber.getAudioChannels());recorder.setAudioBitrate(grabber.getAudioBitrate());recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);}recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);//设置音频编码为AACif (grabber.getAudioChannels() > 0) {recorder.setAudioChannels(grabber.getAudioChannels());recorder.setAudioBitrate(grabber.getAudioBitrate());recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);}//将解码后的帧记录到输出文件中//recorder.start通常用于处理已经解码成图像的视频数据recorder.start();while ((frame = grabber.grab()) != null) {recorder.record(frame);}recorder.close();grabber.close();}}

开始推流后,会在D:\nginx_rtmp\html\生成m3u8和ts文件,我们只需要播放m3u8文件即可。

image.png

打开vlc软件,点击媒体-》打开串流网络 ,输入http://localhost:8080/test.m3u8 进行播放

优化TODO

后继利用高性能网络框架netty进行直播多路复用,避免视频重复解码推流,详情关注最新文章!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/214964.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode力扣每日一题(Java):35、搜索插入位置

一、题目 二、解题思路 1、我的思路&#xff08;又称&#xff1a;论API的重要性&#xff09; 读完题目之后&#xff0c;我心想这题目怎么看着这么眼熟&#xff1f;好像我之前学过的一个API呀&#xff01; 于是我回去翻了翻我之前写的博客&#xff1a;小白备战蓝桥杯&#xf…

通用的AGI 安全风险

传统安全风险 平台基础设施安全风险 模型与数据层安全风险 应用层安全风险 平台基础设施安全风险 &#xff08;1&#xff09;物理攻击&#xff1a;机房管控不到位 &#xff08;2&#xff09;网络攻击 &#xff08;3&#xff09;计算环境&#xff1a;自身安全漏洞&#xf…

编辑器Sublime text 常用快捷命令 列模式 替换空行

平替notepad 下载可取官网 www.sublimetext.com 据说可以无限试用&#xff0c;没有功能限制 1、快速删除空行 ctrl h选择正则表达式 .*Find输入&#xff1a; ^(\t)*$\nReplace输入&#xff1a;点击Replace All 2、快速选择指定字符 用鼠标选中alt f3修改 3、列编辑模式 ct…

宇视科技视频监控 main-cgi 文件信息泄露漏洞复现

0x01 产品简介 宇视(Uniview)高清网络摄像机是一种高性能的网络摄像机,它可以通过网络进行视频传输和监控。该摄像机采用先进的视频技术,具有高清晰度、低照度、宽动态等特点,能够提供高质量的视频图像。 0x02 漏洞概述 宇视(Uniview)高清网络摄像机存在信息泄露漏洞…

ppt编辑密码如何设置?

大家在PPT中设置了限制编辑&#xff0c;发现后面任然可以编辑文件。那么如何将PPT文件设置成禁止修改模式呢&#xff1f;今天分享几个方法给大家。 方法一 将PPT文件直接保存或者另存为一份文件&#xff0c;在保存时&#xff0c;将文件格式选择为PowerPoint图片演示文稿 方法…

.NET 8 编写 LiteDB vs SQLite 数据库 CRUD 接口性能测试(测试篇)

WebAppDbTest 项目测试 测试工具 ltt介绍安装使用方式1、Drill2、Hammer3、Nailgun 测试主机规格配置CRUD 性能测试对比1、ltt 工具测试1.1、AddSingle 单条数据添加1.2、AddBulk 批量数据&#xff08;1000&#xff09;条添加1.3、GetSingle 单条数据查询1.4、GetAll 多条&…

多合一iPhone 解锁工具:iMyFone LockWiper iOS

多合一iPhone 解锁工具 无需密码解锁 iPhone/iPad/iPod touch 上所有类型的屏幕锁定 在几分钟内解锁 iPhone Apple ID、Touch ID 和 Face ID 立即绕过 MDM 并删除 iPhone/iPad/iPod touch 上的 MDM 配置文件 支持所有 iOS 版本和设备&#xff0c;包括最新的 iOS 17 和 iPhone 1…

JAVA实操经验

零&#xff1a; 按照需要&#xff0c;可以使用需要某个类下&#xff08;主要是java提供的&#xff09;的方法来实现某个功能。&#xff08;主要是用在不同类下的方法会进行重写功能不同&#xff09; 方法和构造方法不同&#xff1a;方法是方法&#xff0c;构造方法是构造器&a…

基于FPGA的视频接口之高速IO

简介 相对于其他视频接口来说,高速IO接口(以Xilinx公司为例,spartan 6系列的GTP、Artix7系列的GTP,KENTEX7系列的GTX和GTH等)具有简化设计、充分利用FPGA资源、降低设计成本等功能。 高速IO接口传输视频,一般会被拓展为万兆以太网、40G以太网、10G光纤、40G光纤、3G-SDI、…

c语言插入排序及希尔排序详解

目录 前言&#xff1a; 插入排序&#xff1a; 希尔排序&#xff1a; 前言&#xff1a; 排序在我们生活中无处不在&#xff0c;比如学生成就排名&#xff0c;商品价格排名等等&#xff0c;所以排序在数据结构的学习中尤为重要&#xff0c;今天就为大家介绍两个经典的排序算法&…

深入解析C++中的虚函数和虚继承:实现多态性与继承关系的高级特性

这里写目录标题 虚函数虚函数实现动态绑定虚继承抽象类 虚函数 虚函数是在C中用于实现多态性的一种特殊函数。它通过使用关键字"virtual"进行声明&#xff0c;在基类中定义&#xff0c;可在派生类中进行重写。虚函数允许在运行时根据对象的实际类型来调用相应的函数…

BigData之Google Hadoop中间件安装

前言 Hadoop / Zookeeper / Hbase 因资源有限 这三个都是安装在同一台Centos7.9的机器上 但通过配置 所以在逻辑上是distributed模式 1 Java安装 1.1 下载java11 tar/opt/java/jdk-11.0.5/ 1.2 环境配置修改 文件/etc/profile export JAVA_HOME/opt/java/jdk-11.0.5/ e…

HarmonyOS编译开源native库(OpenSSL实例)

前言 近期项目要开始做鸿蒙版本&#xff0c;有一部分依赖native的代码也需要迁移&#xff0c;某个native模块依赖openssl&#xff0c;需要在鸿蒙下重新编译openssl才行。一开始找了很多相关文档都没有得到方法&#xff0c;无奈只能自己凭经验慢慢试&#xff0c;最后还是成功了…

JS基础之执行上下文

JS基础之执行上下文 执行上下文顺序执行可执行代码执行上下文栈回顾上文 执行上下文 顺序执行 写个JavaScript的开发者都会有个直观的印象&#xff0c;那就是顺序执行&#xff1a; var foo function(){console.log(foo1) } foo(); //foo1 var foo function(){console.log(…

HTML面试题---专题一

文章目录 一、前言二、 HTML5 中 <header> 和 <footer> 标签的用途是什么&#xff1f;三、如何在 HTML 中嵌入 SVG&#xff08;可缩放矢量图形&#xff09;文件&#xff1f;四、解释 contenteditable 属性的用途五、如何创建随屏幕尺寸缩放的响应式图像&#xff1f…

线上扭蛋机小程序搭建,扭蛋与科技的完美结合

扭蛋机作为当下比较热门的一种盲盒玩法&#xff0c;在年轻人群体中非常受欢迎。随着经济的增长和人们生活水平的提高&#xff0c;人们对娱乐消费需求也在增加&#xff0c;扭蛋机的受众群体也在扩大。 目前线上扭蛋机小程序也获得了大众的青睐&#xff0c;扭蛋机小程序就是把线…

记录一下快速上手Springboot登录注册项目

本教程需要安装以下工具&#xff0c;如果不清楚怎么安装的可以看下我的这篇文章 链接: https://blog.csdn.net/qq_30627241/article/details/134804675 管理工具&#xff1a; maven IDE&#xff1a; IDEA 数据库&#xff1a; MySQL 测试工具&#xff1a; Postman 打开IDE…

AR-LDM原理及代码分析

AR-LDM原理AR-LDM代码分析pytorch_lightning(pl)的hook流程main.py 具体分析TrainSampleLightningDatasetARLDM blip mm encoder AR-LDM原理 左边是模仿了自回归地从1, 2, ..., j-1来构造 j 时刻的 frame 的过程。 在普通Stable Diffusion的基础上&#xff0c;使用了1, 2, .…

网工内推 | 项目经理专场,最高20K*13薪,软考证书优先

01 Trasen 招聘岗位&#xff1a;大项目经理&#xff08;医疗行业/HIS&#xff09; 职责描述&#xff1a; 1.负责项目按计划完成交付并顺利验收结项&#xff1b; 2.参与项目前期预算、评审、方案设计等&#xff1b; 3.负责具体项目实施&#xff0c;制定项目计划、组织项目资源、…