public async Task Play( [FromOptionalArgument] string streamName, [FromOptionalArgument] double start = -1, [FromOptionalArgument] double duration = -1, [FromOptionalArgument] bool reset = false) { _recordFile = new FileStream(_recordService.GetRecordFilename(streamName) + ".flv", FileMode.Open, FileAccess.Read); await FlvDemuxer.AttachStream(_recordFile); var resetData = new AmfObject { { "level", "status" }, { "code", "NetStream.Play.Reset" }, { "description", "Resetting and playing stream." }, { "details", streamName } }; var resetStatus = RtmpSession.CreateCommandMessage <OnStatusCommandMessage>(); resetStatus.InfoObject = resetData; await MessageStream.SendMessageAsync(ChunkStream, resetStatus); var startData = new AmfObject { { "level", "status" }, { "code", "NetStream.Play.Start" }, { "description", "Started playing." }, { "details", streamName } }; var startStatus = RtmpSession.CreateCommandMessage <OnStatusCommandMessage>(); startStatus.InfoObject = startData; await MessageStream.SendMessageAsync(ChunkStream, startStatus); var bandwidthLimit = new WindowAcknowledgementSizeMessage() { WindowSize = 500 * 1024 }; await RtmpSession.ControlMessageStream.SendMessageAsync(RtmpSession.ControlChunkStream, bandwidthLimit); VideoChunkStream = RtmpSession.CreateChunkStream(); AudioChunkStream = RtmpSession.CreateChunkStream(); var cts = new CancellationTokenSource(); _playCts?.Dispose(); _playCts = cts; start = Math.Max(start, 0); await SeekAndPlay(start / 1000, cts.Token); }
public async Task Play( [FromOptionalArgument] string streamName, [FromOptionalArgument] double start = -1, [FromOptionalArgument] double duration = -1, [FromOptionalArgument] bool reset = false) { var publisher = _publisherSessionService.FindPublisher(streamName); if (publisher == null) { throw new KeyNotFoundException(); } var resetData = new AmfObject { { "level", "status" }, { "code", "NetStream.Play.Reset" }, { "description", "Resetting and playing stream." }, { "details", streamName } }; var resetStatus = RtmpSession.CreateCommandMessage <OnStatusCommandMessage>(); resetStatus.InfoObject = resetData; await MessageStream.SendMessageAsync(ChunkStream, resetStatus); var startData = new AmfObject { { "level", "status" }, { "code", "NetStream.Play.Start" }, { "description", "Started playing." }, { "details", streamName } }; var startStatus = RtmpSession.CreateCommandMessage <OnStatusCommandMessage>(); startStatus.InfoObject = startData; await MessageStream.SendMessageAsync(ChunkStream, startStatus); var flvMetadata = RtmpSession.CreateData <DataMessage>(); flvMetadata.MessageHeader = (MessageHeader)publisher.FlvMetadata.MessageHeader.Clone(); flvMetadata.Data = publisher.FlvMetadata.Data; await MessageStream.SendMessageAsync(ChunkStream, flvMetadata); _videoChunkStream = RtmpSession.CreateChunkStream(); _audioChunkStream = RtmpSession.CreateChunkStream(); if (publisher.AACConfigureRecord != null) { await MessageStream.SendMessageAsync(_audioChunkStream, publisher.AACConfigureRecord.Clone() as AudioMessage); } if (publisher.AVCConfigureRecord != null) { await MessageStream.SendMessageAsync(_videoChunkStream, publisher.AVCConfigureRecord.Clone() as VideoMessage); } publisher.OnAudioMessage += SendAudio; publisher.OnVideoMessage += SendVideo; _cleanupActions.Add(() => { publisher.OnVideoMessage -= SendVideo; publisher.OnAudioMessage -= SendAudio; }); }