/// <summary> /// Get audio stream. /// </summary> /// <param name="transcodingJobType">Transcoding job type.</param> /// <param name="streamingRequest">Streaming controller.Request dto.</param> /// <returns>A <see cref="Task"/> containing the resulting <see cref="ActionResult"/>.</returns> public async Task <ActionResult> GetAudioStream( TranscodingJobType transcodingJobType, StreamingRequestDto streamingRequest) { if (_httpContextAccessor.HttpContext == null) { throw new ResourceNotFoundException(nameof(_httpContextAccessor.HttpContext)); } bool isHeadRequest = _httpContextAccessor.HttpContext.Request.Method == System.Net.WebRequestMethods.Http.Head; // CTS lifecycle is managed internally. var cancellationTokenSource = new CancellationTokenSource(); using var state = await StreamingHelpers.GetStreamingState( streamingRequest, _httpContextAccessor.HttpContext.Request, _authContext, _mediaSourceManager, _userManager, _libraryManager, _serverConfigurationManager, _mediaEncoder, _encodingHelper, _dlnaManager, _deviceManager, _transcodingJobHelper, transcodingJobType, cancellationTokenSource.Token) .ConfigureAwait(false); if (streamingRequest.Static && state.DirectStreamProvider != null) { StreamingHelpers.AddDlnaHeaders(state, _httpContextAccessor.HttpContext.Response.Headers, true, streamingRequest.StartTimeTicks, _httpContextAccessor.HttpContext.Request, _dlnaManager); var liveStreamInfo = _mediaSourceManager.GetLiveStreamInfo(streamingRequest.LiveStreamId); if (liveStreamInfo == null) { throw new FileNotFoundException(); } var liveStream = new ProgressiveFileStream(liveStreamInfo.GetStream()); // TODO (moved from MediaBrowser.Api): Don't hardcode contentType return(new FileStreamResult(liveStream, MimeTypes.GetMimeType("file.ts"))); } // Static remote stream if (streamingRequest.Static && state.InputProtocol == MediaProtocol.Http) { StreamingHelpers.AddDlnaHeaders(state, _httpContextAccessor.HttpContext.Response.Headers, true, streamingRequest.StartTimeTicks, _httpContextAccessor.HttpContext.Request, _dlnaManager); var httpClient = _httpClientFactory.CreateClient(NamedClient.Default); return(await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, httpClient, _httpContextAccessor.HttpContext).ConfigureAwait(false)); } if (streamingRequest.Static && state.InputProtocol != MediaProtocol.File) { return(new BadRequestObjectResult($"Input protocol {state.InputProtocol} cannot be streamed statically")); } var outputPath = state.OutputFilePath; var outputPathExists = File.Exists(outputPath); var transcodingJob = _transcodingJobHelper.GetTranscodingJob(outputPath, TranscodingJobType.Progressive); var isTranscodeCached = outputPathExists && transcodingJob != null; StreamingHelpers.AddDlnaHeaders(state, _httpContextAccessor.HttpContext.Response.Headers, streamingRequest.Static || isTranscodeCached, streamingRequest.StartTimeTicks, _httpContextAccessor.HttpContext.Request, _dlnaManager); // Static stream if (streamingRequest.Static) { var contentType = state.GetMimeType("." + state.OutputContainer, false) ?? state.GetMimeType(state.MediaPath); if (state.MediaSource.IsInfiniteStream) { var stream = new ProgressiveFileStream(state.MediaPath, null, _transcodingJobHelper); return(new FileStreamResult(stream, contentType)); } return(FileStreamResponseHelpers.GetStaticFileResult( state.MediaPath, contentType)); } // Need to start ffmpeg (because media can't be returned directly) var encodingOptions = _serverConfigurationManager.GetEncodingOptions(); var ffmpegCommandLineArguments = _encodingHelper.GetProgressiveAudioFullCommandLine(state, encodingOptions, outputPath); return(await FileStreamResponseHelpers.GetTranscodedFile( state, isHeadRequest, _httpContextAccessor.HttpContext, _transcodingJobHelper, ffmpegCommandLineArguments, transcodingJobType, cancellationTokenSource).ConfigureAwait(false)); }
public async Task <ActionResult> GetVideoStream( [FromRoute, Required] Guid itemId, [FromQuery] string?container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string?tag, [FromQuery] string?deviceProfileId, [FromQuery] string?playSessionId, [FromQuery] string?segmentContainer, [FromQuery] int?segmentLength, [FromQuery] int?minSegments, [FromQuery] string?mediaSourceId, [FromQuery] string?deviceId, [FromQuery] string?audioCodec, [FromQuery] bool?enableAutoStreamCopy, [FromQuery] bool?allowVideoStreamCopy, [FromQuery] bool?allowAudioStreamCopy, [FromQuery] bool?breakOnNonKeyFrames, [FromQuery] int?audioSampleRate, [FromQuery] int?maxAudioBitDepth, [FromQuery] int?audioBitRate, [FromQuery] int?audioChannels, [FromQuery] int?maxAudioChannels, [FromQuery] string?profile, [FromQuery] string?level, [FromQuery] float?framerate, [FromQuery] float?maxFramerate, [FromQuery] bool?copyTimestamps, [FromQuery] long?startTimeTicks, [FromQuery] int?width, [FromQuery] int?height, [FromQuery] int?maxWidth, [FromQuery] int?maxHeight, [FromQuery] int?videoBitRate, [FromQuery] int?subtitleStreamIndex, [FromQuery] SubtitleDeliveryMethod?subtitleMethod, [FromQuery] int?maxRefFrames, [FromQuery] int?maxVideoBitDepth, [FromQuery] bool?requireAvc, [FromQuery] bool?deInterlace, [FromQuery] bool?requireNonAnamorphic, [FromQuery] int?transcodingMaxAudioChannels, [FromQuery] int?cpuCoreLimit, [FromQuery] string?liveStreamId, [FromQuery] bool?enableMpegtsM2TsMode, [FromQuery] string?videoCodec, [FromQuery] string?subtitleCodec, [FromQuery] string?transcodeReasons, [FromQuery] int?audioStreamIndex, [FromQuery] int?videoStreamIndex, [FromQuery] EncodingContext?context, [FromQuery] Dictionary <string, string> streamOptions) { var isHeadRequest = Request.Method == System.Net.WebRequestMethods.Http.Head; // CTS lifecycle is managed internally. var cancellationTokenSource = new CancellationTokenSource(); var streamingRequest = new VideoRequestDto { Id = itemId, Container = container, Static = @static ?? false, Params = @params, Tag = tag, DeviceProfileId = deviceProfileId, PlaySessionId = playSessionId, SegmentContainer = segmentContainer, SegmentLength = segmentLength, MinSegments = minSegments, MediaSourceId = mediaSourceId, DeviceId = deviceId, AudioCodec = audioCodec, EnableAutoStreamCopy = enableAutoStreamCopy ?? true, AllowAudioStreamCopy = allowAudioStreamCopy ?? true, AllowVideoStreamCopy = allowVideoStreamCopy ?? true, BreakOnNonKeyFrames = breakOnNonKeyFrames ?? false, AudioSampleRate = audioSampleRate, MaxAudioChannels = maxAudioChannels, AudioBitRate = audioBitRate, MaxAudioBitDepth = maxAudioBitDepth, AudioChannels = audioChannels, Profile = profile, Level = level, Framerate = framerate, MaxFramerate = maxFramerate, CopyTimestamps = copyTimestamps ?? false, StartTimeTicks = startTimeTicks, Width = width, Height = height, MaxWidth = maxWidth, MaxHeight = maxHeight, VideoBitRate = videoBitRate, SubtitleStreamIndex = subtitleStreamIndex, SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode, MaxRefFrames = maxRefFrames, MaxVideoBitDepth = maxVideoBitDepth, RequireAvc = requireAvc ?? false, DeInterlace = deInterlace ?? false, RequireNonAnamorphic = requireNonAnamorphic ?? false, TranscodingMaxAudioChannels = transcodingMaxAudioChannels, CpuCoreLimit = cpuCoreLimit, LiveStreamId = liveStreamId, EnableMpegtsM2TsMode = enableMpegtsM2TsMode ?? false, VideoCodec = videoCodec, SubtitleCodec = subtitleCodec, TranscodeReasons = transcodeReasons, AudioStreamIndex = audioStreamIndex, VideoStreamIndex = videoStreamIndex, Context = context ?? EncodingContext.Streaming, StreamOptions = streamOptions }; using var state = await StreamingHelpers.GetStreamingState( streamingRequest, Request, _authContext, _mediaSourceManager, _userManager, _libraryManager, _serverConfigurationManager, _mediaEncoder, _encodingHelper, _dlnaManager, _deviceManager, _transcodingJobHelper, _transcodingJobType, cancellationTokenSource.Token) .ConfigureAwait(false); if (@static.HasValue && @static.Value && state.DirectStreamProvider != null) { StreamingHelpers.AddDlnaHeaders(state, Response.Headers, true, state.Request.StartTimeTicks, Request, _dlnaManager); var liveStreamInfo = _mediaSourceManager.GetLiveStreamInfo(streamingRequest.LiveStreamId); if (liveStreamInfo == null) { return(NotFound()); } var liveStream = new ProgressiveFileStream(liveStreamInfo.GetStream()); // TODO (moved from MediaBrowser.Api): Don't hardcode contentType return(File(liveStream, MimeTypes.GetMimeType("file.ts"))); } // Static remote stream if (@static.HasValue && @static.Value && state.InputProtocol == MediaProtocol.Http) { StreamingHelpers.AddDlnaHeaders(state, Response.Headers, true, state.Request.StartTimeTicks, Request, _dlnaManager); var httpClient = _httpClientFactory.CreateClient(NamedClient.Default); return(await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, isHeadRequest, httpClient, HttpContext).ConfigureAwait(false)); } if (@static.HasValue && @static.Value && state.InputProtocol != MediaProtocol.File) { return(BadRequest($"Input protocol {state.InputProtocol} cannot be streamed statically")); } var outputPath = state.OutputFilePath; var outputPathExists = System.IO.File.Exists(outputPath); var transcodingJob = _transcodingJobHelper.GetTranscodingJob(outputPath, TranscodingJobType.Progressive); var isTranscodeCached = outputPathExists && transcodingJob != null; StreamingHelpers.AddDlnaHeaders(state, Response.Headers, (@static.HasValue && @static.Value) || isTranscodeCached, state.Request.StartTimeTicks, Request, _dlnaManager); // Static stream if (@static.HasValue && @static.Value) { var contentType = state.GetMimeType("." + state.OutputContainer, false) ?? state.GetMimeType(state.MediaPath); if (state.MediaSource.IsInfiniteStream) { var liveStream = new ProgressiveFileStream(state.MediaPath, null, _transcodingJobHelper); return(File(liveStream, contentType)); } return(FileStreamResponseHelpers.GetStaticFileResult( state.MediaPath, contentType, isHeadRequest, HttpContext)); } // Need to start ffmpeg (because media can't be returned directly) var encodingOptions = _serverConfigurationManager.GetEncodingOptions(); var ffmpegCommandLineArguments = _encodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, outputPath, "superfast"); return(await FileStreamResponseHelpers.GetTranscodedFile( state, isHeadRequest, HttpContext, _transcodingJobHelper, ffmpegCommandLineArguments, _transcodingJobType, cancellationTokenSource).ConfigureAwait(false)); }