Skip to content

Commit

Permalink
支持自定义视频存储位置
Browse files Browse the repository at this point in the history
  • Loading branch information
chatop committed Sep 22, 2020
1 parent c66fd00 commit 17fa0c3
Show file tree
Hide file tree
Showing 15 changed files with 141 additions and 4 deletions.
Binary file added .DS_Store
Binary file not shown.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[Bb]in/
[Oo]bj/
[Ll]og/
2 changes: 2 additions & 0 deletions CommonFunctions/DBStructs/StreamDvrPlan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public class StreamDvrPlan
public long? LimitSpace { get; set; }

public int? LimitDays { get; set; }


[Column(MapType = typeof(string))] public OverStepPlan? OverStepPlan { get; set; }

[Navigate(nameof(DvrDayTimeRange.StreamDvrPlanId))]
Expand Down
10 changes: 9 additions & 1 deletion CommonFunctions/MediaServerControl/MediaServerInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class MediaServerInstance
private DateTime _updateTime; //最后控制时间
private DateTime _keepAlive;
private ZLMediaKitWebApiHelper _webApi; //流媒体服务操作类
private string? _recordFilePath;//保存录制文件的目录

private ZLMediaKitConfigForResponse _config = new ZLMediaKitConfigForResponse(); //流媒体服务器配置
//private List<OnlineClientSession> _onlineClientSessionList = new List<OnlineClientSession>();
Expand Down Expand Up @@ -114,6 +115,12 @@ private double getUpTime()
return 0;
}

public string? RecordFilePath
{
get => _recordFilePath;
set => _recordFilePath = value;
}

public ZLMediaKitConfigForResponse Config
{
get => _config;
Expand Down Expand Up @@ -264,7 +271,7 @@ private void checkStreamStatusNew()
}*/

