直播架构
业务服务器:负责协调直播类应用的业务逻辑
创建直播房间 返回直播房间播放地址列表 关闭直播房间 LiveNet 实时流网络:负责流媒体的分发、直播流的创建、查询等相关操作 采集端:负责采集和推送流媒体 播放端:负责拉取并播放流媒体
直播云API:https://developer.qiniu.com/pili
服务端
SDK:https://developer.qiniu.com/pili/sdk/1220/server-sdk
关键代码:
// 配置企业开发者密钥,密钥使用七牛账号登录https://portal.qiniu.com/user/key 获取 String accessKey = "xxx"; String secretKey = "xxx"; // 直播空间名称 // 直播空间必须事先存在,可以在 portal.qiniu.com 上创建 String hubName = "xxx"; Config.APIHost = "pili.qiniuapi.com"; //初始化client Client cli = new Client(accessKey,secretKey); //初始化Hub Hub hub = cli.newHub(hubName);
//列出所有流 try{ Hub.ListRet listRet = hub.list("liu", 0, ""); System.out.printf("hub=%s 列出流: keys=%s marker=%s\n", hubName,printArrary(listRet.keys) , listRet.omarker); }catch (PiliException e){ e.printStackTrace(); return; } //列出正在直播的流 try{ Hub.ListRet listRet = hub.listLive("liu", 0, ""); System.out.printf("hub=%s 列出正在直播的流: keys=%s marker=%s\n", hubName, printArrary(listRet.keys), listRet.omarker); }catch (PiliException e){ e.printStackTrace(); return; } // RTMP推流地址 String url = cli.RTMPPublishURL("pili-publish.www.gs369.cn", hubName, keyA, 3600); System.out.printf("keyA=%s RTMP推流地址=%s\n", keyA, url); //RTMP直播地址 String RTMPUrl = cli.RTMPPlayURL("pili-live-rtmp.www.gs369.cn", hubName, keyA); System.out.printf("keyA=%s RTMP直播地址=%s\n", keyA, RTMPUrl); request.setAttribute("RTMPUrl",urlTimestamp(RTMPUrl)); //HLS直播地址 String HLSUrl = cli.HLSPlayURL("pili-live-hls.www.gs369.cn", hubName, keyA); System.out.printf("keyA=%s HLS直播地址=%s\n", keyA, HLSUrl); request.setAttribute("HLSUrl",urlTimestamp(HLSUrl)); //HDL直播地址 String FLVUrl = cli.HDLPlayURL("pili-live-hdl.www.gs369.cn", hubName, keyA); System.out.printf("keyA=%s HDL直播地址=%s\n", keyA, FLVUrl); request.setAttribute("FLVUrl",urlTimestamp(FLVUrl)); // 截图直播地址 url = cli.SnapshotPlayURL("pili-live-snapshot.www.gs369.cn", hubName, keyA); System.out.printf("keyA=%s 截图直播地址=%s\n", keyA, url);
将URL添加时间戳代码:
1 private static String urlTimestamp(String url,String key){ 2 String t = Long.toHexString(new Long(new Date().getTime() + 60)); 3 //String key = "yuanda"; 4 int index = url.indexOf("/",url.indexOf("//")+3); 5 String s = key+url.substring(index)+t; 6 System.out.println("s:"+s); 7 String sign=""; 8 try { 9 MessageDigest md5 = MessageDigest.getInstance("md5");10 md5.update(s.getBytes());11 byte[] tmp = md5.digest();12 StringBuilder sb = new StringBuilder();13 for (byte b : tmp) {14 if (b > 0 && b < 16)15 sb.append("0");16 sb.append(Integer.toHexString(b & 0xff));17 }18 sign=sb.toString().toLowerCase();19 } catch (NoSuchAlgorithmException e) {20 e.printStackTrace();21 }22 //System.out.println("sign:"+sign);23 String resultUrl = url + "?sign=" + sign + "&t=" + t ;24 return resultUrl;25 }
播放端
web播放端,m3u8格式,此处JSP
1 <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> 2 <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 3 4 5Qiniu Web Player in HTML5 6 7 8 9 10 HLSUrl: ${HLSUrl } 11 RTMPUrl: ${RTMPUrl } 12 FLVUrl: ${FLVUrl } 13
14 HLS格式播放:15 16 17 18播放器状态: 0: 视频尚未开始加载,当前没有可用媒体信息;19 1: 视频元数据已经可用;20 2: 视频可以播放;21 3: 视频可以播放,并且可以被快进;22 4: 视频可以无终止的播放。
23 24 25 40 41
-------------------或者videojs播放器:
源码:https://github.com/saysmy/videojs-hls