Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DVR: On-demand recording, dynamic recording, recording and slicing based on conditions. #1577

Closed
springjk opened this issue Jan 15, 2020 · 4 comments
Assignees
Labels
Feature It's a new feature. TransByAI Translated by AI/GPT. Won't fix We won't fix it.
Milestone

Comments

@springjk
Copy link

springjk commented Jan 15, 2020

Demand scenario:

After the user's live stream is transcoded into multiple resolutions, it is only necessary to record and slice a specified resolution or several resolutions. For example, there is no need to slice the ultra-high-definition resolution, and there is no need to record the low-resolution. Only recording a high-resolution or transcoding-encoded stream is sufficient. Currently, if recording and slicing are done directly in the origin, it will record and slice all resolutions according to the transcoding-related configuration, which does not meet the requirements. However, if it is forwarded to another machine, the forwarded stream will also include all resolutions, and there is no way to forward only a specific resolution. In other words, forwarding does not work within the scope of the transcode engine.

Currently, I have a crude solution: transcoding into an additional stream and outputting it to another SRS (Streaming Media Server) that is specifically configured for recording. This way, it will only record the desired resolution, and the slicing process will work similarly.

    transcode {
        enabled     on;
        ffmpeg      ./objs/ffmpeg/bin/ffmpeg;


        engine 720p {
            enabled         on;
            vfilter {
                v           quiet;
            }
            vcodec          libx264;
            vbitrate        2000;
            vfps            25;
            vwidth          1280;
            vheight         720;
            vthreads        12;
            vprofile        main;
            vpreset         ultrafast;
            vparams {
            }
            acodec          libfdk_aac;
            aparams {
            }
            output          rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine];
        }

        engine 720p_dvr {
            enabled         on;
            vfilter {
                v           quiet;
            }
            vcodec          libx264;
            vbitrate        2000;
            vfps            25;
            vwidth          1280;
            vheight         720;
            vthreads        12;
            vprofile        main;
            vpreset         ultrafast;
            vparams {
            }
            acodec          libfdk_aac;
            aparams {
            }
            output          rtmp://10.16.0.4:1937/[app]?vhost=[vhost]/[stream]_[engine];
        }
    }

This approach seems to be a redundant use of CPU resources to create an additional stream, and it is uncertain whether it will have any impact on the cluster. I am unsure of the correct approach to take in this situation.

Expectation:

  • Recording and slicing can be configured to be enabled for a specified engine.
  • Forwarding can forward the stream of a specified engine.
  • Recording or slicing has related callback APIs for the business side to indicate which one to enable or disable, but this may make SRS stateful.

If the above implementation can meet the requirements, it is necessary to explore what kind of solutions can be used to achieve better results if it is not currently supported. Alternatively, it is worth considering if there are already existing methods to achieve the desired outcome that I may have overlooked. Any input or guidance would be greatly appreciated.

TRANS_BY_GPT3

@springjk
Copy link
Author

springjk commented Jan 15, 2020

Continued to try 2 methods, ingest and publish stream event exec, with the following results:

ingest

ingest {
        enabled      on;
        input {
            type    stream;

            url     rtmp://127.0.0.1/streams/123_720p;
        }
        ffmpeg      ./objs/ffmpeg/bin/ffmpeg;
        engine {
            enabled          on;
            output          rtmp://10.16.0.4:1937/[streams/123_720p;
        }
}

This method pulls the specified 720p stream and pushes it to record SRS, which is feasible, but it cannot dynamically configure or insert parameters to support all streams. Each stream needs to be configured separately, which is not feasible.

exec


exec {

        enabled     on;

        publish     ./objs/ffmpeg/bin/ffmpeg -f flv -i rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_720p -c copy -f flv rtmp://10.16.0.4:1937/[app]?vhost=[vhost]/[stream]_720p;
}

This method pulls the 720p stream of each stream and pushes it to record SRS, which is feasible. However, in the source station cluster mode, there may be error reports but the push is normal. The error message is as follows:

