Sfoglia il codice sorgente

1.解决因源地址太长导致m3u8文件不能生成的问题
2.缩短已存在的hls流开始播放的时间
3.解决hls.html,rtmp.html部署在服务器上不能直接测试的问题

huangfei 3 anni fa
parent
commit
e65b9d0847

+ 10 - 10
README.md

@@ -5,24 +5,24 @@
 
 #### 二. 将视频流转为HLS并播放
 
-1.  调用 http://{server}:{port}/url/encode 接口将直播地址编码处理为key
-2.  调用 http://{server}:{port}/live/openHls/{key} 接口开始流转换
-3.  使用hls.js播放 http://{server}:{port}/live/{key}/play.m3u8
-4.  定时访问 http://{server}:{port}/live/ping/{key} 保持转换任务运行
+1.  调用 http://{server}:{port}/stream/url/encode 接口将直播地址编码处理为key
+2.  调用 http://{server}:{port}/stream/live/openHls/{key} 接口开始流转换
+3.  使用hls.js播放 http://{server}:{port}/stream/live/{key}/play.m3u8
+4.  定时访问 http://{server}:{port}/stream/live/ping/{key} 保持转换任务运行
 
-启动后访问:  http://{server}:{port}/static/hls.html  可查看示例
+启动后访问:  http://{server}:{port}/stream/static/hls.html  可查看示例
 
 #### 三. 将视频流转为FLV并播放
 
-1.  调用 http://{server}:{port}/url/encode 接口将直播地址编码处理为key
-2.  使用flv.js播放 http://{server}:{port}/live/{key}.flv
-3.  定时访问 http://{server}:{port}/live/ping/{key} 保持转换任务运行
+1.  调用 http://{server}:{port}/stream/url/encode 接口将直播地址编码处理为key
+2.  使用flv.js播放 http://{server}:{port}/stream/live/{key}.flv
+3.  定时访问 http://{server}:{port}/stream/live/ping/{key} 保持转换任务运行
 
 启动后访问:  
-http://{server}:{port}/static/rtmp.html  可查看rtsp转rtmp示例
+http://{server}:{port}/stream/static/rtmp.html  可查看rtsp转rtmp示例
 
 
-http://{server}:{port}/static/hls.html   可查看rtsp转hls示例
+http://{server}:{port}/stream/static/hls.html   可查看rtsp转hls示例
 
 
 

+ 5 - 0
pom.xml

@@ -84,6 +84,11 @@
             <artifactId>commons-lang3</artifactId>
             <version>${commons-lang3.version}</version>
         </dependency>
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+            <version>${commons-codec.version}</version>
+        </dependency>
         <dependency>
             <groupId>commons-io</groupId>
             <artifactId>commons-io</artifactId>

+ 5 - 2
src/main/java/com/coyee/stream/controller/StreamController.java

@@ -8,6 +8,7 @@ import com.coyee.stream.config.StreamServerConfig;
 import com.coyee.stream.result.JsonResult;
 import com.coyee.stream.service.IStreamService;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.catalina.connector.ClientAbortException;
 import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.IOUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -153,14 +154,16 @@ public class StreamController {
             inputStream = new FileInputStream(tsFile);
             IOUtils.copy(inputStream, output);
             return null;
-        } catch (Exception er) {
+        } catch(ClientAbortException er){
+            log.debug("客户端中断:"+er.getMessage());
+        }catch (Exception er) {
             log.error("获取ts出错", er);
-            return null;
         } finally {
             if (inputStream != null) {
                 IOUtils.closeQuietly(inputStream);
             }
         }
