| | |
| | | /****************************************************************************** |
| | | * Copyright (C) 2015 Shenzhen Penguin Network Technology Co., Ltd |
| | | * All Rights Reserved. |
| | | * 本软件为深圳市企鹅网络科技有限公司开发研制。未经本公司正式书面同意,其他任何个人、团体 |
| | | * 不得使用、复制、修改或发布本软件. |
| | | * 本软件为深圳市企鹅网络科技有限公司开发研制。未经本公司正式书面同意,其他任何个人、团体 |
| | | * 不得使用、复制、修改或发布本软件. |
| | | *****************************************************************************/ |
| | | |
| | | package com.qxueyou.scc.teach.live.service.impl; |
| | |
| | | |
| | | private static final Logger log = LogManager.getLogger(MediaVideoLivePlayBackService.class); |
| | | |
| | | //直播回放队列 |
| | | //直播回放队列 |
| | | public static final String LIVE_PLAYBACK_LST = "LIVE_PLAYBACK_LST"; |
| | | |
| | | //直播回放全局锁 |
| | | //直播回放全局锁 |
| | | public static final String LIVE_PLAYBACK_LOCK = "LIVE_PLAYBACK_LOCK"; |
| | | |
| | | @Autowired |
| | |
| | | return this.find(hql.toString(),params, MediaVideoLiveReplay.class); |
| | | } |
| | | |
| | | //生成回放(需修改为晚上2:00 开始执行) |
| | | //生成回放(需修改为晚上2:00 开始执行) |
| | | @Scheduled(cron = " 0 0/2 * * * ?") |
| | | protected void doTimer(){ |
| | | if(this.lock()){ |
| | |
| | | return ; |
| | | } |
| | | |
| | | //判断是否是回放状态 |
| | | //判断是否是回放状态 |
| | | MediaVideoLive live = this.read(MediaVideoLive.class, liveId); |
| | | |
| | | if(live.getStatus()==MediaVideoLive.STATUS_LIVE_DOWNLOAD){ |
| | |
| | | |
| | | this.doVideoLivePlayBack(live); |
| | | |
| | | //更新状态 |
| | | //更新状态 |
| | | live.setStatus(MediaVideoLive.STATUS_LIVE_REVIEW); |
| | | this.save(live); |
| | | } |
| | | } catch (Exception e) { |
| | | //重新处理 |
| | | //重新处理 |
| | | if(StringUtils.isNotEmpty(liveId)){ |
| | | cacheService.lstRightPush(LIVE_PLAYBACK_LST,liveId); |
| | | } |
| | |
| | | |
| | | @Override |
| | | public void testPlayBack(String liveId){ |
| | | //判断是否是回放状态 |
| | | //判断是否是回放状态 |
| | | MediaVideoLive live = this.read(MediaVideoLive.class, liveId); |
| | | |
| | | if(live.getStatus()==MediaVideoLive.STATUS_LIVE_DOWNLOAD){ |
| | | try { |
| | | this.doVideoLivePlayBack(live); |
| | | |
| | | //更新状态 |
| | | //更新状态 |
| | | live.setStatus(MediaVideoLive.STATUS_LIVE_REVIEW); |
| | | this.save(live); |
| | | |
| | | } catch (Exception e) { |
| | | //重新处理 |
| | | //重新处理 |
| | | cacheService.lstRightPush(LIVE_PLAYBACK_LST,liveId); |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | public void doVideoLivePlayBack(MediaVideoLive videoLive) throws Exception{ |
| | | //读取原文件 |
| | | //读取原文件 |
| | | File srcRootFile = new File(cfg.getSrcLivePath()); |
| | | |
| | | String[] fileNames= srcRootFile.list(new FilenameFilter(){ |
| | |
| | | |
| | | log.info("doVideoLivePlayBack fileNames: "+fileNames==null?"xxx":Arrays.toString(fileNames)); |
| | | |
| | | //排序 |
| | | //排序 |
| | | Arrays.sort(fileNames, new Comparator<String>(){ |
| | | @Override |
| | | public int compare(String o1, String o2) { |
| | |
| | | } |
| | | }); |
| | | |
| | | //读取 |
| | | //读取 |
| | | if(fileNames!=null && fileNames.length>0){ |
| | | short order = 1 ; |
| | | for(String srcFileName:fileNames){ |
| | | log.info("doCreateVideoLiveReplay srcFileName: "+srcFileName); |
| | | doCreateVideoLiveReplay(videoLive,srcFileName,order++); //生成回放 |
| | | doCreateVideoLiveReplay(videoLive,srcFileName,order++); //生成回放 |
| | | } |
| | | } |
| | | |
| | | //清理源文件 |
| | | //清理源文件 |
| | | if(fileNames!=null && fileNames.length>0){ |
| | | for(String srcFileName:fileNames){ |
| | | log.info("删除原文件:filePath"+srcRootFile.getAbsolutePath().concat(File.separator).concat(srcFileName)); |
| | | log.info("删除原文件:filePath"+srcRootFile.getAbsolutePath().concat(File.separator).concat(srcFileName)); |
| | | FileUtils.deleteQuietly(new File(srcRootFile.getAbsolutePath().concat(File.separator).concat(srcFileName))); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | //生成VideoLiveReplay信息 |
| | | //生成VideoLiveReplay信息 |
| | | private String doCreateVideoLiveReplay(MediaVideoLive videoLive,String srcFileName,short order) throws Exception{ |
| | | //视频文件后缀 |
| | | //视频文件后缀 |
| | | String mediaSuffix = srcFileName.substring(srcFileName.lastIndexOf(".")); |
| | | |
| | | //回放地址 |
| | | //回放地址 |
| | | String dstPath =this.generateDstPath(videoLive.getVideoLiveId(), mediaSuffix); |
| | | |
| | | File srcFile = new File(cfg.getSrcLivePath() + srcFileName); |
| | | |
| | | File dstFileDir = new File(cfg.getResRootPath().concat(dstPath)).getParentFile(); |
| | | |
| | | //创建目录 |
| | | //创建目录 |
| | | dstFileDir.mkdirs(); |
| | | |
| | | log.info("开始生成 doCreateVideoLiveReplay: srcFile"+srcFile.getAbsolutePath()); |
| | | log.info("开始生成 doCreateVideoLiveReplay: srcFile"+srcFile.getAbsolutePath()); |
| | | |
| | | String dstFile = this.convertFlvToMp4(srcFile, dstFileDir); |
| | | |
| | | log.info("结束生成 doCreateVideoLiveReplay: dstFile"+ dstFile); |
| | | log.info("结束生成 doCreateVideoLiveReplay: dstFile"+ dstFile); |
| | | |
| | | //获取视频时长 |
| | | //获取视频时长 |
| | | long playTime = this.getMediaPlayTime(srcFile.getAbsolutePath()); |
| | | |
| | | MediaVideoLiveReplay liveReplay = new MediaVideoLiveReplay(); |
| | |
| | | |
| | | |
| | | /** |
| | | * 获取文件目标路径 |
| | | * 获取文件目标路径 |
| | | * |
| | | * @param name |
| | | * @return |
| | |
| | | } |
| | | |
| | | private String convertFlvToMp4(File srcFile,File dstFile) throws Exception{ |
| | | // 获取直播视频片段信息 |
| | | // 获取直播视频片段信息 |
| | | FfmpegFileVO videoFileVO = new FfmpegFileVO(); |
| | | videoFileVO.setInputPath(srcFile.getPath()); |
| | | |
| | | // 转码视频 |
| | | // 转码视频 |
| | | videoFileVO.setOutputPath(dstFile.getPath() + File.separator); |
| | | |
| | | return FfmpegMediaHelper.converUploadVideoToLiveMp4(videoFileVO, new FfmpegVideoInfo()); |
| | | |
| | | //copy备份原片段(暂不备份) |
| | | //copy备份原片段(暂不备份) |
| | | // FileUtils.copyFile(srcFile, dstFile); |
| | | } |
| | | |
| | | |
| | | //格式: d72de336c7ed45beb14641a79074f9bb-1541497652-rec , 时间戳单位: 秒 |
| | | //格式: d72de336c7ed45beb14641a79074f9bb-1541497652-rec , 时间戳单位: 秒 |
| | | private Long getStartTime(String filePath){ |
| | | return Long.valueOf(filePath.split("-")[1]); |
| | | } |
| | | |
| | | private boolean lock(){ |
| | | boolean lockResult = redisTemplate.opsForValue().setIfAbsent(LIVE_PLAYBACK_LOCK, "lock"); |
| | | //可能发生死锁,需要手动清除锁 |
| | | //可能发生死锁,需要手动清除锁 |
| | | if(lockResult==true){ |
| | | redisTemplate.expire(LIVE_PLAYBACK_LOCK, 6, TimeUnit.HOURS); |
| | | } |