diff --git a/conf/config.ini b/conf/config.ini index 9be5e411..ec3a557a 100644 --- a/conf/config.ini +++ b/conf/config.ini @@ -284,6 +284,11 @@ segKeep=0 # If set to 1, the length of the first segment is forcibly set to exactly 1 GOP. # When the GOP is smaller than `segDur`, this can improve the initial startup (instant playback) speed. fastRegister=0 + +# fmp4 HLS切片文件的扩展名,例如 .mp4 或 .m4s(fmp4媒体段的标准扩展名);init段始终为init.mp4,mpegts切片始终为.ts +# File extension for fMP4 HLS segment files, e.g. .mp4 or .m4s (the standard extension for fMP4 media segments). +# The init segment is always init.mp4, and mpegts segments are always .ts. +fmp4SegExt=.mp4 [hook] # 是否启用hook事件,启用后,推拉流都将进行鉴权 # Whether to enable webhook events. When enabled, pushing and pulling streams requires authentication. diff --git a/src/Common/config.cpp b/src/Common/config.cpp index f1774fe7..591e42df 100644 --- a/src/Common/config.cpp +++ b/src/Common/config.cpp @@ -355,6 +355,7 @@ const string kFileBufSize = HLS_FIELD "fileBufSize"; const string kBroadcastRecordTs = HLS_FIELD "broadcastRecordTs"; const string kDeleteDelaySec = HLS_FIELD "deleteDelaySec"; const string kFastRegister = HLS_FIELD "fastRegister"; +const string kFmp4SegExt = HLS_FIELD "fmp4SegExt"; static onceToken token([]() { mINI::Instance()[kSegmentDuration] = 2; @@ -366,6 +367,7 @@ static onceToken token([]() { mINI::Instance()[kBroadcastRecordTs] = false; mINI::Instance()[kDeleteDelaySec] = 10; mINI::Instance()[kFastRegister] = false; + mINI::Instance()[kFmp4SegExt] = ".mp4"; }); } // namespace Hls diff --git a/src/Common/config.h b/src/Common/config.h index d33b71f7..e3f85844 100644 --- a/src/Common/config.h +++ b/src/Common/config.h @@ -531,6 +531,9 @@ extern const std::string kDeleteDelaySec; // 如果设置为1,则第一个切片长度强制设置为1个GOP [AUTO-TRANSLATED:fbbb651d] // If set to 1, the length of the first slice is forced to be 1 GOP extern const std::string kFastRegister; +// fmp4 HLS切片文件的扩展名(例如 .mp4 或 .m4s);mpegts切片始终为.ts +// File extension for fMP4 HLS segment files (e.g. .mp4 or .m4s); mpegts segments are always .ts +extern const std::string kFmp4SegExt; } // namespace Hls // //////////Rtp代理相关配置/////////// [AUTO-TRANSLATED:7b285587] diff --git a/src/Http/HttpConst.cpp b/src/Http/HttpConst.cpp index 7c1a896c..240057d3 100644 --- a/src/Http/HttpConst.cpp +++ b/src/Http/HttpConst.cpp @@ -183,6 +183,7 @@ static const char *s_mime_src[][2] = { {"3gp", "video/3gpp"}, {"ts", "video/mp2t"}, {"mp4", "video/mp4"}, + {"m4s", "video/mp4"}, {"mpeg", "video/mpeg"}, {"mpg", "video/mpeg"}, {"mov", "video/quicktime"}, diff --git a/src/Record/HlsMakerImp.cpp b/src/Record/HlsMakerImp.cpp index 37e49be2..d5c77665 100644 --- a/src/Record/HlsMakerImp.cpp +++ b/src/Record/HlsMakerImp.cpp @@ -31,13 +31,16 @@ std::string getDelayPath(const std::string& originalPath) { } HlsMakerImp::HlsMakerImp(bool is_fmp4, const string &m3u8_file, const string ¶ms, uint32_t bufSize, float seg_duration, - uint32_t seg_number, bool seg_keep) : HlsMaker(is_fmp4, seg_duration, seg_number, seg_keep) { + uint32_t seg_number, bool seg_keep, const string &fmp4_seg_ext) : HlsMaker(is_fmp4, seg_duration, seg_number, seg_keep) { _poller = EventPollerPool::Instance().getPoller(); _path_prefix = m3u8_file.substr(0, m3u8_file.rfind('/')); _path_hls = m3u8_file; _path_hls_delay = getDelayPath(m3u8_file); _params = params; _buf_size = bufSize; + // 兼容用户配置不带前导点的扩展名(例如 m4s),统一补上"." [AUTO-TRANSLATED] + // Tolerate user-configured extensions without a leading dot (e.g. m4s) by normalizing to ".m4s" + _fmp4_seg_ext = fmp4_seg_ext.empty() ? ".mp4" : (fmp4_seg_ext.front() == '.' ? fmp4_seg_ext : "." + fmp4_seg_ext); _file_buf.reset(new char[bufSize], [](char *ptr) { delete[] ptr; }); _info.folder = _path_prefix; } @@ -151,7 +154,7 @@ string HlsMakerImp::onOpenSegment(uint64_t index) { auto strHour = getTimeStr("%H"); auto strTime = getTimeStr("%M-%S"); auto current_dir = strDate + "/" + strHour + "/"; - segment_name = current_dir + strTime + "_" + std::to_string(index) + (isFmp4() ? ".mp4" : ".ts"); + segment_name = current_dir + strTime + "_" + std::to_string(index) + (isFmp4() ? _fmp4_seg_ext : ".ts"); segment_path = _path_prefix + "/" + segment_name; if (isLive()) { // 直播 diff --git a/src/Record/HlsMakerImp.h b/src/Record/HlsMakerImp.h index aa1b9efe..d1af9a07 100644 --- a/src/Record/HlsMakerImp.h +++ b/src/Record/HlsMakerImp.h @@ -22,7 +22,8 @@ namespace mediakit { class HlsMakerImp : public HlsMaker { public: HlsMakerImp(bool is_fmp4, const std::string &m3u8_file, const std::string ¶ms, uint32_t bufSize = 64 * 1024, - float seg_duration = 5, uint32_t seg_number = 3, bool seg_keep = false); + float seg_duration = 5, uint32_t seg_number = 3, bool seg_keep = false, + const std::string &fmp4_seg_ext = ".mp4"); ~HlsMakerImp() override; /** @@ -68,6 +69,7 @@ private: private: int _buf_size; std::string _params; + std::string _fmp4_seg_ext; std::string _path_hls; std::string _path_hls_delay; std::string _path_init; diff --git a/src/Record/HlsRecorder.h b/src/Record/HlsRecorder.h index 6ed4e78f..21992059 100644 --- a/src/Record/HlsRecorder.h +++ b/src/Record/HlsRecorder.h @@ -26,9 +26,10 @@ public: GET_CONFIG(bool, hlsKeep, Hls::kSegmentKeep); GET_CONFIG(uint32_t, hlsBufSize, Hls::kFileBufSize); GET_CONFIG(float, hlsDuration, Hls::kSegmentDuration); + GET_CONFIG(std::string, hlsFmp4SegExt, Hls::kFmp4SegExt); _option = option; - _hls = std::make_shared(is_fmp4, m3u8_file, params, hlsBufSize, hlsDuration, hlsNum, hlsKeep); + _hls = std::make_shared(is_fmp4, m3u8_file, params, hlsBufSize, hlsDuration, hlsNum, hlsKeep, hlsFmp4SegExt); // 清空上次的残余文件 [AUTO-TRANSLATED:e16122be] // Clear the residual files from the last time _hls->clearCache();