+        return null;
     }
 
     /**

+ 19 - 5
src/main/java/com/coyee/stream/converter/HlsConverter.java

@@ -3,6 +3,7 @@ package com.coyee.stream.converter;
 import com.alibaba.fastjson.util.IOUtils;
 import com.coyee.stream.config.StreamServerConfig;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.io.FilenameUtils;
 import org.bytedeco.ffmpeg.avcodec.AVPacket;
 import org.bytedeco.ffmpeg.avformat.AVFormatContext;
@@ -52,6 +53,10 @@ public class HlsConverter extends Thread implements Converter {
     private String url;
 
     private String key;
+    /**
+     * 后续请求无须等待
+     */
+    private boolean noWait=false;
 
 
     public HlsConverter(StreamServerConfig config, String url, String key) {
@@ -155,7 +160,8 @@ public class HlsConverter extends Thread implements Converter {
      */
     public File getM3u8File() {
         String hlsStoreDir = streamServerConfig.getHlsStoreDir();
-        String hlsUrl = FilenameUtils.separatorsToSystem(hlsStoreDir + File.separator + key + File.separator + "play.m3u8");
+        String shortKey=this.getShortKey();
+        String hlsUrl = FilenameUtils.separatorsToSystem(hlsStoreDir + File.separator + shortKey + File.separator + "play.m3u8");
         File hlsFile = new File(hlsUrl);
         File hlsParentFile = hlsFile.getParentFile();
         if (hlsParentFile.exists() == false) {
@@ -164,6 +170,10 @@ public class HlsConverter extends Thread implements Converter {
         return hlsFile;
     }
 
+    private String getShortKey(){
+        return DigestUtils.md5Hex(this.key);
+    }
+
     /**
      * 退出转换
      */
@@ -184,10 +194,14 @@ public class HlsConverter extends Thread implements Converter {
 
 
     public String getPlayUrl() throws InterruptedException {
-        lock.lock();
-        condition.await(10, TimeUnit.SECONDS);
-        lock.unlock();
-        return String.format("/live/%s/play.m3u8", key);
+        if(this.noWait==false) {//m3u8文件已存在就直接返回,不用等待新的ts文件解析完成
+            lock.lock();
+            condition.await(10, TimeUnit.SECONDS);
+            lock.unlock();
+        }
+        this.noWait=true;
+        String shortKey=this.getShortKey();
+        return String.format("/live/%s/play.m3u8", shortKey);
     }
 
 }

+ 11 - 7
src/main/java/com/coyee/stream/service/impl/StreamServiceImpl.java

@@ -50,16 +50,20 @@ public class StreamServiceImpl implements IStreamService {
 		//如果是hls协议,开启转换,转换成功以后返回播放地址给客户端
 		//如果是flv协议,开启转换,并保持与客户端的链接,不断的输出视频流给客户端
 		if(StringUtils.equals(format,"hls")){
+			HlsConverter hlsConverter=null;
 			if (hlsConverters.containsKey(key)==false) {
-				HlsConverter hlsConverter=new HlsConverter(streamServerConfig,url,key);
+				hlsConverter=new HlsConverter(streamServerConfig,url,key);
 				hlsConverter.start();
 				hlsConverters.put(key,hlsConverter);
-				try {
-					String playUrl = hlsConverter.getPlayUrl();
-					return playUrl;
-				}catch(InterruptedException er){
-					throw new RuntimeException("获取播放地址失败!");
-				}
+			}else{
+				hlsConverter=(HlsConverter)hlsConverters.get(key);
+				log.info("流{}的转换任务已存在,可以复用。", url);
+			}
+			try {
+				String playUrl = hlsConverter.getPlayUrl();
+				return playUrl;
+			}catch(InterruptedException er){
+				throw new RuntimeException("获取播放地址失败!");
 			}
 		}else {
 			AsyncContext async = request.startAsync();

+ 2 - 0
src/main/resources/application.yml

@@ -19,6 +19,8 @@ server:
   port: 8081
   tomcat:
     uri-encoding: UTF-8
+  servlet:
+    context-path: /stream
 streamserver:
   desKey: hxfein@2
   hlsStoreDir: /home/hls

+ 2 - 2
src/main/resources/static/hls.html

@@ -43,14 +43,14 @@
 	<p id="keepMsg"></p>
 </div>
 <script type="text/javascript">
-	var baseUrl="http://localhost:8081";
+	var baseUrl=window.location.href.split("/static/")[0];
 	function createKey(){
 		var sourceUrl=$("#sourceUrl").val()||'';
 		if(sourceUrl==''){
 			alert("源地址不能为空!");
 			return;
 		}
-		var url="/url/encode";
+		var url=baseUrl+"/url/encode";
 		$.post(url,{url:sourceUrl},function(json){
 			if(json.status==200){
 				var key=json.data;

+ 2 - 2
src/main/resources/static/rtmp.html

@@ -39,7 +39,7 @@
     <p id="keepMsg"></p>
 </div>
 <script type="text/javascript">
-    var baseUrl = "http://localhost:8081";
+    var baseUrl = window.location.href.split("/static/")[0];
 
     function createKey() {
         var sourceUrl = $("#sourceUrl").val() || '';
@@ -47,7 +47,7 @@
             alert("源地址不能为空!");
             return;
         }
-        var url = "/url/encode";
+        var url = baseUrl+"/url/encode";
         $.post(url, {url: sourceUrl}, function (json) {
             if (json.status == 200) {
                 var key = json.data;