diff --git a/api/include/mk_recorder.h b/api/include/mk_recorder.h index 7419fce3..a09b0147 100644 --- a/api/include/mk_recorder.h +++ b/api/include/mk_recorder.h @@ -83,7 +83,7 @@ API_EXPORT int API_CALL mk_recorder_status(int type, const char *vhost, const ch * @param continue_record 流注销时是否继续等待录制还是立即停止录制 * @return 0代表成功,负数代表失败 */ -API_EXPORT int API_CALL mk_recorder_start(int type, const char *vhost, const char *app, const char *stream,int wait_for_record, int continue_record); +API_EXPORT int API_CALL mk_recorder_start(int type, const char *vhost, const char *app, const char *stream, const char *customized_path, int wait_for_record, int continue_record); /** * 停止录制 diff --git a/api/source/mk_recorder.cpp b/api/source/mk_recorder.cpp index 7ac4968c..175a1e78 100644 --- a/api/source/mk_recorder.cpp +++ b/api/source/mk_recorder.cpp @@ -57,9 +57,9 @@ API_EXPORT int API_CALL mk_recorder_status(int type, const char *vhost, const ch return Recorder::getRecordStatus((Recorder::type)type,vhost,app,stream); } -API_EXPORT int API_CALL mk_recorder_start(int type, const char *vhost, const char *app, const char *stream,int wait_for_record, int continue_record){ +API_EXPORT int API_CALL mk_recorder_start(int type, const char *vhost, const char *app, const char *stream,const char *customized_path,int wait_for_record, int continue_record){ assert(vhost && app && stream); - return Recorder::startRecord((Recorder::type)type,vhost,app,stream,wait_for_record,continue_record); + return Recorder::startRecord((Recorder::type)type,vhost,app,stream,customized_path,wait_for_record,continue_record); } API_EXPORT int API_CALL mk_recorder_stop(int type, const char *vhost, const char *app, const char *stream){ diff --git a/server/WebApi.cpp b/server/WebApi.cpp index 91a158f6..04dd3715 100644 --- a/server/WebApi.cpp +++ b/server/WebApi.cpp @@ -745,10 +745,12 @@ void installWebApi() { API_REGIST(api,startRecord,{ CHECK_SECRET(); CHECK_ARGS("type","vhost","app","stream","wait_for_record","continue_record"); + int result = Recorder::startRecord((Recorder::type)allArgs["type"].as(), allArgs["vhost"], allArgs["app"], allArgs["stream"], + allArgs["customized_path"], allArgs["wait_for_record"], allArgs["continue_record"]); val["result"] = result; diff --git a/src/Common/MultiMediaSourceMuxer.h b/src/Common/MultiMediaSourceMuxer.h index b711f638..0ec1f2ed 100644 --- a/src/Common/MultiMediaSourceMuxer.h +++ b/src/Common/MultiMediaSourceMuxer.h @@ -53,11 +53,11 @@ public: } if(enable_hls){ - Recorder::startRecord(Recorder::type_hls,vhost, app, stream, true, false); + Recorder::startRecord(Recorder::type_hls,vhost, app, stream, "", true, false); } if(enable_mp4){ - Recorder::startRecord(Recorder::type_mp4,vhost, app, stream, true, false); + Recorder::startRecord(Recorder::type_mp4,vhost, app, stream, "", true, false); } _get_hls_media_source = [vhost,app,stream](){ diff --git a/src/Record/HlsMakerImp.cpp b/src/Record/HlsMakerImp.cpp index 39fe77b9..cdbe8e01 100644 --- a/src/Record/HlsMakerImp.cpp +++ b/src/Record/HlsMakerImp.cpp @@ -58,8 +58,9 @@ string HlsMakerImp::onOpenSegment(int index) { string segment_name , segment_path; { auto strDate = getTimeStr("%Y-%m-%d"); - auto strTime = getTimeStr("%H-%M-%S"); - segment_name = StrPrinter << strDate + "/" + strTime << "_" << index << ".ts"; + auto strHour = getTimeStr("%H"); + auto strTime = getTimeStr("%M-%S"); + segment_name = StrPrinter << strDate + "/" + strHour + "/" + strTime << "_" << index << ".ts"; segment_path = _path_prefix + "/" + segment_name; if(isLive()){ _segment_file_paths.emplace(index,segment_path); diff --git a/src/Record/Recorder.cpp b/src/Record/Recorder.cpp index e3ef8106..851a9d32 100644 --- a/src/Record/Recorder.cpp +++ b/src/Record/Recorder.cpp @@ -34,7 +34,7 @@ using namespace toolkit; namespace mediakit { -MediaSinkInterface *createHlsRecorder(const string &strVhost_tmp, const string &strApp, const string &strId) { +MediaSinkInterface *createHlsRecorder(const string &strVhost_tmp, const string &strApp, const string &strId, const string &customized_path) { #if defined(ENABLE_HLS) GET_CONFIG(bool, enableVhost, General::kEnableVhost); GET_CONFIG(string, hlsPath, Hls::kFilePath); @@ -53,6 +53,10 @@ MediaSinkInterface *createHlsRecorder(const string &strVhost_tmp, const string & } else { m3u8FilePath = strApp + "/" + strId + "/hls.m3u8"; } + //Here we use the customized file path. + if(!customized_path.empty()){ + m3u8FilePath = customized_path + "/hls.m3u8"; + } m3u8FilePath = File::absolutePath(m3u8FilePath, hlsPath); auto ret = new HlsRecorder(m3u8FilePath, params); ret->setMediaSource(strVhost, strApp, strId); @@ -62,7 +66,7 @@ MediaSinkInterface *createHlsRecorder(const string &strVhost_tmp, const string & #endif //defined(ENABLE_HLS) } -MediaSinkInterface *createMP4Recorder(const string &strVhost_tmp, const string &strApp, const string &strId) { +MediaSinkInterface *createMP4Recorder(const string &strVhost_tmp, const string &strApp, const string &strId, const string &customized_path) { #if defined(ENABLE_MP4RECORD) GET_CONFIG(bool, enableVhost, General::kEnableVhost); GET_CONFIG(string, recordPath, Record::kFilePath); @@ -80,6 +84,10 @@ MediaSinkInterface *createMP4Recorder(const string &strVhost_tmp, const string & } else { mp4FilePath = recordAppName + "/" + strApp + "/" + strId + "/"; } + //Here we use the customized file path. + if(!customized_path.empty()){ + mp4FilePath = customized_path + "/"; + } mp4FilePath = File::absolutePath(mp4FilePath, recordPath); return new MP4Recorder(mp4FilePath, strVhost, strApp, strId); #else @@ -193,7 +201,7 @@ public: return it->second->getRecorder(); } - int startRecord(const string &vhost, const string &app, const string &stream_id, bool waitForRecord, bool continueRecord) { + int startRecord(const string &vhost, const string &app, const string &stream_id, const string &customized_path, bool waitForRecord, bool continueRecord) { auto key = getRecorderKey(vhost, app, stream_id); lock_guard lck(_recorder_mtx); if (getRecordStatus_l(key) != Recorder::status_not_record) { @@ -207,7 +215,7 @@ public: return -1; } - auto recorder = MediaSinkInterface::Ptr(createRecorder(vhost, app, stream_id)); + auto recorder = MediaSinkInterface::Ptr(createRecorder(vhost, app, stream_id, customized_path)); if (!recorder) { // 创建录制器失败 return -2; @@ -326,14 +334,14 @@ private: return vhost + "/" + app + "/" + stream_id; } - MediaSinkInterface *createRecorder(const string &vhost, const string &app, const string &stream_id) { + MediaSinkInterface *createRecorder(const string &vhost, const string &app, const string &stream_id, const string &customized_path) { MediaSinkInterface *ret = nullptr; switch (type) { case Recorder::type_hls: - ret = createHlsRecorder(vhost, app, stream_id); + ret = createHlsRecorder(vhost, app, stream_id,customized_path); break; case Recorder::type_mp4: - ret = createMP4Recorder(vhost, app, stream_id); + ret = createMP4Recorder(vhost, app, stream_id,customized_path); break; default: break; @@ -385,12 +393,12 @@ std::shared_ptr Recorder::getRecorder(type type, const strin } -int Recorder::startRecord(Recorder::type type, const string &vhost, const string &app, const string &stream_id, bool waitForRecord, bool continueRecord) { +int Recorder::startRecord(Recorder::type type, const string &vhost, const string &app, const string &stream_id, const string &customized_path, bool waitForRecord, bool continueRecord) { switch (type){ case type_mp4: - return MediaSourceWatcher::Instance().startRecord(vhost,app,stream_id,waitForRecord,continueRecord); + return MediaSourceWatcher::Instance().startRecord(vhost,app,stream_id,customized_path,waitForRecord,continueRecord); case type_hls: - return MediaSourceWatcher::Instance().startRecord(vhost,app,stream_id,waitForRecord,continueRecord); + return MediaSourceWatcher::Instance().startRecord(vhost,app,stream_id,customized_path,waitForRecord,continueRecord); } WarnL << "unknown record type: " << type; return -3; diff --git a/src/Record/Recorder.h b/src/Record/Recorder.h index 26921214..84107950 100644 --- a/src/Record/Recorder.h +++ b/src/Record/Recorder.h @@ -73,7 +73,7 @@ public: * @param continueRecord 流注销时是否继续等待录制还是立即停止录制 * @return 0代表成功,负数代表失败 */ - static int startRecord(type type, const string &vhost, const string &app, const string &stream_id,bool waitForRecord, bool continueRecord); + static int startRecord(type type, const string &vhost, const string &app, const string &stream_id,const string &customized_path,bool waitForRecord, bool continueRecord); /** * 停止录制