1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-02-12 19:31:53 +00:00

fix #179: dvr support custom filepath by variables. 2.0.87

This commit is contained in:
winlin 2015-01-03 12:54:54 +08:00
parent f89941254a
commit f881bc43b5
10 changed files with 215 additions and 27 deletions

View file

@ -501,7 +501,8 @@ Supported operating systems and hardware:
* 2013-10-17, Created.<br/>
## History
* v2.0, 2015-01-02, hotfix [#211](https://github.com/winlinvip/simple-rtmp-server/issues/211), support security allow/deny publish/play all/ip. 2.0.86
* v2.0, 2015-01-03, fix [#179](https://github.com/winlinvip/simple-rtmp-server/issues/179), dvr support custom filepath by variables. 2.0.87
* v2.0, 2015-01-02, fix [#211](https://github.com/winlinvip/simple-rtmp-server/issues/211), support security allow/deny publish/play all/ip. 2.0.86
* v2.0, 2015-01-02, hotfix [#207](https://github.com/winlinvip/simple-rtmp-server/issues/207), trim the last 0 of log. 2.0.85
* v2.0, 2014-01-02, fix [#158](https://github.com/winlinvip/simple-rtmp-server/issues/158), http-callback check http status code ok(200). 2.0.84
* v2.0, 2015-01-02, hotfix [#216](https://github.com/winlinvip/simple-rtmp-server/issues/216), http-callback post in application/json content-type. 2.0.83

16
trunk/conf/dvr.path.conf Normal file
View file

@ -0,0 +1,16 @@
# the config for srs to dvr in custom path.
# @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_DVR#custom-path
# @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_DVR#custom-path
# @see full.conf for detail config.
listen 1935;
max_connections 1000;
vhost __defaultVhost__ {
dvr {
enabled on;
dvr_path ./objs/nginx/html/[app]/[stream]/[2006]/[01]/[02]/[15].[04].[05].[999].flv;
dvr_plan segment;
dvr_duration 30;
dvr_wait_keyframe on;
}
}

41
trunk/conf/full.conf Normal file → Executable file
View file

@ -236,15 +236,38 @@ vhost dvr.srs.com {
# default: off
enabled on;
# the dvr output path.
# the app dir is auto created under the dvr_path.
# for example, for rtmp stream:
# rtmp://127.0.0.1/live/livestream
# http://127.0.0.1/live/livestream.m3u8
# where dvr_path is /dvr, srs will create the following files:
# /dvr/live the app dir for all streams.
# /dvr/live/livestream.{time}.flv the dvr flv file.
# @remark, the time use system timestamp in ms, user can use http callback to rename it.
# in a word, the dvr_path is for vhost.
# we supports some variables to generate the filename.
# [vhost], the vhost of stream.
# [app], the app of stream.
# [stream], the stream name of stream.
# [2006], replace this const to current year.
# [01], replace this const to current month.
# [02], replace this const to current date.
# [15], replace this const to current hour.
# [04], repleace this const to current minute.
# [05], repleace this const to current second.
# [999], repleace this const to current millisecond.
# [timestamp],replace this const to current UNIX timestamp in ms.
# @remark we use golang time format "2006-01-02 15:04:05.999"
# for example, for url rtmp://ossrs.net/live/livestream and time 2015-01-03 10:57:30.776
# 1. No variables, the rule of SRS1.0(auto add [stream].[timestamp].flv as filename):
# dvr_path ./objs/nginx/html;
# =>
# dvr_path ./objs/nginx/html/live/livestream.1420254068776.flv;
# 2. Use stream and date as dir name, time as filename:
# dvr_path /data/[vhost]/[app]/[stream]/[2006]/[01]/[02]/[15].[04].[05].[999].flv;
# =>
# dvr_path /data/ossrs.net/live/livestream/2015/01/03/10.57.30.776.flv;
# 3. Use stream and year/month as dir name, date and time as filename:
# dvr_path /data/[vhost]/[app]/[stream]/[2006]/[01]/[02]-[15].[04].[05].[999].flv;
# =>
# dvr_path /data/ossrs.net/live/livestream/2015/01/03-10.57.30.776.flv;
# 4. Use vhost/app and year/month as dir name, stream/date/time as filename:
# dvr_path /data/[vhost]/[app]/[2006]/[01]/[stream]-[02]-[15].[04].[05].[999].flv;
# =>
# dvr_path /data/ossrs.net/live/2015/01/livestream-03-10.57.30.776.flv;
# @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_DVR#custom-path
# @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_DVR#custom-path
# default: ./objs/nginx/html
dvr_path ./objs/nginx/html;
# the dvr plan. canbe:

View file

@ -27,6 +27,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <fcntl.h>
#include <sstream>
#include <sys/time.h>
using namespace std;
#include <srs_app_config.hpp>
@ -136,14 +137,97 @@ int SrsDvrPlan::open_new_segment()
SrsRequest* req = _req;
// new flv file
std::stringstream path;
// the path in config, for example,
// /data/[vhost]/[app]/[stream]/[2006]/[01]/[02]/[15].[04].[05].[999].flv
std::string path_config = _srs_config->get_dvr_path(req->vhost);
path << _srs_config->get_dvr_path(req->vhost)
<< "/" << req->app << "/"
<< req->stream << "." << srs_get_system_time_ms() << ".flv";
// add [stream].[timestamp].flv as filename for dir
if (path_config.find(".flv") != path_config.length() - 4) {
path_config += "/[stream].[timestamp].flv";
}
if ((ret = flv_open(req->get_stream_url(), path.str())) != ERROR_SUCCESS) {
// the flv file path
std::string path = path_config;
// variable [vhost]
path = srs_string_replace(path, "[vhost]", req->vhost);
// variable [app]
path = srs_string_replace(path, "[app]", req->app);
// variable [stream]
path = srs_string_replace(path, "[stream]", req->stream);
// date and time substitude
// clock time
timeval tv;
if (gettimeofday(&tv, NULL) == -1) {
return ERROR_SYSTEM_TIME;
}
// to calendar time
struct tm* tm;
if ((tm = localtime(&tv.tv_sec)) == NULL) {
return ERROR_SYSTEM_TIME;
}
// the buffer to format the date and time.
char buf[64];
// [2006], replace with current year.
if (true) {
snprintf(buf, sizeof(buf), "%d", 1900 + tm->tm_year);
path = srs_string_replace(path, "[2006]", buf);
}
// [2006], replace with current year.
if (true) {
snprintf(buf, sizeof(buf), "%d", 1900 + tm->tm_year);
path = srs_string_replace(path, "[2006]", buf);
}
// [01], replace this const to current month.
if (true) {
snprintf(buf, sizeof(buf), "%d", 1 + tm->tm_mon);
path = srs_string_replace(path, "[01]", buf);
}
// [02], replace this const to current date.
if (true) {
snprintf(buf, sizeof(buf), "%d", tm->tm_mday);
path = srs_string_replace(path, "[02]", buf);
}
// [15], replace this const to current hour.
if (true) {
snprintf(buf, sizeof(buf), "%d", tm->tm_hour);
path = srs_string_replace(path, "[15]", buf);
}
// [04], repleace this const to current minute.
if (true) {
snprintf(buf, sizeof(buf), "%d", tm->tm_min);
path = srs_string_replace(path, "[04]", buf);
}
// [05], repleace this const to current second.
if (true) {
snprintf(buf, sizeof(buf), "%d", tm->tm_sec);
path = srs_string_replace(path, "[05]", buf);
}
// [999], repleace this const to current millisecond.
if (true) {
snprintf(buf, sizeof(buf), "%03d", (int)(tv.tv_usec / 1000));
path = srs_string_replace(path, "[999]", buf);
}
// [timestamp],replace this const to current UNIX timestamp in ms.
if (true) {
int64_t now_us = ((int64_t)tv.tv_sec) * 1000 * 1000 + (int64_t)tv.tv_usec;
snprintf(buf, sizeof(buf), "%"PRId64, now_us / 1000);
path = srs_string_replace(path, "[timestamp]", buf);
}
// create dir first.
std::string dir = path.substr(0, path.rfind("/"));
if ((ret = srs_create_dir_recursively(dir)) != ERROR_SUCCESS) {
srs_error("create dir=%s failed. ret=%d", dir.c_str(), ret);
return ret;
}
srs_info("create dir=%s ok", dir.c_str());
if ((ret = flv_open(req->get_stream_url(), path)) != ERROR_SUCCESS) {
return ret;
}
dvr_enabled = true;

View file

@ -951,16 +951,12 @@ int SrsHlsMuxer::create_dir()
app_dir += app;
// TODO: cleanup the dir when startup.
mode_t mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IXOTH;
if (::mkdir(app_dir.c_str(), mode) < 0) {
if (errno != EEXIST) {
ret = ERROR_HLS_CREATE_DIR;
srs_error("create app dir %s failed. ret=%d", app_dir.c_str(), ret);
return ret;
}
if ((ret = srs_create_dir_recursively(app_dir)) != ERROR_SUCCESS) {
srs_error("create app dir %s failed. ret=%d", app_dir.c_str(), ret);
return ret;
}
srs_info("create app dir %s success.", app_dir.c_str());
srs_info("create app dir %s ok", app_dir.c_str());
return ret;
}

View file

@ -98,6 +98,9 @@ int SrsSecurity::allow_check(SrsConfDirective* rules, SrsRtmpConnType type, std:
break;
}
break;
case SrsRtmpConnUnknown:
default:
break;
}
// when matched, donot search more.
@ -140,6 +143,9 @@ int SrsSecurity::deny_check(SrsConfDirective* rules, SrsRtmpConnType type, std::
break;
}
break;
case SrsRtmpConnUnknown:
default:
break;
}
// when matched, donot search more.

View file

@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// current release version
#define VERSION_MAJOR 2
#define VERSION_MINOR 0
#define VERSION_REVISION 86
#define VERSION_REVISION 87
// server info.
#define RTMP_SIG_SRS_KEY "SRS"
#define RTMP_SIG_SRS_ROLE "origin/edge server"

View file

@ -93,6 +93,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define ERROR_SYSTEM_SECURITY 1052
#define ERROR_SYSTEM_SECURITY_DENY 1053
#define ERROR_SYSTEM_SECURITY_ALLOW 1054
#define ERROR_SYSTEM_TIME 1055
#define ERROR_SYSTEM_DIR_EXISTS 1056
#define ERROR_SYSTEM_CREATE_DIR 1057
///////////////////////////////////////////////////////
// RTMP protocol error.
@ -152,7 +155,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
///////////////////////////////////////////////////////
#define ERROR_HLS_METADATA 3000
#define ERROR_HLS_DECODE_ERROR 3001
#define ERROR_HLS_CREATE_DIR 3002
//#define ERROR_HLS_CREATE_DIR 3002
#define ERROR_HLS_OPEN_FAILED 3003
#define ERROR_HLS_WRITE_FAILED 3004
#define ERROR_HLS_AAC_FRAME_LENGTH 3005

View file

@ -32,10 +32,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#endif
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
using namespace std;
#include <srs_kernel_log.hpp>
#include <srs_kernel_error.hpp>
// this value must:
// equals to (SRS_SYS_CYCLE_INTERVAL*SRS_SYS_TIME_RESOLUTION_MS_TIMES)*1000
@ -222,3 +225,56 @@ bool srs_string_ends_with(string str, string flag)
return str.rfind(flag) == str.length() - flag.length();
}
int __srs_create_dir_recursively(string dir)
{
int ret = ERROR_SUCCESS;
struct stat st;
// stat current dir, if exists, return error.
if (stat(dir.c_str(), &st) == 0) {
return ERROR_SYSTEM_DIR_EXISTS;
}
// create parent first.
size_t pos;
if ((pos = dir.rfind("/")) != std::string::npos) {
std::string parent = dir.substr(0, pos);
ret = __srs_create_dir_recursively(parent);
// return for error.
if (ret != ERROR_SUCCESS && ret != ERROR_SYSTEM_DIR_EXISTS) {
return ret;
}
// parent exists, set to ok.
ret = ERROR_SUCCESS;
}
// create curren dir.
mode_t mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IXOTH;
if (::mkdir(dir.c_str(), mode) < 0) {
if (errno == EEXIST) {
return ERROR_SYSTEM_DIR_EXISTS;
}
ret = ERROR_SYSTEM_CREATE_DIR;
srs_error("create dir %s failed. ret=%d", dir.c_str(), ret);
return ret;
}
srs_info("create dir %s success.", dir.c_str());
return ret;
}
int srs_create_dir_recursively(string dir)
{
int ret = ERROR_SUCCESS;
ret = __srs_create_dir_recursively(dir);
if (ret == ERROR_SYSTEM_DIR_EXISTS) {
return ERROR_SUCCESS;
}
return ret;
}

View file

@ -59,5 +59,8 @@ extern std::string srs_string_remove(std::string str, std::string remove_chars);
// whether string end with
extern bool srs_string_ends_with(std::string str, std::string flag);
// create dir recursively
extern int srs_create_dir_recursively(std::string dir);
#endif