on_play鉴权回调到python层

This commit is contained in:
xia-chu
2025-12-02 20:21:41 +08:00
parent 9420f25b73
commit c496dbf51e
5 changed files with 75 additions and 10 deletions

View File

@@ -4,18 +4,23 @@ import mk_loader
def on_start():
mk_logger.log_info("on_start")
def on_exit():
mk_logger.log_info("on_exit")
def on_publish(type: str, info, invoker, sender) -> bool:
mk_logger.log_info(f"on_publish: {type}")
def on_publish(type: str, args: dict, invoker, sender: dict) -> bool:
mk_logger.log_info(f"on_publish, args: {type}, args: {args}, sender: {sender}")
# opt 控制转协议,请参考配置文件[protocol]下字段
opt = {
"enable_rtmp": "1"
}
# 响应推流鉴权结果
mk_loader.mk_publish_auth_invoker_do(invoker, "", opt);
mk_loader.publish_auth_invoker_do(invoker, "", opt);
# 返回True代表此事件被python拦截
return True
def on_play(args: dict, invoker, sender: dict) -> bool:
mk_logger.log_info(f"on_play, args: {args}, sender: {sender}")
# 响应播放鉴权结果
mk_loader.auth_invoker_do(invoker, "");
# 返回True代表此事件被python拦截
return True

View File