srs_1  | [2020-01-15 18:44:19.573][Trace][1][231] connected stream, tcUrl=rtmp://127.0.0.1:1935/streams?vhost=__defaultVhost__, pageUrl=, swfUrl=, schema=rtmp, vhost=__defaultVhost__, port=1935, app=streams, stream=123_720p_720p, param=, args=null
srs_1  | [2020-01-15 18:44:19.574][Trace][1][231] source url=/streams/123_720p_720p, ip=127.0.0.1, cache=1, is_edge=0, source_id=-1[-1]
srs_1  | [2020-01-15 18:44:19.574][Trace][1][232] ignore AMF0/AMF3 command message.
srs_1  | [2020-01-15 18:44:19.574][Trace][1][232] client identified, type=Play, vhost=__defaultVhost__, app=streams, stream=123_1080p_720p, param=, duration=-1ms
srs_1  | [2020-01-15 18:44:19.574][Trace][1][232] connected stream, tcUrl=rtmp://127.0.0.1:1935/streams?vhost=__defaultVhost__, pageUrl=, swfUrl=, schema=rtmp, vhost=__defaultVhost__, port=1935, app=streams, stream=123_1080p_720p, param=, args=null
srs_1  | [2020-01-15 18:44:19.575][Trace][1][232] source url=/streams/123_1080p_720p, ip=127.0.0.1, cache=1, is_edge=0, source_id=-1[-1]
srs_1  | [2020-01-15 18:44:19.575][Error][1][231][115] serve error code=3090 : service cycle : rtmp: stream service : discover coworkers, url=http://10.16.0.4:1936/api/v1/clusters?vhost=__defaultVhost__&ip=127.0.0.1&app=streams&stream=123_720p_720p&coworker=10.16.0.4:1936 : parse data {"code":0,"data":{"query":{"ip":"127.0.0.1","vhost":"__defaultVhost__","app":"streams","stream":"123_720p_720p"},"origin":null}}
srs_1  | thread [1][231]: do_cycle() [src/app/srs_app_rtmp_conn.cpp:210][errno=115]
srs_1  | thread [1][231]: service_cycle() [src/app/srs_app_rtmp_conn.cpp:400][errno=115]
srs_1  | thread [1][231]: playing() [src/app/srs_app_rtmp_conn.cpp:622][errno=115]
srs_1  | thread [1][231]: discover_co_workers() [src/app/srs_app_http_hooks.cpp:453][errno=115](Operation now in progress)
srs_1  | rtmp://127.0.0.1:1935/streams?vhost=__defaultVhost__/123_720p_720p: Input/output error
srs_1  | [2020-01-15 18:44:19.576][Error][1][232][11] serve error code=3090 : service cycle : rtmp: stream service : discover coworkers, url=http://10.16.0.4:1936/api/v1/clusters?vhost=__defaultVhost__&ip=127.0.0.1&app=streams&stream=123_1080p_720p&coworker=10.16.0.4:1936 : parse data {"code":0,"data":{"query":{"ip":"127.0.0.1","vhost":"__defaultVhost__","app":"streams","stream":"123_1080p_720p"},"origin":null}}
srs_1  | thread [1][232]: do_cycle() [src/app/srs_app_rtmp_conn.cpp:210][errno=11]
srs_1  | thread [1][232]: service_cycle() [src/app/srs_app_rtmp_conn.cpp:400][errno=11]
srs_1  | thread [1][232]: playing() [src/app/srs_app_rtmp_conn.cpp:622][errno=11]
srs_1  | thread [1][232]: discover_co_workers() [src/app/srs_app_http_hooks.cpp:453][errno=11](Resource temporarily unavailable)
srs_1  | rtmp://127.0.0.1:1935/streams?vhost=__defaultVhost__/123_1080p_720p: Input/output error

Method 2 seems to be feasible, but it needs improvement. Can the errors caused by inter-cluster communication be avoided?

The above test was conducted on docker 3.0-a8, pushing the /streams/123 stream and transcoding it to 1080p and 720p.

TRANS_BY_GPT3

@winlinvip winlinvip changed the title 根据条件进行录制和切片 动态录制,根据条件进行录制和切片 Jan 25, 2020
@winlinvip
Copy link
Member

winlinvip commented Jan 25, 2020

Dynamic recording: Decide whether to record based on callbacks, and it is more appropriate to pass the parameters of the stream.

TRANS_BY_GPT3

@winlinvip winlinvip added the Feature It's a new feature. label Jan 25, 2020
@winlinvip winlinvip added this to the SRS 4.0 release milestone Jan 25, 2020
@winlinvip winlinvip changed the title 动态录制,根据条件进行录制和切片 DVR: 按需录制,动态录制,根据条件进行录制和切片 Jan 10, 2022
@ghostsf
Copy link
Contributor

ghostsf commented Jan 10, 2022

Dynamic recording: Decide whether to record based on callbacks, and pass the parameters of the stream, which is more appropriate.

What does this mean? Custom recording of pulling streams based on the stream on_publish callback?

TRANS_BY_GPT3

@winlinvip
Copy link
Member

winlinvip commented Jun 24, 2022

Please refer to FAQ for more information.

  • Dynamic DVR: Regarding dynamic recording, regular expression matching is used to determine which streams need to be recorded.
    1. You can use on_publish to callback the business system, and let the business system handle the rules.
    2. The actual recording files can be handled using on_hls, by copying the segments to the recording directory or cloud storage.
    3. You can refer to the implementation of DVR in srs-cloud.

Please make sure to maintain the markdown structure.

On-demand DVR, similar to on-demand Forward, is a hook that handles streams on-demand. You can refer to the solution at #1342 (comment). If you are willing to implement it yourself, you can also use a similar approach.

Please make sure to maintain the markdown structure.

However, the complexity of DVR compared to Forward lies in the fact that Forward is stateless, while DVR involves issues such as stream re-publishing and concatenation.

Please make sure to maintain the markdown structure.

Therefore, considering these factors, it is better to implement it with callbacks in conjunction with the business system, and SRS is not suitable for support.

Please make sure to maintain the markdown structure.

TRANS_BY_GPT3

@winlinvip winlinvip added the Won't fix We won't fix it. label Jun 24, 2022
@winlinvip winlinvip changed the title DVR: 按需录制,动态录制,根据条件进行录制和切片 DVR: On-demand recording, dynamic recording, recording and slicing based on conditions. Jul 28, 2023
@winlinvip winlinvip added the TransByAI Translated by AI/GPT. label Jul 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature It's a new feature. TransByAI Translated by AI/GPT. Won't fix We won't fix it.
Projects
None yet
Development

No branches or pull requests

6 participants