随着视频智能安防监控系统的普及,安防监控平台在各行各业的项目中得到了广泛应用。未来,AI智能将成为安防监控的主导方向。为了满足行业需求,TSINGSEE青犀视频不断提升现有产品的适应能力,进一步推动智能安防监控系统的发展。目前,EasyNVR作为TSINGSEE青犀视频开发的稳定可靠的智能安防监控平台,具备视频采集、直播、转码、分发等功能。在录像功能方面,除了支持调取录像视频进行直接回放外,还可以通过接口调用下载录像文件。不过目前下载和播放的视频文件格式仅限于MP4格式。
根据部分项目团队提出的新需求,他们希望EasyNVR的录像接口调用功能能够在指定时间段返回在线的m3u8格式视频,以便进行在线观看和下载。
目前,EasyNVR的录像文件确实是以m3u8格式存储在服务器中。然而,在调用指定时间段的录像播放及下载接口时,由于EasyNVR会将录像文件通过ffmpeg转换为mp4格式,所以当前的下载和播放功能仅限于mp4格式的视频。
实现该项目的需求,我们可以定位到EasyNVR接口中找到指定时间段录像播放及下载接口具体逻辑处。首先将接口改变下,需要添加个字段判断获取m3u8格式的视频还是mp4的视频,这个字段为file,这个新接口的file字段不能为空。参考代码如下:
/**
* @api {get} /api/v2/record/video/:operate/:file/:id/:starttime/:endtime 指定时间段录像播放及下载
* @apiGroup record
* @apiParam {String=play,download} operate 调用操作 play:播放 download下载
* @apiParam {String=mp4,m3u8} file 文件类别 m3u8:(只提供在线地址) mp4:支持
* @apiParam {String} id 通道号
* @apiParam {String} starttime 开始时间, YYYYMMDDHHmmss
* @apiParam {String} endtime 结束时间, YYYYMMDDHHmmss
* @apiSuccessExample 播放示例
* 播放mp4
* http://localhost:10800/api/v2/record/video/play/mp4/1/20180911101139/20180911101248
* 播放m3u8
* http://localhost:10800/api/v2/record/video/play/m3u8/1/20180911101139/20180911101248
* @apiErrorExample 下载示例 (不支持下载m3u8)
* 下载mp4
* http://localhost:10800/api/v2/record/video/download/mp4/1/20180911101139/20180911101248
*/
func (h *APIHandler) VideoFileMP4(c *gin.Context) {
operate := c.Param("operate")
fileType := strings.ToLower(c.Param("file"))
if fileType == "" {
c.AbortWithStatusJSON(http.StatusBadRequest, "文件类别不能为空")
return
}
var err error
id := c.Param("id")
if id == "" {
c.AbortWithStatusJSON(http.StatusBadRequest, "未指定通道号")
return
}
streamID := channels.StreamIDString(id)
starttime := c.Param("starttime")
endtime := c.Param("endtime")
if matched, err := regexp.MatchString(`^\d{14}$`, starttime); !matched || err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, "开始时间格式不合法,正确格式:YYYYMMDDHHmmss")
return
}
if matched, err := regexp.MatchString(`^\d{14}$`, endtime); !matched || err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, "结束时间格式不合法,正确格式:YYYYMMDDHHmmss")
return
}
start := ff.StrYYYYMMDDHHmmssToTime(starttime)
end := ff.StrYYYYMMDDHHmmssToTime(endtime)
if start.After(end) {
c.AbortWithStatusJSON(http.StatusBadRequest, "开始时间要小于结束时间")
return
}
if end.Unix()-start.Unix() > 10800 {
c.AbortWithStatusJSON(http.StatusBadRequest, "最大播放/下载录像间隔是3小时!")
return
}
videoID := fmt.Sprintf(`%s_%s_%s`, id, starttime, endtime)
recordCachePath := dss.RecordDir()
if operate == "play" && fileType == "m3u8" {
resPath, ok, _ := ff.GetRecordM3U8File(id, start, end, videoID, false)
if ok != "Complete" {
c.AbortWithStatusJSON(http.StatusBadRequest, "获取录像错误!")
return
}
c.JSON(http.StatusOK, resPath)
return
}
mp4Path := filepath.Join(recordCachePath, fmt.Sprintf(`Stream_%s.mp4`, videoID))
if utils.Exist(mp4Path) {
//存在直接返回
ff.RecordCacheTime[videoID] = ff.RecordCacheTimeStruct{
Time: time.Now(),
Path: mp4Path}
ff.OperFile(c, operate, mp4Path, videoID)
return
}
//判断任务是否在处理
if _, OK := ff.RecordCacheTime[videoID]; OK { //存在任务
c.AbortWithStatusJSON(http.StatusBadRequest, "合成中")
return
}
安防监控系统支持直接下载并进行部署测试,如果您对其感兴趣,可以直接下载并进行测试。在测试期间,您仍可调用二次开发接口,并享有定制、修改和功能拓展的支持。