java七牛视频直播的那些事

  最近公司的视频直播出了点问题,才有幸研究了一下七牛家的直播。根据七牛家的文档以及网上大咖的博客,总结了一下,仅供参考,不对地方请指教。

  首先到七牛的官网上(https://sso.qiniu.com/?client_id=BG0o9WIbVw0QTMMF4nnnimetSKUlf5xy67pcymZMKW1otjBQePCr6DrGhYifj1gH&redirect_url=https://www.qiniu.com&ref=www.qiniu.com)注册账号,获取

qiniu_access_key,qiniu_secret_key,qiniu_callback,HUB_NAME等信息,这些信息都是公司领导申请的,需要付费的,具体细节不在赘述,如有需要可以向七牛的客服联系。

   然后到官网的开发者中心(https://developer.qiniu.com/sdk#official-sdk)下载,我下载的java版的后台服务器。

  

  需要的jar包截图如下

  

  这些前期准备阶段就差不多了,就开始写后台直播的业务逻辑了,在我的项目中用到的直播逻辑如下:

 

其中代码部分:


import java.util.Date;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import com.alibaba.fastjson.JSON;
import com.aspire.boc.util.ResourceManager;
import com.google.gson.Gson;
import com.pili.Hub;
import com.pili.PiliException;
import com.pili.Stream;
import com.pili.Stream.SaveAsResponse;
import com.pili.Stream.SegmentList;
import com.pili.Stream.SnapshotResponse;
import com.pili.Stream.Status;
import com.qiniu.Credentials;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.processing.OperationManager;
import com.qiniu.processing.OperationStatus;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import com.qiniu.util.UrlSafeBase64;

/**
 * 
 * 
 * @类编号:
 * @类名称:QiniuLiveTools
 * @内容摘要: 七牛直播工具类
 * 
 */
public class QiniuLiveTools {
private Logger logger = Logger.getLogger(QiniuLiveTools.class);
private static QiniuLiveTools instance;
public static final String HUB_NAME = "";
private static final String PRE_STREAM_PRESET_PUBLISH_SECURITY = "static";
private static ResourceManager rm = ResourceManager.getInstance();
private Credentials mCredentials = new Credentials(
rm.getValue("qiniu_access_key"), rm.getValue("qiniu_secret_key"));
private Hub mHub = new Hub(mCredentials, HUB_NAME);


static {
com.pili.Configuration.getInstance()
.setAPIHost("pili-lte.qiniuapi.com");


}
public static QiniuLiveTools getInstance() {
if (instance == null) {
instance = new QiniuLiveTools();
}
return instance;
}
// 准备直播流
public Stream prepareStream() {
Stream mStream = null;
try {
mStream = mHub.createStream(null, null,
PRE_STREAM_PRESET_PUBLISH_SECURITY);
} catch (PiliException e) {
logger.error("生成直播流异常:", e);
e.printStackTrace();
}
return mStream;
}


// 生成推送地址
public String createPushUrl(String streamId) {
Stream stream = getStreamById(streamId);
try {
if (true) {// 判断直播流是否正常
return stream.rtmpPublishUrl();
}
} catch (PiliException e) {
e.printStackTrace();
logger.error("生成推送地址异常", e);
}
return "";
}


// 根据id获得直播流
public Stream getStreamById(String streamId) {
try {
return mHub.getStream(streamId);
} catch (PiliException e) {
logger.error("根据id获得直播流异常:", e);
e.printStackTrace();
}
return null;
}


// 禁播
public Stream disableStream(String streamId) {
Stream stream = getStreamById(streamId);
try {
return stream.disable();
} catch (PiliException e) {
// TODO Auto-generated catch block
logger.error("直播流禁播异常:", e);
e.printStackTrace();
}
return null;
}


// 开启播放
public Stream enableStream(String streamId) {
Stream stream = getStreamById(streamId);
try {
return stream.enable();
} catch (PiliException e) {
// TODO Auto-generated catch block
logger.error("直播流开启异常:", e);
e.printStackTrace();
}
return null;
}


// 获得流状态
public boolean streamStatus(String streamId) {
Stream stream = getStreamById(streamId);
try {
Status status = stream.status();
logger.info(streamId + "直播流状态:" + status.getStatus());
if ("connected".equals(status.getStatus())) {
return true;
}
} catch (PiliException e) {
logger.error("获得直播流状态异常:", e);
e.printStackTrace();
}
return false;
}


// 将流文件保存
public SaveAsReturn saveAs(String streamId) {
SaveAsReturn returnDs=new SaveAsReturn();
Stream stream = getStreamById(streamId);
// String saveAsFormat = "mp4"; // required
String saveAsFormat = "m3u8"; 
String timeTemp = String.valueOf(new Date().getTime());
String saveAsName = "ydzb_" + timeTemp + "." + saveAsFormat; // required
long saveAsStart = 0; // required, in second, unix timestamp
long saveAsEnd = 0; // required, in second, unix timestamp
try {
// 获得流片段开始时间和结束时间
SegmentList list = stream.segments();
saveAsStart = list.getStart();
saveAsEnd = list.getEnd();
SaveAsResponse response = stream.saveAs(saveAsName, null,
saveAsStart, saveAsEnd);
logger.info("streamId:" + streamId + ",name:" + saveAsName
+ ",start:" + saveAsStart + ",end:" + saveAsEnd
+ ",TargetUrl:" + response.getTargetUrl());
String url=response.getUrl();
String persistentId=response.getPersistentId();
//转码mp4
persistentId=saveAsMp4(response.getUrl().substring(response.getUrl().indexOf("recordings")));
// response.getUrl();//m3u8
// response.getTargetUrl();//mp4
// String
// jsonstr=HttpRequest.sendPost("http://api.qiniu.com/status/get/prefop",
// "id="+response.getPersistentId());
// logger.info(jsonstr);
//拼接片头片尾
//joinVideo2(response.getUrl().substring(response.getUrl().indexOf("recordings"))+".mp4");
returnDs.setPersistentId(persistentId);
returnDs.setUrl(url);
returnDs.setTargetUrl(url+".mp4");
return returnDs;
} catch (PiliException e) {
// TODO Auto-generated catch block
logger.error("直播流保存异常:", e);
e.printStackTrace();
}
return null;
}


/**

* @方法名称:saveAsMp4
* @内容摘要: <将直播流转码成mp4>
* @param streamId
* @return String
* @exception
* @author:鹿伟伟
* @创建日期:2017年1月3日-上午11:02:07
*/
private String saveAsMp4(String streamId) {
try {
// streamId=StringUtil.getStreamId(streamId);
// 设置账号的AK,SK
Auth auth = Auth.create(rm.getValue("qiniu_access_key"),
rm.getValue("qiniu_secret_key"));
// 要上传的空间(bucket)的存储区域为华东时
// Zone z = Zone.zone0();
// 要上传的空间(bucket)的存储区域为华北时
// Zone z = Zone.zone1();
// 要上传的空间(bucket)的存储区域为华南时
// Zone z = Zone.zone2();
Zone z = Zone.zone1();
Configuration c = new Configuration(z);


// 新建一个OperationManager对象
OperationManager operater = new OperationManager(auth, c);
// 设置要转码的空间和key,并且这个key在你空间中存在
String bucket = "";
String key = streamId;
// 设置转码操作参数
String fops = "avthumb/mp4";
// 设置转码的队列
String pipeline = "";
// 可以对转码后的文件进行使用saveas参数自定义命名,当然也可以不指定文件会默认命名并保存在当前空间。
String urlbase64 = UrlSafeBase64.encodeToString(bucket + ":" + key+".mp4");
String pfops = fops + "|saveas/" + urlbase64;
// 设置pipeline参数
StringMap params = new StringMap().putWhen("force", 1, true)
.putNotEmpty("pipeline", pipeline);
// String persistid = operater.pfop(bucket, key, pfops, params);
// return persistid;
try {
String persistid = operater.pfop(bucket, key, pfops, params);
// 打印返回的persistid
// System.out.println(persistid);
return persistid;
} catch (QiniuException e) {
// 捕获异常信息
Response r = e.response;
// 请求失败时简单状态信息
logger.error(r.toString(), e);
try {
// 响应的文本信息
logger.error(r.bodyString());
} catch (QiniuException e1) {
// ignore
}
}
} catch (Exception e) {
// TODO: handle exception
logger.error("直播流转码mp4异常:", e);
}
return null;
}


/**

* @方法名称:createPlayerUrl
* @内容摘要: <根据直播流id生成播放地址>
* @param streamId
*            直播id
* @param type
*            FLV HLS 默认RTMP
* @return String 播放地址
* @exception
* @author:鹿伟伟
* @创建日期:2016年10月11日-下午1:57:12
*/
public String createPlayerUrl(String streamId, String type) {
Stream stream = getStreamById(streamId);
try {
// 默认 RTMP
if (streamStatus(streamId)) {// 判断直播流是否正常
if ("FLV".equals(type)) {
return stream.httpFlvLiveUrls().get(Stream.ORIGIN);
} else if ("HLS".equals(type)) {
return stream.hlsLiveUrls().get(Stream.ORIGIN);
} else {
return stream.rtmpLiveUrls().get(Stream.ORIGIN);
}
}
} catch (Exception e) {
logger.error("生成直播播放地址异常:", e);
e.printStackTrace();
return "";
}
return "";
}


public String deleteStream(String streamId) {
Stream stream = getStreamById(streamId);
try {
return stream.delete();
} catch (PiliException e) {
logger.error("deleteStream异常:", e);
e.printStackTrace();
}
return null;
}


// 直播封面
public String snapshot(String streamId) {
Stream stream = getStreamById(streamId);
try {
String fileName = "qyd_" + System.currentTimeMillis();
SnapshotResponse response = stream.snapshot(fileName, "jpg");
return response.getTargetUrl();
} catch (PiliException e) {
logger.error("snapshot异常:", e);
e.printStackTrace();
}
return null;
}
    
/**
* 上传本地文件
* @param args
*/
public static void uploadVedioFile(){
//构造一个带指定Zone对象的配置类
Configuration cfg = new Configuration(Zone.zone1());
//...其他参数参考类注释
UploadManager uploadManager = new UploadManager(cfg);
//...生成上传凭证,然后准备上传
String accessKey = "";
String secretKey = "-";
String bucket = "";
//如果是Windows情况下,格式是 D:\\qiniu\\test.png
String localFilePath = "C:\\Users\\Administrator\\Desktop\\vedio\\live (03).mp4";
//默认不指定key的情况下,以文件内容的hash值作为文件名
String key = null;
Auth auth = Auth.create(accessKey, secretKey);
String upToken = auth.uploadToken(bucket);
try {
   Response response = uploadManager.put(localFilePath, key, upToken);
   //解析上传成功的结果
   DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
   System.out.println(putRet.key);
   System.out.println(putRet.hash);
} catch (QiniuException ex) {
   Response r = ex.response;
   System.err.println(r.toString());
   try {
       System.err.println(r.bodyString());
   } catch (QiniuException ex2) {
       //ignore
   }
}
}
public static void getFileInfo(){
Configuration cfg = new Configuration(Zone.zone1());
//...其他参数参考类注释
String accessKey = "";
String secretKey = "-";
String bucket = "ql1dzhibo";
String key = "recordings/z1.ql1dzhibo.59c35d425e11fe72b084b/y_1505986424434.m3u8.mp4";
Auth auth = Auth.create(accessKey, secretKey);
BucketManager bucketManager = new BucketManager(auth, cfg);
try {
   FileInfo fileInfo = bucketManager.stat(bucket, key);
  System.out.println(JSON.toJSON(fileInfo));
} catch (QiniuException ex) {
   System.err.println(ex.response.toString());
}
}

//拼接两段视频
public  void joinVideo2(String key){
String accessKey = "";
String secretKey = "";
//待处理文件所在空间
String bucket = "";
//待处理文件名
Auth auth = Auth.create(accessKey, secretKey);
//数据处理指令,支持多个指令
String saveMp4Entry2 = String.format("%s:"+key, bucket);
String fops =String.format("avconcat/2/format/mp4/index/2/%s/%s|saveas/%s",
UrlSafeBase64.encodeToString("http://o9z2hke.bkt.clou.com/avthumb_test_target.mp4"),
UrlSafeBase64.encodeToString("http://o9zkej4.bkt.clouddnm/avthumb_test_target1.mp4"),UrlSafeBase64.encodeToString(saveMp4Entry2));
//数据处理队列名称,必须
String persistentPipeline = "";
//数据处理完成结果通知地址
//构造一个带指定Zone对象的配置类
Configuration cfg = new Configuration(Zone.zone1());
//构建持久化数据处理对象
OperationManager operationManager = new OperationManager(auth, cfg);
try {
   String persistentId = operationManager.pfop(bucket, key,fops, persistentPipeline, true);
   logger.error("persistentIdpersistentId:"+persistentId);
} catch (QiniuException e) {
   System.err.println(e.response.toString());
   logger.error("persistentIdpersistentId:"+"---------");
}
}


public static void main(String[] args) {


// System.out.println(QiniuLiveTools.getInstance().saveAsMp4(
// "recordings/z1.ql.586b512975b625198b194f10b_1483429219401.m3u8"));
// String str="http://pili-media.ql1d.com/recordings/z1.ql1dzhibo.5865e77b017850c39a5/ydzb_1483242710898.m3u8";
// System.out.println(str.indexOf("recordings"));
// System.out.println(str.substring(str.indexOf("recordings")));
//System.out.println(QiniuLiveTools.getInstance().saveAs("z1.ql1bo.58e25da95be740061c0bb9").toString());
//uploadVedioFile();
   //getFileInfo();
//joinVideo2();
}
}

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值