public MediaServerInstance(string ipaddress, ushort webApiPort, ushort mediaServerHttpPort, string secret,
string mediaServerId)
string mediaServerId,string recordFilePath)
{
_ipaddress = ipaddress;
_webApiPort = webApiPort;
Expand All @@ -273,6 +280,7 @@ public MediaServerInstance(string ipaddress, ushort webApiPort, ushort mediaServ
_mediaServerId = mediaServerId;
_webApi = new ZLMediaKitWebApiHelper(_ipaddress, mediaServerHttpPort, _secret);
_updateTime = DateTime.Now;
_recordFilePath = recordFilePath;
new Thread(new ThreadStart(delegate

{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public class ResMediaServerWebApiReg
private string? _ipaddress;
private string _mediaServerId;
private string _secret;
private string? _recordFilePath;


public ushort MediaServerHttpPort
Expand Down Expand Up @@ -42,5 +43,11 @@ public string Secret
get => _secret;
set => _secret = value;
}

public string? RecordFilePath
{
get => _recordFilePath;
set => _recordFilePath = value;
}
}
}
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,52 @@ NoticeCenter::Instance().addListener(nullptr,Broadcast::kBroadcastStreamNoneRead

~~~
-src/Record/Recorder.cpp
~~~c++
string Recorder::getRecordPath(Recorder::type type, const string &vhost, const string &app, const string &stream_id, const string &customized_path) {
GET_CONFIG(bool, enableVhost, General::kEnableVhost);
switch (type) {
case Recorder::type_hls: {
GET_CONFIG(string, hlsPath, Hls::kFilePath);
string m3u8FilePath;
if (enableVhost) {
m3u8FilePath = vhost + "/" + app + "/" + stream_id + "/hls.m3u8";
} else {
m3u8FilePath = app + "/" + stream_id + "/hls.m3u8";
}
//Here we use the customized file path.
if (!customized_path.empty()) {
m3u8FilePath = customized_path + "/hls.m3u8";
}
return File::absolutePath(m3u8FilePath, hlsPath);
}
case Recorder::type_mp4: {
GET_CONFIG(string, recordPath, Record::kFilePath);
GET_CONFIG(string, recordAppName, Record::kAppName);
string mp4FilePath;
if (enableVhost) {
mp4FilePath = vhost + "/" + recordAppName + "/" + app + "/" + stream_id + "/";
} else {
mp4FilePath = recordAppName + "/" + app + "/" + stream_id + "/";
}
//Here we use the customized file path.
if (!customized_path.empty()) {
/*开始删除*/
// mp4FilePath = customized_path + "/";
/*删除结束*/
/*开始添加*/
return customized_path + "/"+mp4FilePath;
/*开始添加*/
}
return File::absolutePath(mp4FilePath, recordPath);
}
default:
return "";
}
}
~~~

# 组成部分
## StreamNodeWebApi
- 全局的流媒体管理API服务,包含了所有流媒体功能的控制,如摄像头注册,录制计划,rtp推流,ptz控制等。
Expand Down Expand Up @@ -367,6 +413,8 @@ NoticeCenter::Instance().addListener(nullptr,Broadcast::kBroadcastStreamNoneRead
~~~




## StreamNodeWebApi/system.conf
- StreamNodeWebApi的配置文件,参数名与参数值以::分开,每行以;结束
- 数据库方面采用CodeFirst 模式,在数据库中建立一个名为streamnode的库,数据表会自动创建
Expand All @@ -386,6 +434,7 @@ MediaServerBinPath::/root/MediaService/MediaServer;//ZLMediaKit流媒体服务
StreamNodeServerUrl::http://192.168.2.43:5800/WebHook/MediaServerRegister; //向哪个StreamNodeWebApi注册自己的服务
HttpPort::6880;//服务的WebApi端口
IpAddress::192.168.2.43;//本机ip地址
CustomizedRecordFilePath::/home/cdtnb; //自定义存储视频的位置
~~~


Expand Down
35 changes: 35 additions & 0 deletions StreamMediaServerKeeper/Common.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ public static class Common
public static string MediaServerId = null!;
public static ProcessApis ProcessApis = new ProcessApis();
public static string MyIPAddress = "";
/// <summary>
/// 自定义的录制文件存储位置
/// </summary>
public static string CustomizedRecordFilePath = "";
public static LogMonitor LogMonitor= new LogMonitor();


Expand Down Expand Up @@ -156,6 +160,8 @@ private static void getMediaServerConfig()
"http://" + streamNodeUri.Host + ":" + streamNodeUri.Port + "/WebHook/OnPublish"; //有流发布时
data["hook"]["on_record_mp4"] =
"http://" + streamNodeUri.Host + ":" + streamNodeUri.Port + "/WebHook/OnRecordMp4Completed"; //当录制mp4完成时
data["hook"]["on_record_ts"]=
"http://" + streamNodeUri.Host + ":" + streamNodeUri.Port + "/WebHook/OnRecordTsCompleted"; //当录制ts完成时
data["hook"]["on_rtsp_auth"] = ""; //rtsp鉴权,不作支持
data["hook"]["on_rtsp_realm"] = ""; //rtsp专用鉴权,不作支持
data["hook"]["on_shell_login"] = ""; //shell鉴权,不作支持
Expand Down Expand Up @@ -243,6 +249,34 @@ public static bool GetConfig()
return false;
}
}
if (str.ToLower().Contains("customizedrecordfilepath"))
{
string[] tmpArr = str.Trim().Split("::", StringSplitOptions.RemoveEmptyEntries);
if (tmpArr.Length == 2)
{
CustomizedRecordFilePath = tmpArr[1].Trim().TrimEnd(';');
if (!string.IsNullOrEmpty(CustomizedRecordFilePath))
{
DirectoryInfo di = null;
if (!Directory.Exists(CustomizedRecordFilePath))
{
di=Directory.CreateDirectory(CustomizedRecordFilePath);
}
else
{
di=new DirectoryInfo(CustomizedRecordFilePath);
}

if (di != null && di.Exists)
{
//如果自定义的存储位置不为空,则使用自定义存储位置替换原有存储位置
RecordPath = CustomizedRecordFilePath;
}

}
}

}
}
}
}
Expand Down Expand Up @@ -338,6 +372,7 @@ private static void KeepAlive()
MediaServerId = MediaServerId,
Secret = Secret,
WebApiServerhttpPort = HttpPort,
RecordFilePath = RecordPath,
};
string reqData = JsonHelper.ToJson(req);
try
Expand Down
3 changes: 2 additions & 1 deletion StreamMediaServerKeeper/Config.conf
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
MediaServerBinPath::/Users/qiuzhouwei/Projects/StreamNode/StreamMediaServerKeeper/bin/Debug/netcoreapp3.1/api_tester_server;
StreamNodeServerUrl::http://127.0.0.1:5800/WebHook/MediaServerRegister;
HttpPort::6880;
IpAddress::192.168.2.45;
IpAddress::192.168.2.45;
CustomizedRecordFilePath::/home/www;
5 changes: 5 additions & 0 deletions StreamMediaServerKeeper/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ public class Program

