当前位置: 首页 > news >正文

行业网站网址收费下载网站源码

行业网站网址,收费下载网站源码,网页设计制作网站模板,利润在100万到300万之间税率20211、背景 最近在做视频转发的开发时#xff0c;遇到一个问题#xff0c;前端订阅播放h264视频流时#xff0c;有时会出现一段时间黑屏#xff0c;经过测试发现是没有收到关键帧#xff0c;只有第一帧是关键帧才能保证后续播放正常。所以后端需要实现一个功能#xff0c;就…1、背景 最近在做视频转发的开发时遇到一个问题前端订阅播放h264视频流时有时会出现一段时间黑屏经过测试发现是没有收到关键帧只有第一帧是关键帧才能保证后续播放正常。所以后端需要实现一个功能就是前端在进入播放页面时后端把最近的一个关键帧发过去。 2、思路环形缓存区 后端接收到的视频流是一个个的字节数组所以在接收时没法直接判断一帧的开始和结束需要将最近的一段视频流截取出来然后利用ffmpeg工具进行整体的解析和关键帧提取。 查看ffmpeg工具的代码可以发现ffmpeg工具入参是inputstream该工具会不断调用inputstream的read方法进行字节的读取。所以就想通过一个环形缓存区不断的记录最新的一段视频流数据。该环形缓存区再实现inputstream的接口重写read方法read读取的开始位置即是环形缓存区头到环形缓存区的尾时自动结束。 3、依赖包 !-- javacv -- dependencygroupIdorg.bytedeco/groupIdartifactIdjavacpp/artifactIdversion1.4.3/version /dependency dependencygroupIdorg.bytedeco/groupIdartifactIdjavacv/artifactIdversion1.4.3/version /dependency dependencygroupIdorg.bytedeco.javacpp-presets/groupIdartifactIdffmpeg-platform/artifactIdversion4.0.2-1.4.3/version /dependency 4、环形缓存区定义 public class CycleBufferInputStream extends InputStream {/************************************************ 环形缓冲区 ***********************************************/private ByteBuffer buffer null;private int readPos 0; //将要读取的位置private int writePos 0; //将要写入的位置private boolean isCycle false; //判断是否已经形成一个环public CycleBufferInputStream(int capacity) {this.buffer ByteBuffer.allocateDirect(capacity);}/*** 将字节数组以覆盖的方式放入环形缓冲区*/public void put(byte[] bytes) {int used buffer.capacity() - buffer.position();if (used bytes.length) {buffer.put(bytes, 0, used);buffer.clear();buffer.put(bytes, used, bytes.length - used);isCycle true;} else if (used bytes.length) {buffer.put(bytes, 0, used);buffer.clear();isCycle true;} else {buffer.put(bytes, 0, bytes.length);}writePos buffer.position();}/*** 定位读取的初始位置执行inputstream 读取前必须要先调用该方法*/public void readPrepare() {if (buffer.capacity() writePos || !isCycle) {readPos 0;} else {readPos buffer.position() 1;}}/*************************************************** 输入流传输 ***************************************************//*** Reads the next byte of data from the input stream. The value byte is returned as an int in the range 0 to 255. If no byte is available because the end of the stream has been reached, the value -1 is returned. This method blocks until input data is available, the end of the stream is detected, or an exception is thrown.* A subclass must provide an implementation of this method.* Returns: the next byte of data, or -1 if the end of the stream is reached.* Throws: IOException – if an I/O error occurs.*/Overridepublic int read() throws IOException {if (readPos buffer.capacity()) readPos 0;if (readPos writePos) return -1;int value buffer.get(readPos);if (value 0) value value 256;return value;}} 5、从环形缓存区提取关键帧 /*** 从环形缓存环获取最近一帧关键帧字节数组* 这里返回的堆外内存所以注意要及时进行内存释放* param inputStream*/public static ByteBuffer dealVideo(InputStream inputStream) {try {int j 0;FFmpegFrameGrabber ff new FFmpegFrameGrabber(inputStream);ff.start();Frame frame null;Frame last null;while ((frame ff.grabKeyFrame()) ! null frame.image ! null) {last frame.clone();System.out.println(获取一帧 j);}ff.stop();if (last ! null) {System.out.println(获取最近的一个关键帧);ByteBuffer byteBuffer (ByteBuffer)last.image[0];return byteBuffer;}} catch (Exception e) {log.error(提取最近一个关键帧异常\n,e);}return null;} 6、使用 public static void main(String[] args) throws Exception {CycleBufferInputStream stream new CycleBufferInputStream(1024 * 1024 * 10);FileInputStream fis new FileInputStream(D:\\tmp-data\\1694511149969.h264);byte[] bytes new byte[fis.available()];fis.read(bytes);stream.put(bytes);stream.readPrepare();dealVideo(stream);} 7、扩展获取近期视频的截图 其实就是从近期的关键帧中提取出图片关键代码如下 public static void dealImage(InputStream inputStream) {try {Java2DFrameConverter converter new Java2DFrameConverter();FFmpegFrameGrabber ff new FFmpegFrameGrabber(inputStream);ff.start();int j 0;Frame frame null;Frame last null;while ((frame ff.grabImage()) ! null) {last frame.clone();System.out.println(获取一张图片 j);}ff.stop();if (last ! null last.image ! null) {System.out.println(存储最后一张图片 );BufferedImage fecthedImage converter.getBufferedImage(last);File screenshotFile new File(D:\\tmp-data\\, System.currentTimeMillis() .jpg);ImageIO.write(fecthedImage, jpg, screenshotFile);}} catch (Exception e) {log.error(提取最近一个图片异常\n,e);}} 8、整体代码 package com.qq.utils;import lombok.extern.slf4j.Slf4j; import org.bytedeco.javacv.FFmpegFrameGrabber; import org.bytedeco.javacv.Frame; import org.bytedeco.javacv.Java2DFrameConverter;import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.*; import java.nio.ByteBuffer;Slf4j public class CycleBufferInputStream extends InputStream {/************************************************ 环形缓冲区 ***********************************************/private ByteBuffer buffer null;private int readPos 0; //将要读取的位置private int writePos 0; //将要写入的位置private boolean isCycle false; //判断是否已经形成一个环public CycleBufferInputStream(int capacity) {this.buffer ByteBuffer.allocateDirect(capacity);}/*** 将字节数组以覆盖的方式放入环形缓冲区*/public void put(byte[] bytes) {int used buffer.capacity() - buffer.position();if (used bytes.length) {buffer.put(bytes, 0, used);buffer.clear();buffer.put(bytes, used, bytes.length - used);isCycle true;} else if (used bytes.length) {buffer.put(bytes, 0, used);buffer.clear();isCycle true;} else {buffer.put(bytes, 0, bytes.length);}writePos buffer.position();}/*** 定位读取的初始位置执行inputstream方法前必须要先调用该方法*/public void readPrepare() {if (buffer.capacity() writePos || !isCycle) {readPos 0;} else {readPos buffer.position() 1;}}/*************************************************** 输入流传输 ***************************************************/Overridepublic int read() throws IOException {if (readPos buffer.capacity()) readPos 0;if (readPos writePos) return -1;int value buffer.get(readPos);if (value 0) value value 256;return value;}/*** 从环形缓存环获取最近一帧关键帧字节数组* 这里返回的堆外内存所以注意要及时进行内存释放* param inputStream*/public static ByteBuffer dealVideo(InputStream inputStream) {try {int j 0;FFmpegFrameGrabber ff new FFmpegFrameGrabber(inputStream);ff.start();Frame frame null;Frame last null;while ((frame ff.grabKeyFrame()) ! null frame.image ! null) {last frame.clone();System.out.println(获取一帧 j);}ff.stop();if (last ! null) {System.out.println(获取最近的一个关键帧);ByteBuffer byteBuffer (ByteBuffer)last.image[0];return byteBuffer;}} catch (Exception e) {log.error(提取最近一个关键帧异常\n,e);}return null;}public static void dealImage(InputStream inputStream) {try {Java2DFrameConverter converter new Java2DFrameConverter();FFmpegFrameGrabber ff new FFmpegFrameGrabber(inputStream);ff.start();int j 0;Frame frame null;Frame last null;while ((frame ff.grabImage()) ! null) {last frame.clone();System.out.println(获取一张图片 j);}ff.stop();if (last ! null last.image ! null) {System.out.println(存储最后一张图片 );BufferedImage fecthedImage converter.getBufferedImage(last);File screenshotFile new File(D:\\tmp-data\\, System.currentTimeMillis() .jpg);ImageIO.write(fecthedImage, jpg, screenshotFile);}} catch (Exception e) {log.error(提取最近一个图片异常\n,e);}}}
http://www.yutouwan.com/news/172718/

