Compare commits
No commits in common. "be740def8df459f37724c4f74ffed73badf83714" and "1e13507381fa154c3404b6cc7b421cc0d6e42be8" have entirely different histories.
be740def8d
...
1e13507381
33
.gitignore
vendored
Normal file
33
.gitignore
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
README.md
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
91
README.cn.md
91
README.cn.md
@ -1,91 +0,0 @@
|
||||
<!-- Easy-FLV: Java RTSP/RTMP to FLV Converter -->
|
||||
# 📺 Easy-FLV: Java 实现的 RTSP/RTMP 到 FLV 转换器
|
||||
|
||||
[](https://github.com/javpower/easy-flv)
|
||||
[](https://github.com/javpower/easy-flv/issues)
|
||||
[](https://opensource.org/licenses/Apache-2.0)
|
||||
[](https://adoptopenjdk.net/)
|
||||
[](https://spring.io/projects/spring-boot)
|
||||
|
||||
## 🌟 关于 Easy-FLV
|
||||
Easy-FLV 是一个用 Java 实现的库,它能够将 RTSP 或 RTMP 视频流转换为 FLV 格式,以便在浏览器中播放。它为实时视频监控、直播和视频流处理提供了一个高效、稳定且易于集成的解决方案。
|
||||
|
||||
### 为什么选择 Easy-FLV?
|
||||
- **高效转换**:快速将视频流转换为 FLV 格式,无需复杂配置。
|
||||
- **易于集成**:作为 Spring Boot Starter 使用,轻松集成到任何 Java 项目。
|
||||
- **现代浏览器支持**:支持所有主流浏览器,无需额外插件。
|
||||
- **实时流处理**:适用于实时视频流的转换,如安防监控和直播。
|
||||
|
||||
## 📄 效果图
|
||||
以下是 Easy-FLV 在行动的效果图:
|
||||
|
||||

|
||||

|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 添加 Maven 依赖
|
||||
在你的 Spring Boot 项目中,添加以下 Maven 依赖:
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>io.github.javpower</groupId>
|
||||
<artifactId>rtsp-converter-flv-spring-boot-starter</artifactId>
|
||||
<version>1.5.9.1</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
### 实现接口
|
||||
创建一个服务类来实现 `IOpenFLVService` 接口,并提供流地址:
|
||||
|
||||
```java
|
||||
@Service
|
||||
public class RtspDataService implements IOpenFLVService {
|
||||
|
||||
@Override
|
||||
public String getUrl(Integer channel) {
|
||||
// 根据 channel 获取 RTSP 视频流地址
|
||||
return "rtsp://10.11.9.251:554/openUrl/16HV8mA";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 配置 YAML
|
||||
在 `application.yml` 中配置 Easy-FLV:
|
||||
|
||||
```yaml
|
||||
easy:
|
||||
flv:
|
||||
host: http://localhost:8200
|
||||
```
|
||||
|
||||
### 使用接口
|
||||
通过以下接口获取转换后的流地址,并在浏览器中播放:
|
||||
|
||||
- 转换地址:`GET http://ip:port/get/flv/hls/stream_{channel}.flv`
|
||||
- 播放地址:`GET http://ip:port/flv/hls/stream_{channel}.flv`
|
||||
|
||||
### 直接使用
|
||||
如果不使用接口,可以直接编码流地址并转换:
|
||||
|
||||
```java
|
||||
public static void main(String[] args) throws UnsupportedEncodingException {
|
||||
String url = "rtsp://XXXXXXXX";
|
||||
String encodedUrl = java.net.URLEncoder.encode(url, "UTF-8");
|
||||
System.out.println("Encoded Stream URL: " + encodedUrl);
|
||||
}
|
||||
```
|
||||
|
||||
- 转换地址:`GET http://ip:port/get/flv/hls/stream?url=编码后的地址`
|
||||
- 播放地址:`GET http://ip:port/flv/hls/stream?url=编码后的地址`
|
||||
|
||||
## 🛠️ 贡献
|
||||
我们欢迎任何形式的贡献,包括但不限于报告 bug、提交修复、添加新功能、改进文档等。
|
||||
|
||||
## 📄 许可证
|
||||
Easy-FLV 根据 [Apache License 2.0](LICENSE) 发布。
|
||||
|
||||
## 📧 联系
|
||||
- Email: [javpower@163.com](mailto:your-email@example.com)
|
||||
- GitHub: [https://github.com/javpower/easy-flv](https://github.com/javpower/easy-flv)
|
||||
- Gitee: [https://gitee.com/giteeClass/easy-flv](https://gitee.com/giteeClass/easy-flv)
|
59
README.md
Normal file
59
README.md
Normal file
@ -0,0 +1,59 @@
|
||||
|
||||
# Easy-FLV
|
||||
|
||||
#### 项目介绍
|
||||
rtsp、rtmp流地址转换成flv浏览器播放
|
||||
|
||||
极速开始
|
||||
-------------------------------------
|
||||
以下例子基于Spring Boot
|
||||
|
||||
### 第一步:添加Maven依赖
|
||||
|
||||
直接添加以下maven依赖即可
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>io.github.javpower</groupId>
|
||||
<artifactId>rtsp-converter-flv-spring-boot-starter</artifactId>
|
||||
<version>1.5.9</version>
|
||||
</dependency>
|
||||
```
|
||||
### 第二步:实现interface
|
||||
数据库里面存储要播放的rtsp、rtmp流地址和自定义的通道号 实现类中通过通道号查询出地址<br>
|
||||
```java
|
||||
@Service
|
||||
public class RtspDataService implements IOpenFLVService {
|
||||
|
||||
|
||||
@Override
|
||||
public String getUrl(Integer channel) {
|
||||
//todo: 根据自定义的channel获取rtsp视频流地址
|
||||
return "rtsp://10.11.9.251:554/openUrl/16HV8mA";
|
||||
}
|
||||
}
|
||||
```
|
||||
### 第三步:配置yml
|
||||
```yml
|
||||
easy.flv.host=http://localhost:8200
|
||||
```
|
||||
### 第四步:实现interface使用
|
||||
|
||||
- 流转换地址:GET http://ip:port/get/flv/hls/stream_{channel}.flv
|
||||
- 浏览器直接播放测试: GET http://ip:port/flv/hls/stream_{channel}.flv
|
||||
|
||||
### 第五步:不想实现interface使用
|
||||
原地址:rtsp://XXXXXXXX <br>
|
||||
```Java
|
||||
public static void main(String[] args) throws UnsupportedEncodingException {
|
||||
|
||||
String url = "rtsp://XXXXXXXX";
|
||||
String encodedUrl = java.net.URLEncoder.encode(url, "UTF-8");
|
||||
System.out.println("编码:" + encodedUrl);
|
||||
}
|
||||
```
|
||||
- 流转换地址:GET http://ip:port/get/flv/hls/stream?url=编码后的地址
|
||||
- 浏览器直接播放测试: GET http://ip:port/flv/hls/stream?url=编码后的地址
|
||||
|
||||

|
||||

|
17
pom.xml
17
pom.xml
@ -2,12 +2,12 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>me.zhengjie</groupId>
|
||||
<artifactId>eladmin-flv</artifactId>
|
||||
<version>1.1</version>
|
||||
<name>视频模块</name>
|
||||
<description>视频流转换 rtsp/rtmp 转flv</description>
|
||||
|
||||
<groupId>io.github.javpower</groupId>
|
||||
<artifactId>rtsp-converter-flv-spring-boot-starter</artifactId>
|
||||
<version>1.5.9</version>
|
||||
<name>rtsp-converter-flv-spring-boot-starter</name>
|
||||
<description>a tool about easy rtsp-converter-flv</description>
|
||||
<url>https://github.com/javpower/easy-flv</url>
|
||||
<licenses>
|
||||
<license>
|
||||
<name> The Apache Software License, Version 2.0 </name>
|
||||
@ -38,11 +38,6 @@
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>me.zhengjie</groupId>
|
||||
<artifactId>eladmin-logging</artifactId>
|
||||
<version>1.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
|
@ -2,16 +2,10 @@ package com.gc.easy.flv.controller;
|
||||
|
||||
import com.gc.easy.flv.service.IFLVService;
|
||||
import com.gc.easy.flv.service.IOpenFLVService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.zhengjie.annotation.Log;
|
||||
import me.zhengjie.annotation.rest.AnonymousGetMapping;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -23,25 +17,28 @@ import java.io.UnsupportedEncodingException;
|
||||
*
|
||||
* @author gc.x
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController("api/front/flv")
|
||||
@Api(tags = "微信:拉流播放")
|
||||
@RestController
|
||||
public class FLVController {
|
||||
|
||||
@Autowired
|
||||
private IFLVService service;
|
||||
|
||||
@Autowired(required = false)
|
||||
private IOpenFLVService openFLVService;
|
||||
|
||||
@Log("拉流播放")
|
||||
@ApiOperation(value = "打开视频流")
|
||||
// @GetMapping(value = "/get/stream")
|
||||
@AnonymousGetMapping(value = "/get/stream")
|
||||
public void open(String url, HttpServletResponse response, HttpServletRequest request) throws UnsupportedEncodingException {
|
||||
@GetMapping(value = "/get/flv/hls/stream_{channel}.flv")
|
||||
public void open(@PathVariable(value = "channel") Integer channel, HttpServletResponse response,
|
||||
HttpServletRequest request) {
|
||||
String url = openFLVService.getUrl(channel);
|
||||
if(!StringUtils.isEmpty(url)){
|
||||
service.open(channel,url, response, request);
|
||||
}
|
||||
}
|
||||
@GetMapping(value = "/get/flv/hls/stream")
|
||||
public void open1(String url, HttpServletResponse response,
|
||||
HttpServletRequest request) throws UnsupportedEncodingException {
|
||||
if(!StringUtils.isEmpty(url)){
|
||||
String decodedUrl = java.net.URLDecoder.decode(url, "UTF-8");
|
||||
service.open(decodedUrl, response, request, openFLVService);
|
||||
service.open(decodedUrl, response, request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,30 +1,39 @@
|
||||
//package com.gc.easy.flv.controller;
|
||||
//
|
||||
//import com.gc.easy.flv.config.FlvConfig;
|
||||
//import me.zhengjie.annotation.rest.AnonymousGetMapping;
|
||||
//import org.springframework.beans.factory.annotation.Autowired;
|
||||
//import org.springframework.stereotype.Controller;
|
||||
//import org.springframework.ui.Model;
|
||||
//
|
||||
//import java.io.UnsupportedEncodingException;
|
||||
//
|
||||
///**
|
||||
// * FLV流转换
|
||||
// *
|
||||
// * @author gc.x
|
||||
// */
|
||||
//@Controller
|
||||
//public class FLVPlayController {
|
||||
// @Autowired
|
||||
// private FlvConfig flvConfig;
|
||||
//
|
||||
// @AnonymousGetMapping(value = "/flv/hls/stream")
|
||||
// public String getAppHtml1(String url, Model model) throws UnsupportedEncodingException {
|
||||
// String decodedUrl = java.net.URLDecoder.decode(url, "UTF-8");
|
||||
// String videoPath="/api/front/flv/get/stream?url="+decodedUrl;
|
||||
// model.addAttribute("videoPath", videoPath);
|
||||
// model.addAttribute("wight", flvConfig.getWight());
|
||||
// model.addAttribute("height", flvConfig.getHeight());
|
||||
// return "video";
|
||||
// }
|
||||
//}
|
||||
package com.gc.easy.flv.controller;
|
||||
|
||||
import com.gc.easy.flv.config.FlvConfig;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
/**
|
||||
* FLV流转换
|
||||
*
|
||||
* @author gc.x
|
||||
*/
|
||||
@Controller
|
||||
public class FLVPlayController {
|
||||
@Autowired
|
||||
private FlvConfig flvConfig;
|
||||
|
||||
@GetMapping(value = "/flv/hls/stream_{channel}.flv")
|
||||
public String getAppHtml(@PathVariable(value = "channel") Integer channel, Model model) {
|
||||
String videoPath=flvConfig.getHost()+"/get/flv/hls/stream_"+channel+".flv";
|
||||
model.addAttribute("videoPath", videoPath);
|
||||
model.addAttribute("wight", flvConfig.getWight());
|
||||
model.addAttribute("height", flvConfig.getHeight());
|
||||
return "video";
|
||||
}
|
||||
@GetMapping(value = "/flv/hls/stream")
|
||||
public String getAppHtml1(String url, Model model) throws UnsupportedEncodingException {
|
||||
String decodedUrl = java.net.URLDecoder.decode(url, "UTF-8");
|
||||
String videoPath=flvConfig.getHost()+"/get/flv/hls/stream?url="+decodedUrl;
|
||||
model.addAttribute("videoPath", videoPath);
|
||||
model.addAttribute("wight", flvConfig.getWight());
|
||||
model.addAttribute("height", flvConfig.getHeight());
|
||||
return "video";
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.gc.easy.flv.factories;
|
||||
|
||||
import com.alibaba.fastjson.util.IOUtils;
|
||||
import com.gc.easy.flv.service.IOpenFLVService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.bytedeco.ffmpeg.avcodec.AVPacket;
|
||||
import org.bytedeco.ffmpeg.global.avcodec;
|
||||
@ -61,15 +60,12 @@ public class ConverterFactories extends Thread implements Converter {
|
||||
*/
|
||||
private Map<String, Converter> factories;
|
||||
|
||||
private IOpenFLVService openFLVService;
|
||||
|
||||
|
||||
public ConverterFactories(String url, String key, Map<String, Converter> factories, List<AsyncContext> outEntitys, IOpenFLVService openFLVService) {
|
||||
public ConverterFactories(String url, String key, Map<String, Converter> factories, List<AsyncContext> outEntitys) {
|
||||
this.url = url;
|
||||
this.key = key;
|
||||
this.factories = factories;
|
||||
this.outEntitys = outEntitys;
|
||||
this.openFLVService = openFLVService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -79,11 +75,11 @@ public class ConverterFactories extends Thread implements Converter {
|
||||
grabber = new FFmpegFrameGrabber(url);
|
||||
if ("rtsp".equals(url.substring(0, 4))) {
|
||||
grabber.setOption("rtsp_transport", "tcp");
|
||||
grabber.setOption("timeout", "5000000");
|
||||
grabber.setOption("stimeout", "5000000");
|
||||
}
|
||||
grabber.start();
|
||||
if (avcodec.AV_CODEC_ID_H264 == grabber.getVideoCodec()
|
||||
&& (grabber.getAudioChannels() == 0 || avcodec.AV_CODEC_ID_AAC == grabber.getAudioCodec()) && (openFLVService == null || !openFLVService.openPreview())) {
|
||||
&& (grabber.getAudioChannels() == 0 || avcodec.AV_CODEC_ID_AAC == grabber.getAudioCodec())) {
|
||||
log.info("this url:{} converterFactories start", url);
|
||||
// 来源视频H264格式,音频AAC格式
|
||||
// 无须转码,更低的资源消耗,更低的延迟
|
||||
@ -139,7 +135,7 @@ public class ConverterFactories extends Thread implements Converter {
|
||||
} else {
|
||||
isCloseGrabberAndResponse = false;
|
||||
// 需要转码为视频H264格式,音频AAC格式
|
||||
ConverterTranFactories c = new ConverterTranFactories(url, key, factories, outEntitys, grabber, openFLVService);
|
||||
ConverterTranFactories c = new ConverterTranFactories(url, key, factories, outEntitys, grabber);
|
||||
factories.put(key, c);
|
||||
c.start();
|
||||
}
|
||||
|
@ -1,14 +1,11 @@
|
||||
package com.gc.easy.flv.factories;
|
||||
|
||||
import com.alibaba.fastjson.util.IOUtils;
|
||||
import com.gc.easy.flv.service.IOpenFLVService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.bytedeco.ffmpeg.global.avcodec;
|
||||
import org.bytedeco.javacv.FFmpegFrameGrabber;
|
||||
import org.bytedeco.javacv.FFmpegFrameRecorder;
|
||||
import org.bytedeco.javacv.Frame;
|
||||
import org.bytedeco.javacv.OpenCVFrameConverter;
|
||||
import org.bytedeco.opencv.opencv_core.IplImage;
|
||||
|
||||
import javax.servlet.AsyncContext;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@ -62,18 +59,13 @@ public class ConverterTranFactories extends Thread implements Converter {
|
||||
*/
|
||||
private Map<String, Converter> factories;
|
||||
|
||||
private OpenCVFrameConverter.ToIplImage converter;
|
||||
private IOpenFLVService openFLVService;
|
||||
|
||||
|
||||
public ConverterTranFactories(String url, String key, Map<String, Converter> factories,
|
||||
List<AsyncContext> outEntitys, FFmpegFrameGrabber grabber, IOpenFLVService openFLVService) {
|
||||
List<AsyncContext> outEntitys, FFmpegFrameGrabber grabber) {
|
||||
this.url = url;
|
||||
this.key = key;
|
||||
this.factories = factories;
|
||||
this.outEntitys = outEntitys;
|
||||
this.grabber = grabber;
|
||||
this.openFLVService=openFLVService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -90,8 +82,6 @@ public class ConverterTranFactories extends Thread implements Converter {
|
||||
stream = new ByteArrayOutputStream();
|
||||
recorder = new FFmpegFrameRecorder(stream, grabber.getImageWidth(), grabber.getImageHeight(),
|
||||
grabber.getAudioChannels());
|
||||
converter = new OpenCVFrameConverter.ToIplImage();
|
||||
|
||||
recorder.setInterleaved(true);
|
||||
recorder.setVideoOption("preset", "ultrafast");
|
||||
recorder.setVideoOption("tune", "zerolatency");
|
||||
@ -117,14 +107,6 @@ public class ConverterTranFactories extends Thread implements Converter {
|
||||
while (runing) {
|
||||
// 抓取一帧
|
||||
Frame f = grabber.grab();
|
||||
if(openFLVService!=null&&openFLVService.openPreview()){
|
||||
//预处理
|
||||
IplImage iplImage = converter.convert(f);//抓取一帧视频并将其转换为图像,至于用这个图像用来做什么?加水印,人脸识别等等自行添加
|
||||
if (iplImage != null) {
|
||||
openFLVService.preview(iplImage);
|
||||
f = converter.convert(iplImage);
|
||||
}
|
||||
}
|
||||
if (f != null) {
|
||||
try {
|
||||
// 转码
|
||||
|
@ -11,7 +11,7 @@ public interface IFLVService {
|
||||
* @param url
|
||||
* @param response
|
||||
*/
|
||||
public void open(Integer channel,String url, HttpServletResponse response, HttpServletRequest request,IOpenFLVService openFLVService);
|
||||
public void open(String url, HttpServletResponse response, HttpServletRequest request,IOpenFLVService openFLVService);
|
||||
public void open(Integer channel,String url, HttpServletResponse response, HttpServletRequest request);
|
||||
public void open(String url, HttpServletResponse response, HttpServletRequest request);
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
package com.gc.easy.flv.service;
|
||||
|
||||
import org.bytedeco.opencv.opencv_core.IplImage;
|
||||
|
||||
public interface IOpenFLVService {
|
||||
|
||||
|
||||
@ -10,17 +8,5 @@ public interface IOpenFLVService {
|
||||
* @param channel
|
||||
* @return
|
||||
*/
|
||||
String getUrl(Integer channel);
|
||||
|
||||
/**
|
||||
* 抓取一帧视频并将其转换为图像预处理
|
||||
* @param iplImage
|
||||
*/
|
||||
void preview(IplImage iplImage);
|
||||
|
||||
/**
|
||||
* 开启预处理
|
||||
* @return
|
||||
*/
|
||||
boolean openPreview();
|
||||
public String getUrl(Integer channel);
|
||||
}
|
@ -4,7 +4,6 @@ package com.gc.easy.flv.service.impl;
|
||||
import com.gc.easy.flv.factories.Converter;
|
||||
import com.gc.easy.flv.factories.ConverterFactories;
|
||||
import com.gc.easy.flv.service.IFLVService;
|
||||
import com.gc.easy.flv.service.IOpenFLVService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@ -28,14 +27,12 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
public class FLVService implements IFLVService {
|
||||
|
||||
private ConcurrentHashMap<String, Converter> converters = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void open(String url, HttpServletResponse response, HttpServletRequest request, IOpenFLVService openFLVService) {
|
||||
open(null, url, response, request, openFLVService);
|
||||
public void open(String url, HttpServletResponse response, HttpServletRequest request) {
|
||||
open(null,url,response,request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open(Integer channel, String url, HttpServletResponse response, HttpServletRequest request, IOpenFLVService openFLVService) {
|
||||
public void open(Integer channel,String url, HttpServletResponse response, HttpServletRequest request) {
|
||||
String key = md5(url);
|
||||
AsyncContext async = request.startAsync();
|
||||
async.setTimeout(0);
|
||||
@ -50,7 +47,7 @@ public class FLVService implements IFLVService {
|
||||
} else {
|
||||
List<AsyncContext> outs = new ArrayList<>();
|
||||
outs.add(async);
|
||||
ConverterFactories c = new ConverterFactories(url, key, converters, outs, openFLVService);
|
||||
ConverterFactories c = new ConverterFactories(url, key, converters, outs);
|
||||
c.start();
|
||||
converters.put(key, c);
|
||||
}
|
||||
|
@ -1,33 +0,0 @@
|
||||
package com.gc.easy.flv.service.impl;
|
||||
|
||||
|
||||
import com.gc.easy.flv.service.IOpenFLVService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.bytedeco.opencv.opencv_core.IplImage;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* FLV流转换
|
||||
*
|
||||
* @author gc.x
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class OpenFLVService implements IOpenFLVService {
|
||||
|
||||
|
||||
@Override
|
||||
public String getUrl(Integer channel) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preview(IplImage iplImage) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean openPreview() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
package com.gc.easy.flv.util;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.bytedeco.javacv.FFmpegFrameGrabber;
|
||||
import org.bytedeco.javacv.Frame;
|
||||
import org.bytedeco.javacv.FrameGrabber;
|
||||
import org.bytedeco.javacv.Java2DFrameConverter;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class FlvUtil {
|
||||
|
||||
private static BufferedImage getBufferedImageByFrame(String filePath) throws IOException {
|
||||
FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(filePath);
|
||||
return getBufferedImageByFrame(grabber);
|
||||
}
|
||||
|
||||
private static BufferedImage getBufferedImageByFrame(FFmpegFrameGrabber grabber)
|
||||
throws FrameGrabber.Exception {
|
||||
grabber.start();
|
||||
Frame frame;
|
||||
frame = grabber.grabImage();
|
||||
Java2DFrameConverter converter = new Java2DFrameConverter();
|
||||
BufferedImage buffer = converter.getBufferedImage(frame);
|
||||
grabber.stop();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static byte[] getFlvImg(String path) throws Exception {
|
||||
return bufferedImageToByteArray(getBufferedImageByFrame(path));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将BufferedImage转换为byte[]
|
||||
*
|
||||
* @param image
|
||||
* @return
|
||||
*/
|
||||
public static byte[] bufferedImageToByteArray(BufferedImage image) throws IOException {
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
ImageIO.write(image, "jpg", os);
|
||||
return os.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*
|
||||
* @param data 文件数据
|
||||
* @param url 上传地址
|
||||
* @param fileName 文件名称
|
||||
* @return
|
||||
*/
|
||||
public static JSONObject postFile(byte[] data, String url, String fileName) {
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
|
||||
ByteArrayResource contentsAsResource = new ByteArrayResource(data) {
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return fileName;
|
||||
}
|
||||
};
|
||||
paramMap.add("file", contentsAsResource);
|
||||
return restTemplate.postForObject(url, paramMap, JSONObject.class);
|
||||
}
|
||||
}
|
@ -5,12 +5,12 @@
|
||||
<title>FLV Video Player</title>
|
||||
|
||||
<!-- 引入flv.js库 -->
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/flv.js/1.5.0/flv.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/flv.js@1.5.0/dist/flv.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<video id="videoPlayer" th:style="'width:500px; height:500px;'" controls></video>
|
||||
<video id="videoPlayer" th:style="'width:' + ${width} + 'px; height:' + ${height} + 'px;'" controls></video>
|
||||
|
||||
<script th:inline="javascript">
|
||||
(function() {
|
||||
@ -20,7 +20,7 @@
|
||||
var videoElement = document.getElementById('videoPlayer');
|
||||
var flvPlayer = flvjs.createPlayer({
|
||||
type: 'flv',
|
||||
url: 'http://localhost:8000' + videoPath
|
||||
url: videoPath
|
||||
});
|
||||
|
||||
flvPlayer.attachMediaElement(videoElement);
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,37 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>FLV Video Player</title>
|
||||
|
||||
<!-- 引入flv.js库 -->
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/flv.js/1.5.0/flv.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<video id="videoPlayer" th:style="'width:500px; height:500px;'" controls></video>
|
||||
|
||||
<script th:inline="javascript">
|
||||
(function () {
|
||||
var videoPath = /*[[${videoPath}]]*/ '';
|
||||
|
||||
if (flvjs.isSupported()) {
|
||||
var videoElement = document.getElementById('videoPlayer');
|
||||
var flvPlayer = flvjs.createPlayer({
|
||||
type: 'flv',
|
||||
url: 'http://localhost:8000' + videoPath
|
||||
});
|
||||
|
||||
flvPlayer.attachMediaElement(videoElement);
|
||||
flvPlayer.load();
|
||||
|
||||
// 播放视频
|
||||
videoElement.play();
|
||||
} else {
|
||||
console.error('FLV not supported');
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user