public static void Main(string[] args)
{
///启动一下,Common对象
if (string.IsNullOrEmpty(Common.CustomizedRecordFilePath))
{
Common.CustomizedRecordFilePath = "";
}
CreateHostBuilder(args).Build().Run();
}

Expand Down
7 changes: 7 additions & 0 deletions StreamMediaServerKeeper/ReqMediaServerReg.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public class ReqMediaServerReg
private string? _ipaddress;
private string? _mediaServerId;
private string? _secret;
private string? _recordFilePath;

public ushort? MediaServerHttpPort
{
Expand Down Expand Up @@ -41,5 +42,11 @@ public string? Secret
get => _secret;
set => _secret = value;
}

public string? RecordFilePath
{
get => _recordFilePath;
set => _recordFilePath = value;
}
}
}
12 changes: 12 additions & 0 deletions StreamMediaServerKeeper/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using System.Linq;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using CommonFunctions;
using CommonFunctions.DBStructs;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
Expand Down Expand Up @@ -67,6 +69,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
}
*/


app.UseHttpsRedirection();
// 启用Swagger中间件
app.UseSwagger();
Expand All @@ -83,6 +86,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
Directory.CreateDirectory(Common.CutOrMergePath);
}

if (!Directory.Exists(Common.CutOrMergeTempPath))
{
Directory.CreateDirectory(Common.CutOrMergeTempPath);
Expand All @@ -100,6 +104,14 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
};
app.UseStaticFiles(staticfile);

app.UseFileServer(new FileServerOptions()
{
FileProvider = new PhysicalFileProvider
(Path.Combine(Directory.GetCurrentDirectory(), Common.RecordPath)), //实际目录地址
RequestPath = new Microsoft.AspNetCore.Http.PathString("/CustomizedRecord"), //用户访问地址
EnableDirectoryBrowsing = true //开启目录浏览
});


app.UseEndpoints(
endpoints =>
Expand Down
5 changes: 5 additions & 0 deletions StreamMediaServerKeeper/Swagger.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions StreamNodeCtrlApis/WebHookApis/MediaServerCtrlApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ public static ResToWebHookOnStreamChange OnRecordMp4Completed(ReqForWebHookOnRec
tmpDvrVideo.PushMediaServerId = record.Mediaserverid;
tmpDvrVideo.UpdateTime = currentTime;
tmpDvrVideo.RecordDate = st.ToString("yyyy-MM-dd");
tmpDvrVideo.DownloadUrl = "http://" + mediaServer.Ipaddress + ":" + mediaServer.WebApiPort + "/" +
tmpDvrVideo.DownloadUrl = "http://" + mediaServer.Ipaddress + ":" + mediaServer.WebApiPort + "/CustomizedRecord/" +
tmpDvrVideo.DownloadUrl;

CameraSession session = null;
Expand Down Expand Up @@ -712,7 +712,7 @@ public static ResMediaServerWebApiReg ServerReg(ResMediaServerWebApiReg req, out
}

MediaServerInstance msi = new MediaServerInstance(req.Ipaddress, req.WebApiServerhttpPort,
req.MediaServerHttpPort, req.Secret, req.MediaServerId);
req.MediaServerHttpPort, req.Secret, req.MediaServerId,req.RecordFilePath);
msi.KeepAlive = DateTime.Now;

lock (Common.MediaServerList)
Expand Down
1 change: 1 addition & 0 deletions StreamNodeWebApi/AutoTasker/RecordAutoKeeper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@ private void setDvrOnorOff(StreamDvrPlan sdp, bool enable)
Secret = "",
Stream = obj.StreamId,
Vhost = obj.Vhost,
Customized_Path = mediaServer.RecordFilePath,
}, out _);
}
else
Expand Down
2 changes: 2 additions & 0 deletions StreamNodeWebApi/Controllers/WebHookController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ public ResToWebHookOnStreamChange OnMediaServerStart(Object req)

var tmpObj = JsonHelper.FromJson<ZLMediaKitConfigForResponse>(str);


ResponseStruct rs;
var ret = MediaServerCtrlApi.OnMediaServerStart(tmpObj, out rs);
if (rs.Code != ErrorNumber.None)
Expand Down Expand Up @@ -201,6 +202,7 @@ public ResMediaServerWebApiReg MediaServerRegister(ResMediaServerWebApiReg req)
req.Ipaddress = thisip.MapToIPv4().ToString();
}


var ret = MediaServerCtrlApi.ServerReg(req, out rs);
if (rs.Code != ErrorNumber.None)
{
Expand Down

0 comments on commit 17fa0c3

Please sign in to comment.