mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-26 04:31:37 +08:00
添加 hls ts 切片录制完成通知
This commit is contained in:
parent
a024c51536
commit
188e087fc2
@ -53,6 +53,7 @@ const string kOnRtspAuth = HOOK_FIELD"on_rtsp_auth";
|
|||||||
const string kOnStreamChanged = HOOK_FIELD"on_stream_changed";
|
const string kOnStreamChanged = HOOK_FIELD"on_stream_changed";
|
||||||
const string kOnStreamNotFound = HOOK_FIELD"on_stream_not_found";
|
const string kOnStreamNotFound = HOOK_FIELD"on_stream_not_found";
|
||||||
const string kOnRecordMp4 = HOOK_FIELD"on_record_mp4";
|
const string kOnRecordMp4 = HOOK_FIELD"on_record_mp4";
|
||||||
|
const string kOnRecordTs = HOOK_FIELD"on_record_ts";
|
||||||
const string kOnShellLogin = HOOK_FIELD"on_shell_login";
|
const string kOnShellLogin = HOOK_FIELD"on_shell_login";
|
||||||
const string kOnStreamNoneReader = HOOK_FIELD"on_stream_none_reader";
|
const string kOnStreamNoneReader = HOOK_FIELD"on_stream_none_reader";
|
||||||
const string kOnHttpAccess = HOOK_FIELD"on_http_access";
|
const string kOnHttpAccess = HOOK_FIELD"on_http_access";
|
||||||
@ -70,6 +71,7 @@ onceToken token([](){
|
|||||||
mINI::Instance()[kOnStreamChanged] = "https://127.0.0.1/index/hook/on_stream_changed";
|
mINI::Instance()[kOnStreamChanged] = "https://127.0.0.1/index/hook/on_stream_changed";
|
||||||
mINI::Instance()[kOnStreamNotFound] = "https://127.0.0.1/index/hook/on_stream_not_found";
|
mINI::Instance()[kOnStreamNotFound] = "https://127.0.0.1/index/hook/on_stream_not_found";
|
||||||
mINI::Instance()[kOnRecordMp4] = "https://127.0.0.1/index/hook/on_record_mp4";
|
mINI::Instance()[kOnRecordMp4] = "https://127.0.0.1/index/hook/on_record_mp4";
|
||||||
|
mINI::Instance()[kOnRecordTs] = "https://127.0.0.1/index/hook/on_record_ts";
|
||||||
mINI::Instance()[kOnShellLogin] = "https://127.0.0.1/index/hook/on_shell_login";
|
mINI::Instance()[kOnShellLogin] = "https://127.0.0.1/index/hook/on_shell_login";
|
||||||
mINI::Instance()[kOnStreamNoneReader] = "https://127.0.0.1/index/hook/on_stream_none_reader";
|
mINI::Instance()[kOnStreamNoneReader] = "https://127.0.0.1/index/hook/on_stream_none_reader";
|
||||||
mINI::Instance()[kOnHttpAccess] = "https://127.0.0.1/index/hook/on_http_access";
|
mINI::Instance()[kOnHttpAccess] = "https://127.0.0.1/index/hook/on_http_access";
|
||||||
@ -190,6 +192,7 @@ void installWebHook(){
|
|||||||
GET_CONFIG(string,hook_stream_chaned,Hook::kOnStreamChanged);
|
GET_CONFIG(string,hook_stream_chaned,Hook::kOnStreamChanged);
|
||||||
GET_CONFIG(string,hook_stream_not_found,Hook::kOnStreamNotFound);
|
GET_CONFIG(string,hook_stream_not_found,Hook::kOnStreamNotFound);
|
||||||
GET_CONFIG(string,hook_record_mp4,Hook::kOnRecordMp4);
|
GET_CONFIG(string,hook_record_mp4,Hook::kOnRecordMp4);
|
||||||
|
GET_CONFIG(string,hook_record_ts,Hook::kOnRecordTs);
|
||||||
GET_CONFIG(string,hook_shell_login,Hook::kOnShellLogin);
|
GET_CONFIG(string,hook_shell_login,Hook::kOnShellLogin);
|
||||||
GET_CONFIG(string,hook_stream_none_reader,Hook::kOnStreamNoneReader);
|
GET_CONFIG(string,hook_stream_none_reader,Hook::kOnStreamNoneReader);
|
||||||
GET_CONFIG(string,hook_http_access,Hook::kOnHttpAccess);
|
GET_CONFIG(string,hook_http_access,Hook::kOnHttpAccess);
|
||||||
@ -361,6 +364,25 @@ void installWebHook(){
|
|||||||
});
|
});
|
||||||
#endif //ENABLE_MP4
|
#endif //ENABLE_MP4
|
||||||
|
|
||||||
|
NoticeCenter::Instance().addListener(nullptr, Broadcast::kBroadcastRecordTs, [](BroadcastRecordTsArgs) {
|
||||||
|
if (!hook_enable || hook_record_ts.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ArgsType body;
|
||||||
|
body["start_time"] = (Json::UInt64)info.ui64StartedTime;
|
||||||
|
body["time_len"] = (Json::UInt64)info.ui64TimeLen;
|
||||||
|
body["file_size"] = (Json::UInt64)info.ui64FileSize;
|
||||||
|
body["file_path"] = info.strFilePath;
|
||||||
|
body["file_name"] = info.strFileName;
|
||||||
|
body["folder"] = info.strFolder;
|
||||||
|
body["url"] = info.strUrl;
|
||||||
|
body["app"] = info.strAppName;
|
||||||
|
body["stream"] = info.strStreamId;
|
||||||
|
body["vhost"] = info.strVhost;
|
||||||
|
// 执行 hook
|
||||||
|
do_http_hook(hook_record_ts, body, nullptr);
|
||||||
|
});
|
||||||
|
|
||||||
NoticeCenter::Instance().addListener(nullptr,Broadcast::kBroadcastShellLogin,[](BroadcastShellLoginArgs){
|
NoticeCenter::Instance().addListener(nullptr,Broadcast::kBroadcastShellLogin,[](BroadcastShellLoginArgs){
|
||||||
if(!hook_enable || hook_shell_login.empty() || sender.get_peer_ip() == "127.0.0.1"){
|
if(!hook_enable || hook_shell_login.empty() || sender.get_peer_ip() == "127.0.0.1"){
|
||||||
invoker("");
|
invoker("");
|
||||||
|
@ -40,6 +40,7 @@ bool loadIniConfig(const char *ini_path){
|
|||||||
namespace Broadcast {
|
namespace Broadcast {
|
||||||
const string kBroadcastMediaChanged = "kBroadcastMediaChanged";
|
const string kBroadcastMediaChanged = "kBroadcastMediaChanged";
|
||||||
const string kBroadcastRecordMP4 = "kBroadcastRecordMP4";
|
const string kBroadcastRecordMP4 = "kBroadcastRecordMP4";
|
||||||
|
const string kBroadcastRecordTs = "kBroadcastRecoredTs";
|
||||||
const string kBroadcastHttpRequest = "kBroadcastHttpRequest";
|
const string kBroadcastHttpRequest = "kBroadcastHttpRequest";
|
||||||
const string kBroadcastHttpAccess = "kBroadcastHttpAccess";
|
const string kBroadcastHttpAccess = "kBroadcastHttpAccess";
|
||||||
const string kBroadcastOnGetRtspRealm = "kBroadcastOnGetRtspRealm";
|
const string kBroadcastOnGetRtspRealm = "kBroadcastOnGetRtspRealm";
|
||||||
|
@ -60,6 +60,10 @@ extern const string kBroadcastMediaChanged;
|
|||||||
extern const string kBroadcastRecordMP4;
|
extern const string kBroadcastRecordMP4;
|
||||||
#define BroadcastRecordMP4Args const MP4Info &info
|
#define BroadcastRecordMP4Args const MP4Info &info
|
||||||
|
|
||||||
|
// 录制 ts 文件后广播
|
||||||
|
extern const string kBroadcastRecordTs;
|
||||||
|
#define BroadcastRecordTsArgs const TsInfo &info
|
||||||
|
|
||||||
//收到http api请求广播
|
//收到http api请求广播
|
||||||
extern const string kBroadcastHttpRequest;
|
extern const string kBroadcastHttpRequest;
|
||||||
#define BroadcastHttpRequestArgs const Parser &parser,const HttpSession::HttpResponseInvoker &invoker,bool &consumed,SockInfo &sender
|
#define BroadcastHttpRequestArgs const Parser &parser,const HttpSession::HttpResponseInvoker &invoker,bool &consumed,SockInfo &sender
|
||||||
|
@ -120,6 +120,11 @@ void HlsMaker::flushLastSegment(uint32_t timestamp, bool eof){
|
|||||||
delOldSegment();
|
delOldSegment();
|
||||||
makeIndexFile(eof);
|
makeIndexFile(eof);
|
||||||
_last_file_name.clear();
|
_last_file_name.clear();
|
||||||
|
|
||||||
|
onFlushLastSegment(seg_dur);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HlsMaker::onFlushLastSegment(uint32_t) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HlsMaker::isLive() {
|
bool HlsMaker::isLive() {
|
||||||
|
@ -22,6 +22,20 @@ using namespace toolkit;
|
|||||||
|
|
||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
|
class TsInfo {
|
||||||
|
public:
|
||||||
|
time_t ui64StartedTime; // GMT 标准时间,单位秒
|
||||||
|
time_t ui64TimeLen; // 录像长度,单位毫秒
|
||||||
|
off_t ui64FileSize; // 文件大小,单位 BYTE
|
||||||
|
string strFilePath; // 文件路径
|
||||||
|
string strFileName; // 文件名称
|
||||||
|
string strFolder; // 文件夹路径
|
||||||
|
string strUrl; // 播放路径
|
||||||
|
string strAppName; // 应用名称
|
||||||
|
string strStreamId; // 流 ID
|
||||||
|
string strVhost; // vhost
|
||||||
|
};
|
||||||
|
|
||||||
class HlsMaker {
|
class HlsMaker {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@ -85,6 +99,12 @@ protected:
|
|||||||
*/
|
*/
|
||||||
void flushLastSegment(uint32_t timestamp, bool eof = false);
|
void flushLastSegment(uint32_t timestamp, bool eof = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上一个 ts 切片写入完成, 可在这里进行通知处理
|
||||||
|
* @param duration 上一个 ts 切片的时长, 单位为毫秒
|
||||||
|
*/
|
||||||
|
virtual void onFlushLastSegment(uint32_t duration);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* 生成m3u8文件
|
* 生成m3u8文件
|
||||||
|
@ -8,7 +8,10 @@
|
|||||||
* may be found in the AUTHORS file in the root of the source tree.
|
* may be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <ctime>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include "HlsMakerImp.h"
|
#include "HlsMakerImp.h"
|
||||||
|
#include "Thread/WorkThreadPool.h"
|
||||||
#include "Util/util.h"
|
#include "Util/util.h"
|
||||||
#include "Util/uv_errno.h"
|
#include "Util/uv_errno.h"
|
||||||
|
|
||||||
@ -28,6 +31,8 @@ HlsMakerImp::HlsMakerImp(const string &m3u8_file,
|
|||||||
_file_buf.reset(new char[bufSize], [](char *ptr) {
|
_file_buf.reset(new char[bufSize], [](char *ptr) {
|
||||||
delete[] ptr;
|
delete[] ptr;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_info.strFolder = _path_prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
HlsMakerImp::~HlsMakerImp() {
|
HlsMakerImp::~HlsMakerImp() {
|
||||||
@ -59,6 +64,12 @@ string HlsMakerImp::onOpenSegment(int index) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_file = makeFile(segment_path, true);
|
_file = makeFile(segment_path, true);
|
||||||
|
|
||||||
|
_info.ui64StartedTime = ::time(NULL);
|
||||||
|
_info.strFileName = segment_name;
|
||||||
|
_info.strFilePath = segment_path;
|
||||||
|
_info.strUrl = _info.strAppName + "/" + _info.strStreamId + "/" + segment_name;
|
||||||
|
|
||||||
if (!_file) {
|
if (!_file) {
|
||||||
WarnL << "create file failed," << segment_path << " " << get_uv_errmsg();
|
WarnL << "create file failed," << segment_path << " " << get_uv_errmsg();
|
||||||
}
|
}
|
||||||
@ -97,6 +108,17 @@ void HlsMakerImp::onWriteHls(const char *data, int len) {
|
|||||||
//DebugL << "\r\n" << string(data,len);
|
//DebugL << "\r\n" << string(data,len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HlsMakerImp::onFlushLastSegment(uint32_t duration) {
|
||||||
|
auto info = _info;
|
||||||
|
info.ui64TimeLen = duration;
|
||||||
|
WorkThreadPool::Instance().getExecutor()->async([info]() {
|
||||||
|
struct stat fileData;
|
||||||
|
stat(info.strFilePath.data(), &fileData);
|
||||||
|
const_cast<TsInfo&>(info).ui64FileSize = fileData.st_size;
|
||||||
|
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastRecordTs, info);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<FILE> HlsMakerImp::makeFile(const string &file, bool setbuf) {
|
std::shared_ptr<FILE> HlsMakerImp::makeFile(const string &file, bool setbuf) {
|
||||||
auto file_buf = _file_buf;
|
auto file_buf = _file_buf;
|
||||||
@ -113,6 +135,9 @@ std::shared_ptr<FILE> HlsMakerImp::makeFile(const string &file, bool setbuf) {
|
|||||||
|
|
||||||
void HlsMakerImp::setMediaSource(const string &vhost, const string &app, const string &stream_id) {
|
void HlsMakerImp::setMediaSource(const string &vhost, const string &app, const string &stream_id) {
|
||||||
_media_src = std::make_shared<HlsMediaSource>(vhost, app, stream_id);
|
_media_src = std::make_shared<HlsMediaSource>(vhost, app, stream_id);
|
||||||
|
_info.strAppName = app;
|
||||||
|
_info.strStreamId = stream_id;
|
||||||
|
_info.strVhost = vhost;
|
||||||
}
|
}
|
||||||
|
|
||||||
HlsMediaSource::Ptr HlsMakerImp::getMediaSource() const {
|
HlsMediaSource::Ptr HlsMakerImp::getMediaSource() const {
|
||||||
|
@ -54,6 +54,7 @@ protected:
|
|||||||
void onDelSegment(int index) override;
|
void onDelSegment(int index) override;
|
||||||
void onWriteSegment(const char *data, int len) override;
|
void onWriteSegment(const char *data, int len) override;
|
||||||
void onWriteHls(const char *data, int len) override;
|
void onWriteHls(const char *data, int len) override;
|
||||||
|
void onFlushLastSegment(uint32_t duration) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<FILE> makeFile(const string &file,bool setbuf = false);
|
std::shared_ptr<FILE> makeFile(const string &file,bool setbuf = false);
|
||||||
@ -66,6 +67,7 @@ private:
|
|||||||
std::shared_ptr<FILE> _file;
|
std::shared_ptr<FILE> _file;
|
||||||
std::shared_ptr<char> _file_buf;
|
std::shared_ptr<char> _file_buf;
|
||||||
HlsMediaSource::Ptr _media_src;
|
HlsMediaSource::Ptr _media_src;
|
||||||
|
TsInfo _info;
|
||||||
map<int /*index*/,string/*file_path*/> _segment_file_paths;
|
map<int /*index*/,string/*file_path*/> _segment_file_paths;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user