给ZLMediaKit添加一个录制MP4文件自动转HLS的功能!
其中ZLMediakit的Server是支持动态添加摄像头,为了简单使用,这里增加一个静态增加摄像头的能力,给config.ini文件添加一个camera一节:
[camera]
#配置默认拉取的监控摄像头地址,对应的点播地址为:http://192.168.1.100:8090/live/chn1/hls.m3u8 http://192.168.1.100:8090/live/chn2/hls.m3u8
number=1
ip_1=rtsp://hkws_media:344444!@192.168.1.103:554/Streaming/Channels/102?transportmode=unicast&profile=Profile_2
ip_2=rtsp://admin:444444@192.168.1.104:554/h264/ch1/sub/av_stream
修改main.cpp增加自动监控采集,并添加录制视频转hls功能:
//add for camera.默认加载的摄像头地址信息配置
namespace CameraConfig{
#define CAMERA_FIELD "camera."
const string number = CAMERA_FIELD"number";
const string ip = CAMERA_FIELD"ip_";
}
//默认加载的摄像头地址信息配置
namespace CameraConfig{
#define CAMERA_FIELD "camera."
const string number = CAMERA_FIELD"number";
const string ip = CAMERA_FIELD"ip_";
}
static map<string, PlayerProxy::Ptr> mGlobalProxyMap;
static void startMonitorRecord(){
//kBroadcastRecordMP4
NoticeCenter::Instance().addListener(nullptr,Broadcast::kBroadcastRecordMP4,[](BroadcastRecordMP4Args){
std::string strFilePath = info.strFilePath;
std::string strFileName = info.strFileName;
std::string strFolder = info.strFolder;
std::string strUrl = info.strUrl;
std::string strAppName = info.strAppName;
std::string strStreamId = info.strStreamId;
std::string strVhost = info.strVhost;
DebugL << "\r\n# record strFileName:\r\n" << strFileName << ":" << strFilePath << "\r\n"
<< "# strFolder:\r\n" << strFolder << "\r\n";
//启动执行切片的脚本
std::string strcmd = "/usr/local/bin/ffmpeg_mp4_to_hls.sh "+strFileName+" "+strFilePath + " "+strFolder;
system(strcmd.c_str());
});
}
void main(){
//读camera的配置列表
uint16_t cameranumber = mINI::Instance()[CameraConfig::number];
int i = 0;
for (;i<cameranumber; i++) {
string ipKey = CameraConfig::ip + to_string(i+1).data();
string url = mINI::Instance()[ipKey];
if (url.size() == 0){
continue;
}
//bEnableRtsp:false, bEnableRtmp = true, bEnableHls = true, bEnableMp4 = true,
PlayerProxy::Ptr player(new PlayerProxy(DEFAULT_VHOST, "live", std::string("chn") + to_string(i+1).data(), false, true, true, true, -1, nullptr));
//指定RTP over TCP(播放rtsp时有效)
(*player)[kRtpType] = Rtsp::RTP_TCP;
//开始播放,如果播放失败或者播放中止,将会自动重试若干次,重试次数在配置文件中配置,默认一直重试
player->play(url);
//需要保存PlayerProxy,否则作用域结束就会销毁该对象
mGlobalProxyMap.emplace(to_string(i), player);
}
if (mGlobalProxyMap.size() > 0){
startMonitorRecord();
//不需要这个功能了, 录制自动一个小时录制一次
//起一个定时服务,每隔15分钟停止一次录制,然后开启录制
// startRecordTimer();
}
// add end
}
//add end.
修改WebAPI.cpp,增加获取HLS点播地址的功能!
api_regist1("/index/api/getHlsRecordFile", [](API_ARGS1){
CHECK_SECRET();
CHECK_ARGS("vhost", "app", "stream");
auto record_path = Recorder::getRecordPath(Recorder::type_mp4, allArgs["vhost"], allArgs["app"],allArgs["stream"]);
auto period = allArgs["period"];
//判断是获取mp4文件列表还是获取文件夹列表
bool search_mp4 = true;//period.size() == sizeof("2020-02-01") - 1;
if (search_mp4) {
record_path = record_path + period + "/";
}
Json::Value paths(arrayValue);
//这是筛选日期,获取文件夹列表
File::scanDir(record_path, [&](const string &path, bool isDir) {
int pos = path.rfind('/');
if (pos != string::npos) {
string relative_path = path.substr(pos + 1);
if (search_mp4) {
if (!isDir) {
//返回m3u8文件路径
std::string file_name = relative_path.substr(0, relative_path.size() - 4);
paths.append(file_name+"/" + file_name+".m3u8");
}
} else if (isDir && relative_path.find(period) == 0) {
//匹配到对应日期的文件夹
paths.append(relative_path);
}
}
return true;
}, false);
val["data"]["rootPath"] = record_path;
val["data"]["paths"] = paths;
});
接口返回的数据:
http://192.168.1.120:8090/index/api/getHlsRecordFile?secret=03334667635c73f7-bb6bcc&vhost=__defaultVhost__&app=live&stream=chn2&period=2020-11-16
返回参数:
{"code":0,"data":{"paths":["12-38-59/12-38-59.m3u8","11-39-51/11-39-51.m3u8","11-29-43/11-29-43.m3u8","11-23-29/11-23-29.m3u8","13-09-01/13-09-01.m3u8","12-08-57/12-08-57.m3u8","11-54-47/11-54-47.m3u8"],"rootPath":"/opt/mediaserver/www/record/live/chn1/2020-11-16/"}}
点播视频的地址:http://192.168.1.120:8090/record/live/chn1/2020-11-16/12-38-59/12-38-59.m3u8
录制的视频和切片文件的目录结构关系:
[root@localhost 2020-11-16]# pwd
/usr/local/src/server/ZLMediaKit/release/linux/Debug/www/record/live/chn1/2020-11-16
[root@localhost 2020-11-16]# ll
总用量 1054856
-rw-r--r-- 1 root root 38781317 11月 16 11:28 11-23-29.mp4
-rw-r--r-- 1 root root 38710638 11月 16 11:34 11-29-43.mp4
drwxr-xr-x 2 root root 4096 11月 16 11:54 11-39-51
-rw-r--r-- 1 root root 38749464 11月 16 11:44 11-39-51.mp4
drwxr-xr-x 2 root root 4096 11月 16 12:00 11-54-47
-rw-r--r-- 1 root root 38730555 11月 16 11:59 11-54-47.mp4
drwxr-xr-x 2 root root 4096 11月 16 12:40 12-08-57
-rw-r--r-- 1 root root 231337755 11月 16 12:38 12-08-57.mp4
drwxr-xr-x 2 root root 4096 11月 16 13:10 12-38-59
-rw-r--r-- 1 root root 231368491 11月 16 13:09 12-38-59.mp4
drwxr-xr-x 2 root root 4096 11月 16 13:40 13-09-01
-rw-r--r-- 1 root root 231344722 11月 16 13:39 13-09-01.mp4
drwxr-xr-x 2 root root 4096 11月 16 15:13 14-41-54
-rw-r--r-- 1 root root 231089039 11月 16 15:11 14-41-54.mp4
[root@localhost 2020-11-16]#
ffmpeg_mp4_to_hls.sh, mp4视频转HLS脚本的功能:
#!/bin/sh
#接收用户参数
strFileName=$1
strFilePath=$2
strFolder=$3
function starttransport(){
#截取除后缀的文件名
hlsFileName=$(echo $strFileName | cut -d . -f1)
hlsFolderPath=${strFilePath%"${strFileName}"}
hlsFolderPath="${hlsFolderPath}${hlsFileName}/"
#create folder.
$(mkdir -p ${hlsFolderPath})
echo "hlsFileName:${hlsFileName}, hlsForderPath:${hlsFolderPath}"
#$(cd ${hlsFolderPath})
$(ffmpeg -i ${strFilePath} -c:v libx264 -hls_time 60 -hls_list_size 0 -c:a aac -strict -2 -f hls ${hlsFolderPath}${hlsFileName}.m3u8 &)
}
#main
starttransport