@@ -345,7 +345,7 @@ static inline string getPusherKey(const string &schema, const string &vhost, con
return schema + "/" + vhost + "/" + app + "/" + stream + "/" + MD5(dst_url).hexdigest();
}
static void fillSockInfo(Value& val, SockInfo* info) {
void fillSockInfo(Value& val, SockInfo* info) {
val["peer_ip"] = info->get_peer_ip();
val["peer_port"] = info->get_peer_port();
val["local_port"] = info->get_local_port();

View File

@@ -230,7 +230,7 @@ void do_http_hook(const string &url, const ArgsType &body, const function<void(c
void dumpMediaTuple(const MediaTuple &tuple, Json::Value& item);
static ArgsType make_json(const MediaInfo &args) {
ArgsType make_json(const MediaInfo &args) {
ArgsType body;
body["schema"] = args.schema;
if(!args.protocol.empty()){
@@ -397,6 +397,11 @@ void installWebHook() {
});
NoticeCenter::Instance().addListener(&web_hook_tag, Broadcast::kBroadcastMediaPlayed, [](BroadcastMediaPlayedArgs) {
#if defined(ENABLE_PYTHON)
if (PythonInvoker::Instance().on_play(args, invoker, sender)) {
return;
}
#endif
GET_CONFIG(string, hook_play, Hook::kOnPlay);
if (!hook_enable || hook_play.empty()) {
invoker("");

View File

@@ -1,17 +1,19 @@
#if defined(ENABLE_PYTHON)
#include "pyinvoker.h"
#include <chrono>
#include <cstdlib>
#include <iostream>
#include <string>
#include <type_traits>
#include "WebHook.h"
using namespace toolkit;
using namespace mediakit;
template <typename T>
auto to_python(const T &obj) -> typename std::enable_if<std::is_copy_constructible<T>::value, py::capsule>::type {
typename std::enable_if<std::is_copy_constructible<T>::value, py::capsule>::type to_python(const T &obj) {
static auto name_str = toolkit::demangle(typeid(T).name());
auto p = new toolkit::Any(std::make_shared<T>(obj));
return py::capsule(p, name_str.data(), [](PyObject *capsule) {
@@ -22,7 +24,7 @@ auto to_python(const T &obj) -> typename std::enable_if<std::is_copy_constructib
}
template <typename T>
auto to_python(const T &obj) -> typename std::enable_if<!std::is_copy_constructible<T>::value, py::capsule>::type {
typename std::enable_if<!std::is_copy_constructible<T>::value, py::capsule>::type to_python(const T &obj) {
static auto name_str = toolkit::demangle(typeid(T).name());
auto p = new toolkit::Any(std::shared_ptr<T>(const_cast<T *>(&obj), [](T *) {}));
return py::capsule(p, name_str.data(), [](PyObject *capsule) {
@@ -32,6 +34,39 @@ auto to_python(const T &obj) -> typename std::enable_if<!std::is_copy_constructi
});
}
extern ArgsType make_json(const MediaInfo &args);
extern void fillSockInfo(Json::Value & val, SockInfo* info);
static py::dict jsonToPython(const Json::Value &obj) {
py::dict ret;
if (obj.isObject()) {
for (auto it = obj.begin(); it != obj.end(); ++it) {
if (it->isNull()) {
// 忽略null修复wvp传null覆盖Protocol配置的问题
continue;
}
try {
auto str = (*it).asString();
ret[it.name().data()] = std::move(str);
} catch (std::exception &) {
WarnL << "Json is not convertible to string, key: " << it.name() << ", value: " << (*it);
}
}
}
return ret;
}
py::dict to_python(const MediaInfo &args) {
auto json = make_json(args);
return jsonToPython(json);
}
py::dict to_python(const SockInfo &info) {
Json::Value json;
fillSockInfo(json, const_cast<SockInfo *>(&info));
return jsonToPython(json);
}
template <typename T>
T &to_native(const py::capsule &cap) {
static auto name_str = toolkit::demangle(typeid(T).name());
@@ -56,7 +91,7 @@ PYBIND11_EMBEDDED_MODULE(mk_loader, m) {
py::gil_scoped_release release;
LoggerWrapper::printLog(::toolkit::getLogger(), lev, file, func, line, content);
});
m.def("mk_publish_auth_invoker_do", [](const py::capsule &cap, const std::string &err, const py::dict &opt) {
m.def("publish_auth_invoker_do", [](const py::capsule &cap, const std::string &err, const py::dict &opt) {
ProtocolOption option;
option.load(to_native(opt));
// 执行c++代码时释放gil锁
@@ -64,6 +99,12 @@ PYBIND11_EMBEDDED_MODULE(mk_loader, m) {
auto &invoker = to_native<Broadcast::PublishAuthInvoker>(cap);
invoker(err, option);
});
m.def("auth_invoker_do", [](const py::capsule &cap, const std::string &err) {
// 执行c++代码时释放gil锁
py::gil_scoped_release release;
auto &invoker = to_native<Broadcast::AuthInvoker>(cap);
invoker(err);
});
}
namespace mediakit {
@@ -137,6 +178,9 @@ void PythonInvoker::load(const std::string &module_name) {
if (hasattr(_module, "on_publish")) {
_on_publish = _module.attr("on_publish");
}
if (hasattr(_module, "on_play")) {
_on_play = _module.attr("on_play");
}
} catch (py::error_already_set &e) {
PrintE("Python exception:%s", e.what());
}
@@ -150,6 +194,14 @@ bool PythonInvoker::on_publish(BroadcastMediaPublishArgs) {
return _on_publish(getOriginTypeString(type), to_python(args), to_python(invoker), to_python(sender)).cast<bool>();
}
bool PythonInvoker::on_play(BroadcastMediaPlayedArgs) {
py::gil_scoped_acquire gil; // 确保在 Python 调用期间持有 GIL
if (!_on_play) {
return false;
}
return _on_play(to_python(args), to_python(invoker), to_python(sender)).cast<bool>();
}
} // namespace mediakit
#endif

View File

@@ -24,6 +24,7 @@ public:
void load(const std::string &module_name);
bool on_publish(BroadcastMediaPublishArgs);
bool on_play(BroadcastMediaPlayedArgs);
private:
PythonInvoker();
@@ -38,6 +39,8 @@ private:
py::object _on_exit;
// 推流鉴权
py::object _on_publish;
// 播放鉴权
py::object _on_play;
};
} // namespace mediakit