From c496dbf51ef9e67123f9828375ea8ed79ab77d32 Mon Sep 17 00:00:00 2001 From: xia-chu <771730766@qq.com> Date: Tue, 2 Dec 2025 20:21:41 +0800 Subject: [PATCH] =?UTF-8?q?on=5Fplay=E9=89=B4=E6=9D=83=E5=9B=9E=E8=B0=83?= =?UTF-8?q?=E5=88=B0python=E5=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- python/mk_plugin.py | 15 ++++++++---- server/WebApi.cpp | 2 +- server/WebHook.cpp | 7 +++++- server/pyinvoker.cpp | 58 +++++++++++++++++++++++++++++++++++++++++--- server/pyinvoker.h | 3 +++ 5 files changed, 75 insertions(+), 10 deletions(-) diff --git a/python/mk_plugin.py b/python/mk_plugin.py index d7b45032..8d4970b5 100644 --- a/python/mk_plugin.py +++ b/python/mk_plugin.py @@ -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 diff --git a/server/WebApi.cpp b/server/WebApi.cpp index 82f32197..a822114a 100755 --- a/server/WebApi.cpp +++ b/server/WebApi.cpp @@ -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(); diff --git a/server/WebHook.cpp b/server/WebHook.cpp index 236cd1c7..516cd48c 100755 --- a/server/WebHook.cpp +++ b/server/WebHook.cpp @@ -230,7 +230,7 @@ void do_http_hook(const string &url, const ArgsType &body, const function #include #include #include #include +#include "WebHook.h" using namespace toolkit; using namespace mediakit; template -auto to_python(const T &obj) -> typename std::enable_if::value, py::capsule>::type { +typename std::enable_if::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(obj)); return py::capsule(p, name_str.data(), [](PyObject *capsule) { @@ -22,7 +24,7 @@ auto to_python(const T &obj) -> typename std::enable_if -auto to_python(const T &obj) -> typename std::enable_if::value, py::capsule>::type { +typename std::enable_if::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(const_cast(&obj), [](T *) {})); return py::capsule(p, name_str.data(), [](PyObject *capsule) { @@ -32,6 +34,39 @@ auto to_python(const T &obj) -> typename std::enable_ifisNull()) { + // 忽略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(&info)); + return jsonToPython(json); +} + template 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(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(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 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(); +} + } // namespace mediakit #endif diff --git a/server/pyinvoker.h b/server/pyinvoker.h index 04f266b7..185fba7e 100644 --- a/server/pyinvoker.h +++ b/server/pyinvoker.h @@ -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