josephnhtam / live-streaming-server-net

A .NET implementation of RTMP live streaming server, supporting HTTP-FLV, WebSocket-FLV, HLS, Kubernetes, cloud storage services integration and more.
https://josephnhtam.github.io/live-streaming-server-net/
MIT License
109 stars 16 forks source link

How do I manage client connections? #50

Closed wosledon closed 3 weeks ago

wosledon commented 1 month ago

The scenario is like this, I need to automatically stop the RTMP stream when there is no client watching, but I can't seem to get the full RTMP connection information and client information

josephnhtam commented 1 month ago

Hi @wosledon

I have released v0.14.2, which exposes IRtmpStreamManager to facilitate a similar use case.

Before v0.14.2, you may need to implement IRtmpServerStreamEventHandler to listen for the publishing and subscribing events in order to know which clients were publishing and subscribing to streams. Now, you can use IRtmpStreamManager to get this information.

I have also updated the LiveStreamingServerNet.EventsDemo to show the usage of IRtmpStreamManager.

wosledon commented 1 month ago

okey, thanks!

wosledon commented 1 month ago

Hi @wosledon

I have released v0.14.2, which exposes IRtmpStreamManager to facilitate a similar use case.

Before v0.14.2, you may need to implement IRtmpServerStreamEventHandler to listen for the publishing and subscribing events in order to know which clients were publishing and subscribing to streams. Now, you can use IRtmpStreamManager to get this information.

I have also updated the LiveStreamingServerNet.EventsDemo to show the usage of IRtmpStreamManager.

Hey, for my testing, I couldn't get if the player was connected to the server.

josephnhtam commented 1 month ago

Can IRtmpStream.Subsribers help?

wosledon commented 1 month ago

Can IRtmpStream.Subsribers help?

I connected using the VLC player and the Subsribers is not receiving the connection event

josephnhtam commented 1 month ago

The Subscribers list will not get updated in realtime. Please refer to RTMP Server Events and implement IRtmpServerStreamEventHandler in order to listen the OnRtmpStreamSubscribedAsync event, and call IStreamManager.GetStream again.

wosledon commented 1 month ago

v0.14.0, for my tests, it works wrong. OnRtmpStreamPublishedAsyncOnRtmpStreamUnpublishedAsyncOnRtmpStreamMetaDataReceivedAsync

OnRtmpStreamSubscribedAsync OnRtmpStreamUnsubscribedAsync x

/// <summary>
///
/// </summary>
public class RtmpMediaServerStreamService : IRtmpServerStreamEventHandler, IDisposable
{
    /// <inheritdoc/>
    public void Dispose()
    {
        throw new NotImplementedException();
    }

    /// <inheritdoc/>
    public ValueTask OnRtmpStreamMetaDataReceivedAsync(IEventContext context, uint clientId, string streamPath, IReadOnlyDictionary<string, object> metaData)
    {
        Console.WriteLine($"A-{clientId}, {streamPath}, {metaData.ToJson()}");

        return ValueTask.CompletedTask;
    }

    /// <inheritdoc/>
    public ValueTask OnRtmpStreamPublishedAsync(IEventContext context, uint clientId, string streamPath, IReadOnlyDictionary<string, string> streamArguments)
    {
        Console.WriteLine($"B-{clientId}, {streamPath}, {streamArguments.ToJson()}");
        return ValueTask.CompletedTask;
    }

    /// <inheritdoc/>
    public ValueTask OnRtmpStreamSubscribedAsync(IEventContext context, uint clientId, string streamPath, IReadOnlyDictionary<string, string> streamArguments)
    {
        Console.WriteLine($"C-{clientId}, {streamPath}, {streamArguments.ToJson()}");
        return ValueTask.CompletedTask;
    }

    /// <inheritdoc/>
    public ValueTask OnRtmpStreamUnpublishedAsync(IEventContext context, uint clientId, string streamPath)
    {
        Console.WriteLine($"D-{clientId}, {streamPath}");
        return ValueTask.CompletedTask;
    }

    /// <inheritdoc/>
    public ValueTask OnRtmpStreamUnsubscribedAsync(IEventContext context, uint clientId, string streamPath)
    {
        Console.WriteLine($"E-{clientId}, {streamPath}");
        return ValueTask.CompletedTask;
    }
}
josephnhtam commented 1 month ago

I have tested with the following code, which works for me

using LiveStreamingServerNet;
using LiveStreamingServerNet.Rtmp.Contracts;
using LiveStreamingServerNet.Utilities.Contracts;
using System.Net;

var liveStreamingServer = LiveStreamingServerBuilder.Create()
    .ConfigureRtmpServer(options =>
        options.AddStreamEventHandler<RtmpMediaServerStreamService>())
    .Build();

await liveStreamingServer.RunAsync(new IPEndPoint(IPAddress.Any, 1935));

public class RtmpMediaServerStreamService : IRtmpServerStreamEventHandler
{
    public ValueTask OnRtmpStreamMetaDataReceivedAsync(IEventContext context, uint clientId, string streamPath, IReadOnlyDictionary<string, object> metaData)
    {
        Console.WriteLine($"A-{clientId}, {streamPath}");

        return ValueTask.CompletedTask;
    }

    public ValueTask OnRtmpStreamPublishedAsync(IEventContext context, uint clientId, string streamPath, IReadOnlyDictionary<string, string> streamArguments)
    {
        Console.WriteLine($"B-{clientId}, {streamPath}");
        return ValueTask.CompletedTask;
    }

    public ValueTask OnRtmpStreamSubscribedAsync(IEventContext context, uint clientId, string streamPath, IReadOnlyDictionary<string, string> streamArguments)
    {
        Console.WriteLine($"C-{clientId}, {streamPath}");
        return ValueTask.CompletedTask;
    }

    public ValueTask OnRtmpStreamUnpublishedAsync(IEventContext context, uint clientId, string streamPath)
    {
        Console.WriteLine($"D-{clientId}, {streamPath}");
        return ValueTask.CompletedTask;
    }

    public ValueTask OnRtmpStreamUnsubscribedAsync(IEventContext context, uint clientId, string streamPath)
    {
        Console.WriteLine($"E-{clientId}, {streamPath}");
        return ValueTask.CompletedTask;
    }
}

OnRtmpStreamSubscribedAsync is invoked when a watcher subscribes the stream, and OnRtmpStreamUnsubscribedAsync is invoked when the watcher leaves.