相关文章:

  • 三网合一网站怎么做一个新手怎么做电商运营
  • 南通网站建设招聘微信网站链接网站建设
  • 合肥建设集团信息网站徐州睢宁建设网站
  • 网站一跳率惠州模板做网站
  • .net网站项目有哪些怎么制作网站记事本
  • 网站快速优化排名排名wordpress图集功能
  • 艺术设计专业灵感推荐网站成都网站网站建设
  • 网站建设一条龙服务网站建设中的注册和登录页面
  • 南京企业网站开发wordpress主题安装路径
  • 动态表情包在线制作网站虚拟机wordpress安装教程
  • 网站流量分析工具国内十大软件培训机构
  • 福建省建设资格管理中心网站网站建设门户
  • 如何用dreamer做网站有做学历在网站能查的到的
  • 怎么做手机app软件贵阳seo网站推广优化
  • 天河网站(建设信科网络)wordpress如何配置文件
  • 网站设计需要哪些技能海沧抖音搜索seo推广运营
  • 网站备案是针对空间还是域名软件工程师培训学校
  • 建立网站不公开广州宣传片制作公司
  • 最受欢迎的建站平台哪个网站可以做代销
  • 网站制作培训价格佛山网站制作网页
  • 免费博客网站有哪些注册安全工程师有什么用
  • 大理企业网站建设2016个人网站备案
  • 软件下载网站如何履行安全福州企业网站建设推广
  • 如何把学校网站建设好海兴县网站建设价格
  • 德宏芒市建设局网站公司做网站好不好
  • 官网网站怎么创建网站如何做双语言
  • 公司网站建设需要资质鞍山网站制作小程序
  • 自学网站开发条件谷歌网页截图快捷键
  • wordpress商用seo短视频发布页
  • 建设众筹类网站网站建设图片排版