AI automatically translates all comments in the code into English (#3917)

This commit is contained in:
alex
2024-09-19 14:53:50 +08:00
committed by GitHub
parent 046de691cb
commit 4152dcd409
279 changed files with 10602 additions and 3038 deletions

View File

@@ -90,7 +90,8 @@ static onceToken token([]() {
}//namespace API
using HttpApi = function<void(const Parser &parser, const HttpSession::HttpResponseInvoker &invoker, SockInfo &sender)>;
//http api列表
// http api列表 [AUTO-TRANSLATED:a05e9d9d]
// http api list
static map<string, HttpApi, StrCaseCompare> s_map_api;
static void responseApi(const Json::Value &res, const HttpSession::HttpResponseInvoker &invoker){
@@ -118,7 +119,8 @@ static HttpApi toApi(const function<void(API_ARGS_MAP_ASYNC)> &cb) {
Json::Value val;
val["code"] = API::Success;
//参数解析成map
// 参数解析成map [AUTO-TRANSLATED:20e11ff3]
// Parse parameters into a map
auto args = getAllArgs(parser);
cb(sender, headerOut, ArgsMap(parser, args), val, invoker);
};
@@ -143,7 +145,8 @@ static HttpApi toApi(const function<void(API_ARGS_JSON_ASYNC)> &cb) {
if (parser["Content-Type"].find("application/json") == string::npos) {
throw InvalidArgsException("该接口只支持json格式的请求");
}
//参数解析成json对象然后处理
// 参数解析成json对象然后处理 [AUTO-TRANSLATED:6f23397b]
// Parse parameters into a JSON object and then process
Json::Value args;
Json::Reader reader;
reader.parse(parser.content(), args);
@@ -203,7 +206,8 @@ void api_regist(const string &api_path, const function<void(API_ARGS_STRING_ASYN
s_map_api.emplace(api_path, toApi(func));
}
//获取HTTP请求中url参数、content参数
// 获取HTTP请求中url参数、content参数 [AUTO-TRANSLATED:d161a1e1]
// Get URL parameters and content parameters from the HTTP request
static ApiArgsType getAllArgs(const Parser &parser) {
ApiArgsType allArgs;
if (parser["Content-Type"].find("application/x-www-form-urlencoded") == 0) {
@@ -245,21 +249,25 @@ static void *web_api_tag = nullptr;
static inline void addHttpListener(){
GET_CONFIG(bool, api_debug, API::kApiDebug);
//注册监听kBroadcastHttpRequest事件
// 注册监听kBroadcastHttpRequest事件 [AUTO-TRANSLATED:4af22c90]
// Register to listen for the kBroadcastHttpRequest event
NoticeCenter::Instance().addListener(&web_api_tag, Broadcast::kBroadcastHttpRequest, [](BroadcastHttpRequestArgs) {
auto it = s_map_api.find(parser.url());
if (it == s_map_api.end()) {
return;
}
//该api已被消费
// 该api已被消费 [AUTO-TRANSLATED:db0872fc]
// This API has been consumed
consumed = true;
if(api_debug){
auto newInvoker = [invoker, parser](int code, const HttpSession::KeyValue &headerOut, const HttpBody::Ptr &body) {
//body默认为空
// body默认为空 [AUTO-TRANSLATED:4fd4ecc8]
// The body is empty by default
ssize_t size = 0;
if (body && body->remainSize()) {
//有body获取body大小
// 有body获取body大小 [AUTO-TRANSLATED:ab1c417d]
// If there is a body, get the body size
size = body->remainSize();
}
@@ -362,17 +370,21 @@ public:
}
};
//拉流代理器列表
// 拉流代理器列表 [AUTO-TRANSLATED:6dcfb11f]
// Pull stream proxy list
static ServiceController<PlayerProxy> s_player_proxy;
//推流代理器列表
// 推流代理器列表 [AUTO-TRANSLATED:539a1bcf]
// Push stream proxy list
static ServiceController<PusherProxy> s_pusher_proxy;
//FFmpeg拉流代理器列表
// FFmpeg拉流代理器列表 [AUTO-TRANSLATED:4bdedf10]
// FFmpeg pull stream proxy list
static ServiceController<FFmpegSource> s_ffmpeg_src;
#if defined(ENABLE_RTPPROXY)
//rtp服务器列表
// rtp服务器列表 [AUTO-TRANSLATED:2e362a8c]
// RTP server list
static ServiceController<RtpServer> s_rtp_server;
#endif
@@ -418,7 +430,8 @@ Value makeMediaSourceJson(MediaSource &media){
item["originSock"] = Json::nullValue;
}
//getLossRate有线程安全问题使用getMediaInfo接口才能获取丢包率getMediaList接口将忽略丢包率
// getLossRate有线程安全问题使用getMediaInfo接口才能获取丢包率getMediaList接口将忽略丢包率 [AUTO-TRANSLATED:b2e927c6]
// getLossRate has thread safety issues; use the getMediaInfo interface to get the packet loss rate; the getMediaList interface will ignore the packet loss rate
auto current_thread = false;
try { current_thread = media.getOwnerPoller()->isCurrentThread();} catch (...) {}
float last_loss = -1;
@@ -430,7 +443,8 @@ Value makeMediaSourceJson(MediaSource &media){
obj["ready"] = track->ready();
obj["codec_type"] = codec_type;
if (current_thread) {
//rtp推流只有一个统计器但是可能有多个track如果短时间多次获取间隔丢包率第二次会获取为-1
// rtp推流只有一个统计器但是可能有多个track如果短时间多次获取间隔丢包率第二次会获取为-1 [AUTO-TRANSLATED:5bfbc951]
// RTP push stream has only one statistics, but may have multiple tracks. If you get the interval packet loss rate multiple times in a short time, the second time will get -1
auto loss = media.getLossRate(codec_type);
if (loss == -1) {
loss = last_loss;
@@ -477,7 +491,8 @@ Value makeMediaSourceJson(MediaSource &media){
uint16_t openRtpServer(uint16_t local_port, const mediakit::MediaTuple &tuple, int tcp_mode, const string &local_ip, bool re_use_port, uint32_t ssrc, int only_track, bool multiplex) {
auto key = tuple.shortUrl();
if (s_rtp_server.find(key)) {
//为了防止RtpProcess所有权限混乱的问题不允许重复添加相同的key
// 为了防止RtpProcess所有权限混乱的问题不允许重复添加相同的key [AUTO-TRANSLATED:06c7b14c]
// To prevent the problem of all permissions being messed up in RtpProcess, duplicate keys are not allowed to be added
return 0;
}
@@ -485,11 +500,13 @@ uint16_t openRtpServer(uint16_t local_port, const mediakit::MediaTuple &tuple, i
server->start(local_port, local_ip.c_str(), tuple, (RtpServer::TcpMode)tcp_mode, re_use_port, ssrc, only_track, multiplex);
});
server->setOnDetach([key](const SockException &ex) {
//设置rtp超时移除事件
// 设置rtp超时移除事件 [AUTO-TRANSLATED:98d42cf3]
// Set RTP timeout removal event
s_rtp_server.erase(key);
});
//回复json
// 回复json [AUTO-TRANSLATED:0c443c6a]
// Reply JSON
return server->getPort();
}
@@ -543,7 +560,8 @@ void getStatisticJson(const function<void(Value &val)> &cb) {
for (auto &val : *thread_mem_info) {
(*obj)["threadMem"].append(val);
}
//触发回调
// 触发回调 [AUTO-TRANSLATED:08ea452d]
// Trigger callback
cb(*obj);
});
@@ -584,27 +602,33 @@ void addStreamProxy(const MediaTuple &tuple, const string &url, int retry_count,
const function<void(const SockException &ex, const string &key)> &cb) {
auto key = tuple.shortUrl();
if (s_player_proxy.find(key)) {
//已经在拉流了
// 已经在拉流了 [AUTO-TRANSLATED:e06c57d7]
// Already pulling stream
cb(SockException(Err_other, "This stream already exists"), key);
return;
}
//添加拉流代理
// 添加拉流代理 [AUTO-TRANSLATED:aa516f44]
// Add pull stream proxy
auto player = s_player_proxy.make(key, tuple, option, retry_count);
// 先透传拷贝参数
// 先透传拷贝参数 [AUTO-TRANSLATED:22b5605e]
// First pass-through copy parameters
for (auto &pr : args) {
(*player)[pr.first] = pr.second;
}
//指定RTP over TCP(播放rtsp时有效)
// 指定RTP over TCP(播放rtsp时有效) [AUTO-TRANSLATED:1a062656]
// Specify RTP over TCP (effective when playing RTSP)
(*player)[Client::kRtpType] = rtp_type;
if (timeout_sec > 0.1f) {
//播放握手超时时间
// 播放握手超时时间 [AUTO-TRANSLATED:5a29ae1f]
// Play handshake timeout
(*player)[Client::kTimeoutMS] = timeout_sec * 1000;
}
//开始播放,如果播放失败或者播放中止,将会自动重试若干次,默认一直重试
// 开始播放,如果播放失败或者播放中止,将会自动重试若干次,默认一直重试 [AUTO-TRANSLATED:ac8499e5]
// Start playing. If playback fails or is stopped, it will automatically retry several times, by default it will retry indefinitely
player->setPlayCallbackOnce([cb, key](const SockException &ex) {
if (ex) {
s_player_proxy.erase(key);
@@ -612,7 +636,8 @@ void addStreamProxy(const MediaTuple &tuple, const string &url, int retry_count,
cb(ex, key);
});
//被主动关闭拉流
// 被主动关闭拉流 [AUTO-TRANSLATED:41a19476]
// The pull stream was actively closed
player->setOnClose([key](const SockException &ex) {
s_player_proxy.erase(key);
});
@@ -636,23 +661,28 @@ void addStreamPusherProxy(const string &schema,
return;
}
if (s_pusher_proxy.find(key)) {
//已经在推流了
// 已经在推流了 [AUTO-TRANSLATED:81fcd202]
// Already pushing stream
cb(SockException(Err_success), key);
return;
}
//添加推流代理
// 添加推流代理 [AUTO-TRANSLATED:f9dbc76d]
// Add push stream proxy
auto pusher = s_pusher_proxy.make(key, src, retry_count);
//指定RTP over TCP(播放rtsp时有效)
// 指定RTP over TCP(播放rtsp时有效) [AUTO-TRANSLATED:1a062656]
// Specify RTP over TCP (effective when playing RTSP)
pusher->emplace(Client::kRtpType, rtp_type);
if (timeout_sec > 0.1f) {
//推流握手超时时间
// 推流握手超时时间 [AUTO-TRANSLATED:00762fc1]
// Push stream handshake timeout
pusher->emplace(Client::kTimeoutMS, timeout_sec * 1000);
}
//开始推流,如果推流失败或者推流中止,将会自动重试若干次,默认一直重试
// 开始推流,如果推流失败或者推流中止,将会自动重试若干次,默认一直重试 [AUTO-TRANSLATED:c8b95088]
// Start pushing stream. If the push stream fails or is stopped, it will automatically retry several times, by default it will retry indefinitely
pusher->setPushCallbackOnce([cb, key, url](const SockException &ex) {
if (ex) {
WarnL << "Push " << url << " failed, key: " << key << ", err: " << ex;
@@ -661,7 +691,8 @@ void addStreamPusherProxy(const string &schema,
cb(ex, key);
});
//被主动关闭推流
// 被主动关闭推流 [AUTO-TRANSLATED:bf216f82]
// Stream closed actively
pusher->setOnClose([key, url](const SockException &ex) {
WarnL << "Push " << url << " failed, key: " << key << ", err: " << ex;
s_pusher_proxy.erase(key);
@@ -674,13 +705,20 @@ void addStreamPusherProxy(const string &schema,
* 安装api接口
* 所有api都支持GET和POST两种方式
* POST方式参数支持application/json和application/x-www-form-urlencoded方式
* Install api interface
* All apis support GET and POST methods
* POST method parameters support application/json and application/x-www-form-urlencoded methods
* [AUTO-TRANSLATED:62e68c43]
*/
void installWebApi() {
addHttpListener();
GET_CONFIG(string,api_secret,API::kSecret);
//获取线程负载
//测试url http://127.0.0.1/index/api/getThreadsLoad
// 获取线程负载 [AUTO-TRANSLATED:3b0ece5c]
// Get thread load
// 测试url http://127.0.0.1/index/api/getThreadsLoad [AUTO-TRANSLATED:de1c93e7]
// Test url http://127.0.0.1/index/api/getThreadsLoad
api_regist("/index/api/getThreadsLoad", [](API_ARGS_MAP_ASYNC) {
CHECK_SECRET();
EventPollerPool::Instance().getExecutorDelay([invoker, headerOut](const vector<int> &vecDelay) {
@@ -698,8 +736,10 @@ void installWebApi() {
});
});
//获取后台工作线程负载
//测试url http://127.0.0.1/index/api/getWorkThreadsLoad
// 获取后台工作线程负载 [AUTO-TRANSLATED:6166e265]
// Get background worker thread load
// 测试url http://127.0.0.1/index/api/getWorkThreadsLoad [AUTO-TRANSLATED:209a8bc1]
// Test url http://127.0.0.1/index/api/getWorkThreadsLoad
api_regist("/index/api/getWorkThreadsLoad", [](API_ARGS_MAP_ASYNC) {
CHECK_SECRET();
WorkThreadPool::Instance().getExecutorDelay([invoker, headerOut](const vector<int> &vecDelay) {
@@ -717,8 +757,10 @@ void installWebApi() {
});
});
//获取服务器配置
//测试url http://127.0.0.1/index/api/getServerConfig
// 获取服务器配置 [AUTO-TRANSLATED:7dd2f3da]
// Get server configuration
// 测试url http://127.0.0.1/index/api/getServerConfig [AUTO-TRANSLATED:59cd0d71]
// Test url http://127.0.0.1/index/api/getServerConfig
api_regist("/index/api/getServerConfig",[](API_ARGS_MAP){
CHECK_SECRET();
Value obj;
@@ -728,9 +770,12 @@ void installWebApi() {
val["data"].append(obj);
});
//设置服务器配置
//测试url(比如关闭http api调试) http://127.0.0.1/index/api/setServerConfig?api.apiDebug=0
//你也可以通过http post方式传参可以通过application/x-www-form-urlencoded或application/json方式传参
// 设置服务器配置 [AUTO-TRANSLATED:3de7bd37]
// Set server configuration
// 测试url(比如关闭http api调试) http://127.0.0.1/index/api/setServerConfig?api.apiDebug=0 [AUTO-TRANSLATED:9471d218]
// Test url (e.g. disable http api debugging) http://127.0.0.1/index/api/setServerConfig?api.apiDebug=0
// 你也可以通过http post方式传参可以通过application/x-www-form-urlencoded或application/json方式传参 [AUTO-TRANSLATED:d493a7c0]
// You can also pass parameters through http post method, you can pass parameters through application/x-www-form-urlencoded or application/json methods
api_regist("/index/api/setServerConfig",[](API_ARGS_MAP){
CHECK_SECRET();
auto &ini = mINI::Instance();
@@ -738,12 +783,15 @@ void installWebApi() {
for (auto &pr : allArgs.args) {
if (ini.find(pr.first) == ini.end()) {
#if 1
//没有这个key
// 没有这个key [AUTO-TRANSLATED:d6855e02]
// This key does not exist
continue;
#else
// 新增配置选项,为了动态添加多个ffmpeg cmd 模板
// 新增配置选项,为了动态添加多个ffmpeg cmd 模板 [AUTO-TRANSLATED:0f977fcd]
// Add configuration options to dynamically add multiple ffmpeg cmd templates
ini[pr.first] = pr.second;
// 防止changed变化
// 防止changed变化 [AUTO-TRANSLATED:f8ad7e59]
// Prevent changed changes
continue;
#endif
}
@@ -755,7 +803,8 @@ void installWebApi() {
continue;
}
ini[pr.first] = pr.second;
//替换成功
// 替换成功 [AUTO-TRANSLATED:b5d4fec1]
// Replacement successful
++changed;
}
if (changed > 0) {
@@ -773,28 +822,36 @@ void installWebApi() {
}
};
//获取服务器api列表
//测试url http://127.0.0.1/index/api/getApiList
// 获取服务器api列表 [AUTO-TRANSLATED:e4c0dd9d]
// Get server api list
// 测试url http://127.0.0.1/index/api/getApiList [AUTO-TRANSLATED:df09e368]
// Test url http://127.0.0.1/index/api/getApiList
api_regist("/index/api/getApiList",[](API_ARGS_MAP){
s_get_api_list(API_ARGS_VALUE);
});
//获取服务器api列表
//测试url http://127.0.0.1/index/
// 获取服务器api列表 [AUTO-TRANSLATED:e4c0dd9d]
// Get server api list
// 测试url http://127.0.0.1/index/ [AUTO-TRANSLATED:76934dd3]
// Test url http://127.0.0.1/index/
api_regist("/index/",[](API_ARGS_MAP){
s_get_api_list(API_ARGS_VALUE);
});
#if !defined(_WIN32)
//重启服务器,只有Daemon方式才能重启否则是直接关闭
//测试url http://127.0.0.1/index/api/restartServer
// 重启服务器,只有Daemon方式才能重启否则是直接关闭 [AUTO-TRANSLATED:9d8a1c32]
// Restart server, only Daemon mode can restart, otherwise it will be closed directly!
// 测试url http://127.0.0.1/index/api/restartServer [AUTO-TRANSLATED:8beaaa8a]
// Test url http://127.0.0.1/index/api/restartServer
api_regist("/index/api/restartServer",[](API_ARGS_MAP){
CHECK_SECRET();
EventPollerPool::Instance().getPoller()->doDelayTask(1000,[](){
//尝试正常退出
// 尝试正常退出 [AUTO-TRANSLATED:93828d0f]
// Try to exit normally
::kill(getpid(), SIGINT);
//3秒后强制退出
// 3秒后强制退出 [AUTO-TRANSLATED:fdc82920]
// Force exit after 3 seconds
EventPollerPool::Instance().getPoller()->doDelayTask(3000,[](){
exit(0);
return 0;
@@ -805,10 +862,12 @@ void installWebApi() {
val["msg"] = "MediaServer will reboot in on 1 second";
});
#else
//增加Windows下的重启代码
// 增加Windows下的重启代码 [AUTO-TRANSLATED:dcba12d5]
// Add restart code for Windows
api_regist("/index/api/restartServer", [](API_ARGS_MAP) {
CHECK_SECRET();
//创建重启批处理脚本文件
// 创建重启批处理脚本文件 [AUTO-TRANSLATED:cc18c259]
// Create a restart batch script file
FILE *pf;
errno_t err = ::_wfopen_s(&pf, L"RestartServer.cmd", L"w"); //“w”如果该文件存在其内容将被覆盖
if (err == 0) {
@@ -824,7 +883,8 @@ void installWebApi() {
strcat(exeName, ext);
fprintf(pf, "@echo off\ntaskkill /f /im %s\nstart \"\" \"%s\"\ndel %%0", exeName, szExeName);
fclose(pf);
// 1秒后执行创建的批处理脚本
// 1秒后执行创建的批处理脚本 [AUTO-TRANSLATED:596dbca9]
// Execute the created batch script after 1 second
EventPollerPool::Instance().getPoller()->doDelayTask(1000, []() {
STARTUPINFO si;
PROCESS_INFORMATION pi;
@@ -859,27 +919,35 @@ void installWebApi() {
});
#endif//#if !defined(_WIN32)
//获取流列表,可选筛选参数
//测试url0(获取所有流) http://127.0.0.1/index/api/getMediaList
//测试url1(获取虚拟主机为"__defaultVost__"的流) http://127.0.0.1/index/api/getMediaList?vhost=__defaultVost__
//测试url2(获取rtsp类型的流) http://127.0.0.1/index/api/getMediaList?schema=rtsp
// 获取流列表,可选筛选参数 [AUTO-TRANSLATED:68ffc6b6]
// Get stream list, optional filtering parameters
// 测试url0(获取所有流) http://127.0.0.1/index/api/getMediaList [AUTO-TRANSLATED:434652ea]
// Test url0 (get all streams) http://127.0.0.1/index/api/getMediaList
// 测试url1(获取虚拟主机为"__defaultVost__"的流) http://127.0.0.1/index/api/getMediaList?vhost=__defaultVost__ [AUTO-TRANSLATED:5d9bd1ee]
// Test url1 (get streams with virtual host "__defaultVost__") http://127.0.0.1/index/api/getMediaList?vhost=__defaultVost__
// 测试url2(获取rtsp类型的流) http://127.0.0.1/index/api/getMediaList?schema=rtsp [AUTO-TRANSLATED:21c2c15d]
// Test url2 (get rtsp type streams) http://127.0.0.1/index/api/getMediaList?schema=rtsp
api_regist("/index/api/getMediaList",[](API_ARGS_MAP){
CHECK_SECRET();
//获取所有MediaSource列表
// 获取所有MediaSource列表 [AUTO-TRANSLATED:7bf16dc2]
// Get all MediaSource lists
MediaSource::for_each_media([&](const MediaSource::Ptr &media) {
val["data"].append(makeMediaSourceJson(*media));
}, allArgs["schema"], allArgs["vhost"], allArgs["app"], allArgs["stream"]);
});
//测试url http://127.0.0.1/index/api/isMediaOnline?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs
// 测试url http://127.0.0.1/index/api/isMediaOnline?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs [AUTO-TRANSLATED:126a75e8]
// Test url http://127.0.0.1/index/api/isMediaOnline?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs
api_regist("/index/api/isMediaOnline",[](API_ARGS_MAP){
CHECK_SECRET();
CHECK_ARGS("schema","vhost","app","stream");
val["online"] = (bool) (MediaSource::find(allArgs["schema"],allArgs["vhost"],allArgs["app"],allArgs["stream"]));
});
//获取媒体流播放器列表
//测试url http://127.0.0.1/index/api/getMediaPlayerList?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs
// 获取媒体流播放器列表 [AUTO-TRANSLATED:bcadf31c]
// Get media stream player list
// 测试url http://127.0.0.1/index/api/getMediaPlayerList?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs [AUTO-TRANSLATED:2aab7522]
// Test url http://127.0.0.1/index/api/getMediaPlayerList?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs
api_regist("/index/api/getMediaPlayerList",[](API_ARGS_MAP_ASYNC){
CHECK_SECRET();
CHECK_ARGS("schema", "vhost", "app", "stream");
@@ -922,7 +990,8 @@ void installWebApi() {
src->broadcastMessage(any);
});
//测试url http://127.0.0.1/index/api/getMediaInfo?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs
// 测试url http://127.0.0.1/index/api/getMediaInfo?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs [AUTO-TRANSLATED:9402e811]
// Test url http://127.0.0.1/index/api/getMediaInfo?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs
api_regist("/index/api/getMediaInfo",[](API_ARGS_MAP_ASYNC){
CHECK_SECRET();
CHECK_ARGS("schema","vhost","app","stream");
@@ -937,12 +1006,15 @@ void installWebApi() {
});
});
//主动关断流,包括关断拉流、推流
//测试url http://127.0.0.1/index/api/close_stream?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs&force=1
// 主动关断流,包括关断拉流、推流 [AUTO-TRANSLATED:80506955]
// Actively close the stream, including closing the pull stream and push stream
// 测试url http://127.0.0.1/index/api/close_stream?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs&force=1 [AUTO-TRANSLATED:c3831592]
// Test url http://127.0.0.1/index/api/close_stream?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs&force=1
api_regist("/index/api/close_stream",[](API_ARGS_MAP_ASYNC){
CHECK_SECRET();
CHECK_ARGS("schema","vhost","app","stream");
//踢掉推流器
// 踢掉推流器 [AUTO-TRANSLATED:61e39b14]
// Kick out the pusher
auto src = MediaSource::find(allArgs["schema"],
allArgs["vhost"],
allArgs["app"],
@@ -961,11 +1033,14 @@ void installWebApi() {
});
});
//批量主动关断流,包括关断拉流、推流
//测试url http://127.0.0.1/index/api/close_streams?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs&force=1
// 批量主动关断流,包括关断拉流、推流 [AUTO-TRANSLATED:5d180cd8]
// Batch actively close the stream, including closing the pull stream and push stream
// 测试url http://127.0.0.1/index/api/close_streams?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs&force=1 [AUTO-TRANSLATED:786933db]
// Test url http://127.0.0.1/index/api/close_streams?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs&force=1
api_regist("/index/api/close_streams",[](API_ARGS_MAP){
CHECK_SECRET();
//筛选命中个数
// 筛选命中个数 [AUTO-TRANSLATED:6db1e8c7]
// Filter hit count
int count_hit = 0;
int count_closed = 0;
list<MediaSource::Ptr> media_list;
@@ -984,9 +1059,12 @@ void installWebApi() {
val["count_closed"] = count_closed;
});
//获取所有Session列表信息
//可以根据本地端口和远端ip来筛选
//测试url(筛选某端口下的tcp会话) http://127.0.0.1/index/api/getAllSession?local_port=1935
// 获取所有Session列表信息 [AUTO-TRANSLATED:e785052d]
// Get all Session list information
// 可以根据本地端口和远端ip来筛选 [AUTO-TRANSLATED:4d4c9d61]
// You can filter by local port and remote ip
// 测试url(筛选某端口下的tcp会话) http://127.0.0.1/index/api/getAllSession?local_port=1935 [AUTO-TRANSLATED:ef845193]
// Test url (filter tcp session under a certain port) http://127.0.0.1/index/api/getAllSession?local_port=1935
api_regist("/index/api/getAllSession",[](API_ARGS_MAP){
CHECK_SECRET();
Value jsession;
@@ -1007,12 +1085,15 @@ void installWebApi() {
});
});
//断开tcp连接比如说可以断开rtsp、rtmp播放器等
//测试url http://127.0.0.1/index/api/kick_session?id=123456
// 断开tcp连接比如说可以断开rtsp、rtmp播放器等 [AUTO-TRANSLATED:9147ffec]
// Disconnect the tcp connection, for example, you can disconnect the rtsp, rtmp player, etc.
// 测试url http://127.0.0.1/index/api/kick_session?id=123456 [AUTO-TRANSLATED:c2880cb5]
// Test url http://127.0.0.1/index/api/kick_session?id=123456
api_regist("/index/api/kick_session",[](API_ARGS_MAP){
CHECK_SECRET();
CHECK_ARGS("id");
//踢掉tcp会话
// 踢掉tcp会话 [AUTO-TRANSLATED:f6f318bd]
// Kick out the tcp session
auto session = SessionMap::Instance().get(allArgs["id"]);
if(!session){
throw ApiRetException("can not find the target",API::OtherFailed);
@@ -1021,8 +1102,10 @@ void installWebApi() {
});
//批量断开tcp连接比如说可以断开rtsp、rtmp播放器等
//测试url http://127.0.0.1/index/api/kick_sessions?local_port=1935
// 批量断开tcp连接比如说可以断开rtsp、rtmp播放器等 [AUTO-TRANSLATED:fef59eb8]
// Batch disconnect tcp connections, for example, you can disconnect rtsp, rtmp players, etc.
// 测试url http://127.0.0.1/index/api/kick_sessions?local_port=1935 [AUTO-TRANSLATED:5891b482]
// Test url http://127.0.0.1/index/api/kick_sessions?local_port=1935
api_regist("/index/api/kick_sessions", [](API_ARGS_MAP) {
CHECK_SECRET();
uint16_t local_port = allArgs["local_port"].as<uint16_t>();
@@ -1038,7 +1121,8 @@ void installWebApi() {
return;
}
if (session->getIdentifier() == sender.getIdentifier()) {
// 忽略本http链接
// 忽略本http链接 [AUTO-TRANSLATED:9fb4bf76]
// Ignore this http link
return;
}
session_list.emplace_back(session);
@@ -1051,8 +1135,10 @@ void installWebApi() {
val["count_hit"] = (Json::UInt64)count_hit;
});
//动态添加rtsp/rtmp推流代理
//测试url http://127.0.0.1/index/api/addStreamPusherProxy?schema=rtmp&vhost=__defaultVhost__&app=proxy&stream=0&dst_url=rtmp://127.0.0.1/live/obs
// 动态添加rtsp/rtmp推流代理 [AUTO-TRANSLATED:2eb09bc9]
// Dynamically add rtsp/rtmp push stream proxy
// 测试url http://127.0.0.1/index/api/addStreamPusherProxy?schema=rtmp&vhost=__defaultVhost__&app=proxy&stream=0&dst_url=rtmp://127.0.0.1/live/obs [AUTO-TRANSLATED:25d7d4b0]
// Test url http://127.0.0.1/index/api/addStreamPusherProxy?schema=rtmp&vhost=__defaultVhost__&app=proxy&stream=0&dst_url=rtmp://127.0.0.1/live/obs
api_regist("/index/api/addStreamPusherProxy", [](API_ARGS_MAP_ASYNC) {
CHECK_SECRET();
CHECK_ARGS("schema", "vhost", "app", "stream", "dst_url");
@@ -1078,16 +1164,20 @@ void installWebApi() {
});
});
//关闭推流代理
//测试url http://127.0.0.1/index/api/delStreamPusherProxy?key=__defaultVhost__/proxy/0
// 关闭推流代理 [AUTO-TRANSLATED:91602b75]
// Close the push stream proxy
// 测试url http://127.0.0.1/index/api/delStreamPusherProxy?key=__defaultVhost__/proxy/0 [AUTO-TRANSLATED:2671206c]
// Test url http://127.0.0.1/index/api/delStreamPusherProxy?key=__defaultVhost__/proxy/0
api_regist("/index/api/delStreamPusherProxy", [](API_ARGS_MAP) {
CHECK_SECRET();
CHECK_ARGS("key");
val["data"]["flag"] = s_pusher_proxy.erase(allArgs["key"]) == 1;
});
//动态添加rtsp/rtmp拉流代理
//测试url http://127.0.0.1/index/api/addStreamProxy?vhost=__defaultVhost__&app=proxy&enable_rtsp=1&enable_rtmp=1&stream=0&url=rtmp://127.0.0.1/live/obs
// 动态添加rtsp/rtmp拉流代理 [AUTO-TRANSLATED:2616537c]
// Dynamically add rtsp/rtmp pull stream proxy
// 测试url http://127.0.0.1/index/api/addStreamProxy?vhost=__defaultVhost__&app=proxy&enable_rtsp=1&enable_rtmp=1&stream=0&url=rtmp://127.0.0.1/live/obs [AUTO-TRANSLATED:71ddce15]
// Test url http://127.0.0.1/index/api/addStreamProxy?vhost=__defaultVhost__&app=proxy&enable_rtsp=1&enable_rtmp=1&stream=0&url=rtmp://127.0.0.1/live/obs
api_regist("/index/api/addStreamProxy",[](API_ARGS_MAP_ASYNC){
CHECK_SECRET();
CHECK_ARGS("vhost","app","stream","url");
@@ -1123,8 +1213,10 @@ void installWebApi() {
});
});
//关闭拉流代理
//测试url http://127.0.0.1/index/api/delStreamProxy?key=__defaultVhost__/proxy/0
// 关闭拉流代理 [AUTO-TRANSLATED:5204f128]
// Close the pull stream proxy
// 测试url http://127.0.0.1/index/api/delStreamProxy?key=__defaultVhost__/proxy/0 [AUTO-TRANSLATED:2b0903ef]
// Test url http://127.0.0.1/index/api/delStreamProxy?key=__defaultVhost__/proxy/0
api_regist("/index/api/delStreamProxy",[](API_ARGS_MAP){
CHECK_SECRET();
CHECK_ARGS("key");
@@ -1140,7 +1232,8 @@ void installWebApi() {
const function<void(const SockException &ex, const string &key)> &cb) {
auto key = MD5(dst_url).hexdigest();
if (s_ffmpeg_src.find(key)) {
//已经在拉流了
// 已经在拉流了 [AUTO-TRANSLATED:e06c57d7]
// Already pulling
cb(SockException(Err_success), key);
return;
}
@@ -1159,8 +1252,10 @@ void installWebApi() {
});
};
//动态添加rtsp/rtmp拉流代理
//测试url http://127.0.0.1/index/api/addFFmpegSource?src_url=http://live.hkstv.hk.lxdns.com/live/hks2/playlist.m3u8&dst_url=rtmp://127.0.0.1/live/hks2&timeout_ms=10000
// 动态添加rtsp/rtmp拉流代理 [AUTO-TRANSLATED:2616537c]
// Dynamically add rtsp/rtmp pull stream proxy
// 测试url http://127.0.0.1/index/api/addFFmpegSource?src_url=http://live.hkstv.hk.lxdns.com/live/hks2/playlist.m3u8&dst_url=rtmp://127.0.0.1/live/hks2&timeout_ms=10000 [AUTO-TRANSLATED:501cdd89]
// // Test url http://127.0.0.1/index/api/addFFmpegSource?src_url=http://live.hkstv.hk.lxdns.com/live/hks2/playlist.m3u8&dst_url=rtmp://127.0.0.1/live/hks2&timeout_ms=10000
api_regist("/index/api/addFFmpegSource",[](API_ARGS_MAP_ASYNC){
CHECK_SECRET();
CHECK_ARGS("src_url","dst_url","timeout_ms");
@@ -1182,16 +1277,20 @@ void installWebApi() {
});
});
//关闭拉流代理
//测试url http://127.0.0.1/index/api/delFFmepgSource?key=key
// 关闭拉流代理 [AUTO-TRANSLATED:5204f128]
// Close the pull stream proxy
// 测试url http://127.0.0.1/index/api/delFFmepgSource?key=key [AUTO-TRANSLATED:ed6fa147]
// Test url http://127.0.0.1/index/api/delFFmepgSource?key=key
api_regist("/index/api/delFFmpegSource",[](API_ARGS_MAP){
CHECK_SECRET();
CHECK_ARGS("key");
val["data"]["flag"] = s_ffmpeg_src.erase(allArgs["key"]) == 1;
});
//新增http api下载可执行程序文件接口
//测试url http://127.0.0.1/index/api/downloadBin
// 新增http api下载可执行程序文件接口 [AUTO-TRANSLATED:d6e44e84]
// Add a new http api to download executable files
// 测试url http://127.0.0.1/index/api/downloadBin [AUTO-TRANSLATED:9525e834]
// Test url http://127.0.0.1/index/api/downloadBin
api_regist("/index/api/downloadBin",[](API_ARGS_MAP_ASYNC){
CHECK_SECRET();
invoker.responseFile(allArgs.parser.getHeader(), StrCaseMap(), exePath());
@@ -1234,12 +1333,14 @@ void installWebApi() {
auto tuple = MediaTuple { vhost, app, stream_id, "" };
auto tcp_mode = allArgs["tcp_mode"].as<int>();
if (allArgs["enable_tcp"].as<int>() && !tcp_mode) {
//兼容老版本请求新版本去除enable_tcp参数并新增tcp_mode参数
// 兼容老版本请求新版本去除enable_tcp参数并新增tcp_mode参数 [AUTO-TRANSLATED:3b6a5ab5]
// Compatible with old version requests, the new version removes the enable_tcp parameter and adds the tcp_mode parameter
tcp_mode = 1;
}
auto only_track = allArgs["only_track"].as<int>();
if (allArgs["only_audio"].as<bool>()) {
// 兼容老版本请求新版本去除only_audio参数并新增only_track参数
// 兼容老版本请求新版本去除only_audio参数并新增only_track参数 [AUTO-TRANSLATED:a7a40942]
// Compatible with old version requests, the new version removes the only_audio parameter and adds the only_track parameter
only_track = 1;
}
GET_CONFIG(std::string, local_ip, General::kListenIP)
@@ -1251,7 +1352,8 @@ void installWebApi() {
if (port == 0) {
throw InvalidArgsException("This stream already exists");
}
//回复json
// 回复json [AUTO-TRANSLATED:0c443c6a]
// Reply json
val["port"] = port;
});
@@ -1270,12 +1372,14 @@ void installWebApi() {
auto tuple = MediaTuple { vhost, app, stream_id, "" };
auto tcp_mode = allArgs["tcp_mode"].as<int>();
if (allArgs["enable_tcp"].as<int>() && !tcp_mode) {
// 兼容老版本请求新版本去除enable_tcp参数并新增tcp_mode参数
// 兼容老版本请求新版本去除enable_tcp参数并新增tcp_mode参数 [AUTO-TRANSLATED:b5f8f5df]
// Compatible with old version requests, the new version removes the enable_tcp parameter and adds the tcp_mode parameter
tcp_mode = 1;
}
auto only_track = allArgs["only_track"].as<int>();
if (allArgs["only_audio"].as<bool>()) {
// 兼容老版本请求新版本去除only_audio参数并新增only_track参数
// 兼容老版本请求新版本去除only_audio参数并新增only_track参数 [AUTO-TRANSLATED:a7a40942]
// Compatible with old version requests, the new version removes the only_audio parameter and adds the only_track parameter
only_track = 1;
}
std::string local_ip = "::";
@@ -1287,7 +1391,8 @@ void installWebApi() {
if (port == 0) {
throw InvalidArgsException("This stream already exists");
}
// 回复json
// 回复json [AUTO-TRANSLATED:e80815cd]
// Reply json
val["port"] = port;
});
@@ -1384,7 +1489,8 @@ void installWebApi() {
}
auto type = allArgs["type"].empty() ? (int)MediaSourceEvent::SendRtpArgs::kRtpPS : allArgs["type"].as<int>();
if (!allArgs["use_ps"].empty()) {
// 兼容之前的use_ps参数
// 兼容之前的use_ps参数 [AUTO-TRANSLATED:0193f489]
// Compatible with the previous use_ps parameter
type = allArgs["use_ps"].as<int>();
}
MediaSourceEvent::SendRtpArgs args;
@@ -1404,7 +1510,8 @@ void installWebApi() {
args.udp_rtcp_timeout = allArgs["udp_rtcp_timeout"];
args.recv_stream_id = allArgs["recv_stream_id"];
args.close_delay_ms = allArgs["close_delay_ms"];
// 记录发送流的app和vhost
// 记录发送流的app和vhost [AUTO-TRANSLATED:ee1b41d5]
// Record the app and vhost of the sending stream
args.recv_stream_app = allArgs["app"];
args.recv_stream_vhost = allArgs["vhost"];
src->getOwnerPoller()->async([=]() mutable {
@@ -1467,7 +1574,8 @@ void installWebApi() {
}
src->getOwnerPoller()->async([=]() mutable {
// ssrc如果为空关闭全部
// ssrc如果为空关闭全部 [AUTO-TRANSLATED:e0955dab]
// If ssrc is empty, close all
if (!src->stopSendRtp(allArgs["ssrc"])) {
val["code"] = API::OtherFailed;
val["msg"] = "stopSendRtp failed";
@@ -1489,7 +1597,8 @@ void installWebApi() {
if (!allArgs["app"].empty()) {
app = allArgs["app"];
}
//只是暂停流的检查流媒体服务器做为流负载服务收流就转发RTSP/RTMP有自己暂停协议
// 只是暂停流的检查流媒体服务器做为流负载服务收流就转发RTSP/RTMP有自己暂停协议 [AUTO-TRANSLATED:dda6ee31]
// Only pause the stream check, the media server acts as a stream load balancing service, receiving the stream and forwarding it, RTSP/RTMP has its own pause protocol
auto src = MediaSource::find(vhost, app, allArgs["stream_id"]);
auto process = src ? src->getRtpProcess() : nullptr;
if (process) {
@@ -1521,7 +1630,8 @@ void installWebApi() {
#endif//ENABLE_RTPPROXY
// 开始录制hls或MP4
// 开始录制hls或MP4 [AUTO-TRANSLATED:0818775e]
// Start recording hls or MP4
api_regist("/index/api/startRecord",[](API_ARGS_MAP_ASYNC){
CHECK_SECRET();
CHECK_ARGS("type","vhost","app","stream");
@@ -1540,7 +1650,8 @@ void installWebApi() {
});
});
//设置录像流播放速度
// 设置录像流播放速度 [AUTO-TRANSLATED:a8d82298]
// Set the playback speed of the recording stream
api_regist("/index/api/setRecordSpeed", [](API_ARGS_MAP_ASYNC) {
CHECK_SECRET();
CHECK_ARGS("schema", "vhost", "app", "stream", "speed");
@@ -1583,7 +1694,8 @@ void installWebApi() {
});
});
// 停止录制hls或MP4
// 停止录制hls或MP4 [AUTO-TRANSLATED:24d11a0c]
// Stop recording hls or MP4
api_regist("/index/api/stopRecord",[](API_ARGS_MAP_ASYNC){
CHECK_SECRET();
CHECK_ARGS("type","vhost","app","stream");
@@ -1603,7 +1715,8 @@ void installWebApi() {
});
});
// 获取hls或MP4录制状态
// 获取hls或MP4录制状态 [AUTO-TRANSLATED:a08a2f1a]
// Get the recording status of hls or MP4
api_regist("/index/api/isRecording",[](API_ARGS_MAP_ASYNC){
CHECK_SECRET();
CHECK_ARGS("type","vhost","app","stream");
@@ -1648,7 +1761,8 @@ void installWebApi() {
invoker(200, headerOut, val.toStyledString());
});
// 删除录像文件夹
// 删除录像文件夹 [AUTO-TRANSLATED:821aed07]
// Delete the recording folder
// http://127.0.0.1/index/api/deleteRecordDirectroy?vhost=__defaultVhost__&app=live&stream=ss&period=2020-01-01
api_regist("/index/api/deleteRecordDirectory", [](API_ARGS_MAP) {
CHECK_SECRET();
@@ -1661,10 +1775,12 @@ void installWebApi() {
bool recording = false;
auto name = allArgs["name"];
if (!name.empty()) {
// 删除指定文件
// 删除指定文件 [AUTO-TRANSLATED:e8ee7bfa]
// Delete the specified file
record_path += name;
} else {
// 删除文件夹,先判断该流是否正在录制中
// 删除文件夹,先判断该流是否正在录制中 [AUTO-TRANSLATED:9f124786]
// Delete the folder, first check if the stream is being recorded
auto src = MediaSource::find(allArgs["vhost"], allArgs["app"], allArgs["stream"]);
if (src && src->isRecording(Recorder::type_mp4)) {
recording = true;
@@ -1689,7 +1805,8 @@ void installWebApi() {
File::deleteEmptyDir(record_path);
});
//获取录像文件夹列表或mp4文件列表
// 获取录像文件夹列表或mp4文件列表 [AUTO-TRANSLATED:f7e299bc]
// Get the list of recording folders or mp4 files
//http://127.0.0.1/index/api/getMP4RecordFile?vhost=__defaultVhost__&app=live&stream=ss&period=2020-01
api_regist("/index/api/getMP4RecordFile", [](API_ARGS_MAP){
CHECK_SECRET();
@@ -1698,25 +1815,29 @@ void installWebApi() {
auto record_path = Recorder::getRecordPath(Recorder::type_mp4, tuple, allArgs["customized_path"]);
auto period = allArgs["period"];
//判断是获取mp4文件列表还是获取文件夹列表
// 判断是获取mp4文件列表还是获取文件夹列表 [AUTO-TRANSLATED:b9c86d2f]
// Determine whether to get the mp4 file list or the folder list
bool search_mp4 = period.size() == sizeof("2020-02-01") - 1;
if (search_mp4) {
record_path = record_path + period + "/";
}
Json::Value paths(arrayValue);
//这是筛选日期,获取文件夹列表
// 这是筛选日期,获取文件夹列表 [AUTO-TRANSLATED:786fa49d]
// This is to filter the date and get the folder list
File::scanDir(record_path, [&](const string &path, bool isDir) {
auto pos = path.rfind('/');
if (pos != string::npos) {
string relative_path = path.substr(pos + 1);
if (search_mp4) {
if (!isDir) {
//我们只收集mp4文件对文件夹不感兴趣
// 我们只收集mp4文件对文件夹不感兴趣 [AUTO-TRANSLATED:254d9f25]
// We only collect mp4 files, we are not interested in folders
paths.append(relative_path);
}
} else if (isDir && relative_path.find(period) == 0) {
//匹配到对应日期的文件夹
// 匹配到对应日期的文件夹 [AUTO-TRANSLATED:cd3d10b9]
// Match the folder for the corresponding date
paths.append(relative_path);
}
}
@@ -1736,24 +1857,29 @@ void installWebApi() {
GET_CONFIG(string, defaultSnap, API::kDefaultSnap);
if (!File::fileSize(snap_path)) {
if (!err_msg.empty() && (!s_snap_success_once || defaultSnap.empty())) {
//重来没截图成功过或者默认截图图片为空那么直接返回FFmpeg错误日志
// 重来没截图成功过或者默认截图图片为空那么直接返回FFmpeg错误日志 [AUTO-TRANSLATED:5bde510f]
// If the screenshot has never been successful or the default screenshot image is empty, then directly return the FFmpeg error log
headerOut["Content-Type"] = HttpFileManager::getContentType(".txt");
invoker.responseFile(headerIn, headerOut, err_msg, false, false);
return;
}
//截图成功过一次,那么认为配置无错误,截图失败时,返回预设默认图片
// 截图成功过一次,那么认为配置无错误,截图失败时,返回预设默认图片 [AUTO-TRANSLATED:ffe4d807]
// If the screenshot has been successful once, then it is considered that the configuration is error-free, and when the screenshot fails, the preset default image is returned
const_cast<string &>(snap_path) = File::absolutePath("", defaultSnap);
headerOut["Content-Type"] = HttpFileManager::getContentType(snap_path.data());
} else {
s_snap_success_once = true;
//之前生成的截图文件我们默认为jpeg格式
// 之前生成的截图文件我们默认为jpeg格式 [AUTO-TRANSLATED:5cc5c1ff]
// The previously generated screenshot file, we default to jpeg format
headerOut["Content-Type"] = HttpFileManager::getContentType(".jpeg");
}
//返回图片给http客户端
// 返回图片给http客户端 [AUTO-TRANSLATED:58a1f64e]
// Return image to http client
invoker.responseFile(headerIn, headerOut, snap_path);
};
//获取截图缓存或者实时截图
// 获取截图缓存或者实时截图 [AUTO-TRANSLATED:78e2fe1e]
// Get screenshot cache or real-time screenshot
//http://127.0.0.1/index/api/getSnap?url=rtmp://127.0.0.1/record/robot.mp4&timeout_sec=10&expire_sec=3
api_regist("/index/api/getSnap", [](API_ARGS_MAP_ASYNC){
CHECK_SECRET();
@@ -1767,49 +1893,61 @@ void installWebApi() {
File::scanDir(scan_path, [&](const string &path, bool isDir) {
if (isDir || !end_with(path, ".jpeg")) {
//忽略文件夹或其他类型的文件
// 忽略文件夹或其他类型的文件 [AUTO-TRANSLATED:3ecffcae]
// Ignore folders or other types of files
return true;
}
//找到截图
// 找到截图 [AUTO-TRANSLATED:b784cfec]
// Find screenshot
auto tm = findSubString(path.data() + scan_path.size(), nullptr, ".jpeg");
if (atoll(tm.data()) + expire_sec < time(NULL)) {
//截图已经过期,改名,以便再次请求时,可以返回老截图
// 截图已经过期,改名,以便再次请求时,可以返回老截图 [AUTO-TRANSLATED:94fac79b]
// Screenshot has expired, rename it so that it can be returned when requested again
rename(path.data(), new_snap.data());
have_old_snap = true;
return true;
}
//截图存在,且未过期,那么返回之
// 截图存在,且未过期,那么返回之 [AUTO-TRANSLATED:6f53d3d1]
// Screenshot exists and has not expired, so return it
res_old_snap = true;
responseSnap(path, allArgs.parser.getHeader(), invoker);
//中断遍历
// 中断遍历 [AUTO-TRANSLATED:7893aab3]
// Interrupt traversal
return false;
});
if (res_old_snap) {
//已经回复了旧的截图
// 已经回复了旧的截图 [AUTO-TRANSLATED:9051a3e6]
// Old screenshot has been replied
return;
}
//无截图或者截图已经过期
// 无截图或者截图已经过期 [AUTO-TRANSLATED:89c46415]
// No screenshot or screenshot has expired
if (!have_old_snap) {
//无过期截图,生成一个空文件,目的是顺便创建文件夹路径
//同时防止在FFmpeg生成截图途中不停的尝试调用该api多次启动FFmpeg进程
// 无过期截图,生成一个空文件,目的是顺便创建文件夹路径 [AUTO-TRANSLATED:bdbfdbcb]
// No expired screenshot, generate an empty file, the purpose is to create the folder path by the way
// 同时防止在FFmpeg生成截图途中不停的尝试调用该api多次启动FFmpeg进程 [AUTO-TRANSLATED:a04e1ee2]
// At the same time, prevent the FFmpeg process from being started multiple times by continuously trying to call this API during the FFmpeg screenshot generation process
auto file = File::create_file(new_snap, "wb");
if (file) {
fclose(file);
}
}
//启动FFmpeg进程开始截图生成临时文件截图成功后替换为正式文件
// 启动FFmpeg进程开始截图生成临时文件截图成功后替换为正式文件 [AUTO-TRANSLATED:7d589e3f]
// Start the FFmpeg process, start taking screenshots, generate temporary files, replace them with formal files after successful screenshots
auto new_snap_tmp = new_snap + ".tmp";
FFmpegSnap::makeSnap(allArgs["url"], new_snap_tmp, allArgs["timeout_sec"], [invoker, allArgs, new_snap, new_snap_tmp](bool success, const string &err_msg) {
if (!success) {
//生成截图失败,可能残留空文件
// 生成截图失败,可能残留空文件 [AUTO-TRANSLATED:c96a4468]
// Screenshot generation failed, there may be residual empty files
File::delete_file(new_snap_tmp);
} else {
//临时文件改成正式文件
// 临时文件改成正式文件 [AUTO-TRANSLATED:eca24dfd]
// Temporary file changed to formal file
File::delete_file(new_snap);
rename(new_snap_tmp.data(), new_snap.data());
}
@@ -1889,7 +2027,8 @@ void installWebApi() {
WebRtcPluginManager::Instance().negotiateSdp(session, type, *args, [invoker, offer, headerOut, location](const WebRtcInterface &exchanger) mutable {
auto &handler = const_cast<WebRtcInterface &>(exchanger);
try {
// 设置返回类型
// 设置返回类型 [AUTO-TRANSLATED:ffc2a31a]
// Set return type
headerOut["Content-Type"] = "application/sdp";
headerOut["Location"] = location + "?id=" + exchanger.getIdentifier() + "&token=" + exchanger.deleteRandStr();
invoker(201, headerOut, handler.getAnswerSdp(offer));
@@ -1938,17 +2077,22 @@ void installWebApi() {
CHECK_ARGS("vhost", "app", "stream", "file_path");
ProtocolOption option;
// mp4支持多track
// mp4支持多track [AUTO-TRANSLATED:b9688762]
// mp4 supports multiple tracks
option.max_track = 16;
// 默认解复用mp4不生成mp4
// 默认解复用mp4不生成mp4 [AUTO-TRANSLATED:11f2dcee]
// By default, demultiplexing mp4 does not generate mp4
option.enable_mp4 = false;
// 但是如果参数明确指定开启mp4, 那么也允许之
// 但是如果参数明确指定开启mp4, 那么也允许之 [AUTO-TRANSLATED:b143a9e3]
// But if the parameter explicitly specifies to enable mp4, then it is also allowed
option.load(allArgs);
// 强制无人观看时自动关闭
// 强制无人观看时自动关闭 [AUTO-TRANSLATED:f7c85948]
// Force automatic shutdown when no one is watching
option.auto_close = true;
auto tuple = MediaTuple{allArgs["vhost"], allArgs["app"], allArgs["stream"], ""};
auto reader = std::make_shared<MP4Reader>(tuple, allArgs["file_path"], option);
// sample_ms设置为0从配置文件加载file_repeat可以指定如果配置文件也指定循环解复用那么强制开启
// sample_ms设置为0从配置文件加载file_repeat可以指定如果配置文件也指定循环解复用那么强制开启 [AUTO-TRANSLATED:23e826b4]
// sample_ms is set to 0, loaded from the configuration file; file_repeat can be specified, if the configuration file also specifies loop demultiplexing, then force it to be enabled
reader->startReadMP4(0, true, allArgs["file_repeat"]);
});
#endif
@@ -1983,7 +2127,8 @@ void installWebApi() {
return;
}
// 通过on_http_access完成文件下载鉴权请务必确认访问鉴权url参数以及访问文件路径是否合法
// 通过on_http_access完成文件下载鉴权请务必确认访问鉴权url参数以及访问文件路径是否合法 [AUTO-TRANSLATED:73507988]
// File download authentication is completed through on_http_access. Please make sure that the access authentication URL parameters and the access file path are legal
HttpSession::HttpAccessPathInvoker file_invoker = [allArgs, invoker](const string &err_msg, const string &cookie_path_in, int life_second) mutable {
if (!err_msg.empty()) {
invoker(401, StrCaseMap{}, err_msg);
@@ -1999,7 +2144,8 @@ void installWebApi() {
bool flag = NOTICE_EMIT(BroadcastHttpAccessArgs, Broadcast::kBroadcastHttpAccess, allArgs.parser, file_path, false, file_invoker, sender);
if (!flag) {
// 文件下载鉴权事件无人监听,不允许下载
// 文件下载鉴权事件无人监听,不允许下载 [AUTO-TRANSLATED:5e02f0ce]
// No one is listening to the file download authentication event, download is not allowed
invoker(401, StrCaseMap {}, "None http access event listener");
}
});