按需录像需求:1. 时延短,接收和执行录像指令的时间要快,100ms以内。2. 录像文件时长不固定,定在[3s, 1800s]这个区间。最短3s,最长30min。
用法:外部进程向redis-queue发送record-start/record-stop指令来控制录像开始和结束。
Cmd格式:start-record|stop-record,
redis-queue名称: {app}-{stream} //rtmp-url格式:rtmp://host:1935/{app}/{stream}
为什么要选srs 4.0release分支呢?因为这个分支分别在centos7.9和debian11下编译,都是成功的,环境兼容性也强。
创建一个自己的srs repo: https://github.com/shitizenlism/srs4.0dvr/tree/4.0release。
fork ossrs/srs.git,跟随4.0release分支。一方面可以merge原分支的更新,自己的修改也不影响原作者的repo。等项目稳定后,再向原作者提交pull request。或者不提交也没关系。
核心函数是
int SrsDvrSegmentPlan::update_duration(SrsSharedPtrMessage* msg)
{
const char *app= req->app.c_str();
const char *stream=req->stream.c_str();
snprintf(queName,sizeof(queName),"%s-%s",app,stream);
ret=redis_queue_lpop(queName, value);
if (ret==1){
srs_trace("fetch from redis-que[%s]: %s", queName,value);
pSubStr[0] = strtok(value, sCut); //cmd
pSubStr[1] = strtok(NULL, sCut); //VideoID
pSubStr[2] = strtok(NULL, sCut); //recordFilename
if (!strcmp(pSubStr[0], "start_record")){
if (segment->current()->duration()>=3){ //录像文件最短3s
dvr_state = 2; // 状态值:0:init, 1:start, 2: stop.
} else {
dvr_state = 1; //
dvr_saveFilename = pSubStr[2]
}
…
} else (!strcmp(pSubStr[0], "stop_record"){
…
}
}
if ((dvr_state==0)||(dvr_state==1))
{
fragment = segment->current();
if (fragment->duration() >= cduration) { //录像文件最长由配置文件dvr.conf决定。
dvr_state=2;
}
}
if (dvr_state==2){
//处理keyframe
}
// reap segment。保存当前录像文件。
if ((err = segment->close(dvr_saveFilename)) != srs_success) {
srs_error_reset(err);
return 0;
}
//创建下一个segment
if ((err = segment->open()) != srs_success) {
}
dvr_state=0;
return 1;
}
新增一个配置文件conf/dvr.segment2.conf
[opc@instance-20220112 trunk]$ cat conf/dvr.segment2.conf
listen 1935;
max_connections 1000;
srs_log_tank console;
srs_log_file ./logs/dvr.log;
srs_log_level info;
daemon off;
redis_server {
host 127.0.0.1;
port 6379;
#pass 123456;
db 1;
}
vhost __defaultVhost__ {
dvr {
enabled on;
dvr_path ./objs/nginx/html/[app]/[stream].[timestamp].mp4;
dvr_plan segment;
dvr_duration 1800;
dvr_wait_keyframe on;
}
}
Make后启动srs进程。
$ ./objs/srs -c conf/dvr.segment2.conf
用obs推流后可以打到dvr.log中打印:
[2023-07-02 23:51:50.933][Trace][21943][4w0j4455] redis_init(127.0.0.1:6379,,db=1),ret=0
[2023-07-02 23:51:50.933][Trace][21943][4w0j4455] redis-server connected!
用redis-cli,发送start_record和stop_record命令。
127.0.0.1:6379[1]> rpush live-test start_record,A001,GB11112222A001
(integer) 1
127.0.0.1:6379[1]> rpush live-test stop_record,A001,GB11112222A001
(integer) 1
127.0.0.1:6379[1]> rpush live-test start_record,A001,GB11112222A002
(integer) 1
127.0.0.1:6379[1]>
打印消息:
[2023-07-02 23:54:02.422][Trace][22468][4966jnrj] fetch from redis-que[live-test]: start_record,A001,GB11112222A002
[2023-07-02 23:54:02.422][Trace][22468][4966jnrj] dvr_saveFilename= GB11112222A001
$ ls objs/nginx/html/live/
GB11112222A001.mp4 //start_record和stop_record之间的录像文件。
test.1688313223719.mp4 //stop_record和next start_stop之间的录像文件。
test.1688313245271.mp4.tmp //当前录像文件。