StreamServiceImpl.java 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. package com.coyee.stream.service.impl;
  2. import java.io.IOException;
  3. import java.nio.charset.Charset;
  4. import java.util.*;
  5. import javax.annotation.Resource;
  6. import javax.servlet.AsyncContext;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. import com.coyee.stream.config.StreamServerConfig;
  10. import com.coyee.stream.converter.HlsConverter;
  11. import com.coyee.stream.converter.Converter;
  12. import com.coyee.stream.converter.FlvConverter;
  13. import com.coyee.stream.service.IStreamService;
  14. import com.coyee.stream.util.Des;
  15. import org.apache.commons.lang3.StringUtils;
  16. import org.springframework.scheduling.annotation.Scheduled;
  17. import org.springframework.stereotype.Service;
  18. import lombok.extern.slf4j.Slf4j;
  19. /**
  20. * @author hxfein
  21. * @className: StreamServiceImpl
  22. * @description: 流服务相关接口实现
  23. * @date 2022/5/12 14:32
  24. * @version:1.0
  25. */
  26. @Slf4j
  27. @Service
  28. public class StreamServiceImpl implements IStreamService {
  29. private Map<String, Converter> flvConverters = new HashMap<>();
  30. private Map<String, Converter> hlsConverters = new HashMap<>();
  31. private Map<String,Date> activeStreamMap=new HashMap<>();
  32. @Resource
  33. private StreamServerConfig streamServerConfig;
  34. /**
  35. * 编码
  36. */
  37. private static Charset charset = Charset.forName("utf-8");
  38. @Override
  39. public String open(String url,String format, HttpServletResponse response, HttpServletRequest request) {
  40. String key=encode(url);
  41. this.activeStream(key);
  42. //如果是hls协议,开启转换,转换成功以后返回播放地址给客户端
  43. //如果是flv协议,开启转换,并保持与客户端的链接,不断的输出视频流给客户端
  44. if(StringUtils.equals(format,"hls")){
  45. if (hlsConverters.containsKey(key)==false) {
  46. HlsConverter hlsConverter=new HlsConverter(streamServerConfig,url,key);
  47. hlsConverter.start();
  48. hlsConverters.put(key,hlsConverter);
  49. try {
  50. String playUrl = hlsConverter.getPlayUrl();
  51. return playUrl;
  52. }catch(InterruptedException er){
  53. throw new RuntimeException("获取播放地址失败!");
  54. }
  55. }
  56. }else {
  57. AsyncContext async = request.startAsync();
  58. async.setTimeout(0);
  59. if (flvConverters.containsKey(key)) {
  60. Converter c = flvConverters.get(key);
  61. try {
  62. c.addOutputStreamEntity(key, async);
  63. } catch (IOException e) {
  64. log.error(e.getMessage(), e);
  65. throw new IllegalArgumentException(e.getMessage());
  66. }
  67. } else {
  68. List<AsyncContext> outs = new ArrayList<>();
  69. outs.add(async);
  70. FlvConverter c = new FlvConverter(url, outs);
  71. c.start();
  72. flvConverters.put(key, c);
  73. }
  74. response.setContentType("video/x-flv");
  75. response.setHeader("Connection", "keep-alive");
  76. response.setStatus(HttpServletResponse.SC_OK);
  77. try {
  78. response.flushBuffer();
  79. } catch (IOException e) {
  80. log.error(e.getMessage(), e);
  81. }
  82. }
  83. return null;
  84. }
  85. @Override
  86. public boolean activeStream(String key) {
  87. if(hlsConverters.containsKey(key)||flvConverters.containsKey(key)) {
  88. activeStreamMap.put(key, new Date());
  89. return true;
  90. }else{
  91. activeStreamMap.remove(key);
  92. return false;
  93. }
  94. }
  95. @Override
  96. public String encode(String url) {
  97. String desKey=streamServerConfig.getDesKey();
  98. return Des.encryptString(url, charset, desKey);
  99. }
  100. @Override
  101. public String decode(String url) {
  102. String desKey=streamServerConfig.getDesKey();
  103. return Des.decryptString(url, charset, desKey);
  104. }
  105. @Scheduled(fixedDelay = 1*60*1000)
  106. @Override
  107. public void manageConverters() {
  108. log.info("管理任务开始运行:{}",new Date());
  109. activeStreamMap.forEach((key,lastAccessTime)->{
  110. if(lastAccessTime==null){
  111. return ;
  112. }
  113. long accessTime=lastAccessTime.getTime();
  114. long currentTime=System.currentTimeMillis();
  115. long diff=currentTime-accessTime;
  116. if(diff/(60*1000)>5){//上次访问时间大于5分钟
  117. Converter flvConverter=flvConverters.get(key);
  118. if(flvConverter!=null){
  119. flvConverter.softClose();
  120. flvConverters.remove(key);
  121. log.info("管理任务移去FLV转流任务:{}",key);
  122. }
  123. Converter hlsConverter=hlsConverters.get(key);
  124. if(hlsConverter!=null){
  125. hlsConverter.softClose();
  126. hlsConverters.remove(key);
  127. log.info("管理任务移去HLS转流任务:{}",key);
  128. }
  129. activeStreamMap.remove(key);
  130. }
  131. });
  132. }
  133. }