This commit is contained in:
2023-07-29 17:43:19 +01:00
parent 4f690b114d
commit c5c9c54518
24 changed files with 985 additions and 12 deletions

View File

@ -124,7 +124,7 @@ public class PlaylistController : Controller
return;
}
Response.ContentType = "application/x-mpegurl";
Response.ContentType = "application/vnd.apple.mpegurl";
await using var sw = new StreamWriter(Response.Body);
var streams = await _srsApi.ListStreams();
@ -176,6 +176,39 @@ public class PlaylistController : Controller
}
}
[HttpGet("recording/{id:guid}.m3u8")]
public async Task RecordingPlaylist([FromRoute]Guid id)
{
try
{
var streamManager = await _streamManagerFactory.ForStream(id);
var userStream = streamManager.GetStream();
// https://developer.apple.com/documentation/http-live-streaming/video-on-demand-playlist-construction
Response.ContentType = "application/vnd.apple.mpegurl";
await using var sw = new StreamWriter(Response.Body);
await sw.WriteLineAsync("#EXTM3U");
await sw.WriteLineAsync("#EXT-X-PLAYLIST-TYPE:VOD");
await sw.WriteLineAsync("#EXT-X-TARGETDURATION:30");
await sw.WriteLineAsync("#EXT-X-VERSION:4");
await sw.WriteLineAsync("#EXT-X-MEDIA-SEQUENCE:0");
await sw.WriteLineAsync("#EXT-X-INDEPENDENT-SEGMENTS");
foreach (var seg in userStream.Recordings.OrderBy(a => a.Timestamp))
{
await sw.WriteLineAsync($"#EXTINF:{seg.Duration:0.0####},");
await sw.WriteLineAsync($"#EXT-X-PROGRAM-DATE-TIME:{seg.Timestamp:yyyy-MM-ddTHH:mm:ss.fffzzz}");
await sw.WriteLineAsync(seg.Url);
}
await sw.WriteLineAsync("#EXT-X-ENDLIST");
}
catch
{
Response.StatusCode = 404;
}
}
private async Task<string?> GetHlsCtx(UserStream stream)
{
var path = $"/{stream.Endpoint.App}/source/{stream.User.StreamKey}.m3u8";

View File

@ -9,11 +9,13 @@ public class SrsController : Controller
{
private readonly ILogger<SrsController> _logger;
private readonly StreamManagerFactory _streamManagerFactory;
private readonly Config _config;
public SrsController(ILogger<SrsController> logger, StreamManagerFactory streamManager)
public SrsController(ILogger<SrsController> logger, StreamManagerFactory streamManager, Config config)
{
_logger = logger;
_streamManagerFactory = streamManager;
_config = config;
}
[HttpPost]
@ -78,6 +80,12 @@ public class SrsController : Controller
await streamManager.ConsumeQuota(req.Duration.Value);
return new();
}
if (req.Action == "on_dvr" && !string.IsNullOrEmpty(req.File))
{
await streamManager.OnDvr(new Uri(_config.SrsHttpHost, $"{req.App}/{Path.GetFileName(req.File)}"));
return new();
}
}
else
{
@ -139,4 +147,7 @@ public class SrsHook
[JsonProperty("duration")]
public double? Duration { get; init; }
[JsonProperty("file")]
public string? File { get; init; }
}