private bool ContainsSubtitleFormat(SubtitleProfile[] profiles, SubtitleDeliveryMethod method, string[] formats) { foreach (SubtitleProfile profile in profiles) { if (method == profile.Method && ListHelper.ContainsIgnoreCase(formats, profile.Format)) { return(true); } } return(false); }
private bool IsEligibleForDirectPlay(MediaSourceInfo item, int?maxBitrate, MediaStream subtitleStream, VideoOptions options) { if (subtitleStream != null) { if (!subtitleStream.IsTextSubtitleStream) { return(false); } SubtitleDeliveryMethod subtitleMethod = GetSubtitleDeliveryMethod(subtitleStream, options); if (subtitleMethod != SubtitleDeliveryMethod.External && subtitleMethod != SubtitleDeliveryMethod.Embed) { return(false); } } return(IsAudioEligibleForDirectPlay(item, maxBitrate)); }
public Task <ActionResult> GetVideoStreamByContainer( [FromRoute, Required] Guid itemId, [FromRoute, Required] 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?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) { return(GetVideoStream( itemId, container, @static, @params, tag, deviceProfileId, playSessionId, segmentContainer, segmentLength, minSegments, mediaSourceId, deviceId, audioCodec, enableAutoStreamCopy, allowVideoStreamCopy, allowAudioStreamCopy, breakOnNonKeyFrames, audioSampleRate, maxAudioBitDepth, audioBitRate, audioChannels, maxAudioChannels, profile, level, framerate, maxFramerate, copyTimestamps, startTimeTicks, width, height, videoBitRate, subtitleStreamIndex, subtitleMethod, maxRefFrames, maxVideoBitDepth, requireAvc, deInterlace, requireNonAnamorphic, transcodingMaxAudioChannels, cpuCoreLimit, liveStreamId, enableMpegtsM2TsMode, videoCodec, subtitleCodec, transcodeReasons, audioStreamIndex, videoStreamIndex, context, streamOptions)); }
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?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; var cancellationTokenSource = new CancellationTokenSource(); var streamingRequest = new VideoRequestDto { Id = itemId, Container = container, Static = @static ?? true, 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 ?? true, StartTimeTicks = startTimeTicks, Width = width, Height = height, VideoBitRate = videoBitRate, SubtitleStreamIndex = subtitleStreamIndex, SubtitleMethod = subtitleMethod, MaxRefFrames = maxRefFrames, MaxVideoBitDepth = maxVideoBitDepth, RequireAvc = requireAvc ?? true, DeInterlace = deInterlace ?? true, RequireNonAnamorphic = requireNonAnamorphic ?? true, TranscodingMaxAudioChannels = transcodingMaxAudioChannels, CpuCoreLimit = cpuCoreLimit, LiveStreamId = liveStreamId, EnableMpegtsM2TsMode = enableMpegtsM2TsMode ?? true, VideoCodec = videoCodec, SubtitleCodec = subtitleCodec, TranscodeReasons = transcodeReasons, AudioStreamIndex = audioStreamIndex, VideoStreamIndex = videoStreamIndex, Context = context, StreamOptions = streamOptions }; using var state = await StreamingHelpers.GetStreamingState( streamingRequest, Request, _authContext, _mediaSourceManager, _userManager, _libraryManager, _serverConfigurationManager, _mediaEncoder, _fileSystem, _subtitleEncoder, _configuration, _dlnaManager, _deviceManager, _transcodingJobHelper, _transcodingJobType, cancellationTokenSource.Token) .ConfigureAwait(false); if (@static.HasValue && @static.Value && state.DirectStreamProvider != null) { StreamingHelpers.AddDlnaHeaders(state, Response.Headers, true, startTimeTicks, Request, _dlnaManager); await new ProgressiveFileCopier(state.DirectStreamProvider, null, _transcodingJobHelper, CancellationToken.None) { AllowEndOfFile = false }.WriteToAsync(Response.Body, CancellationToken.None) .ConfigureAwait(false); // TODO (moved from MediaBrowser.Api): Don't hardcode contentType return(File(Response.Body, MimeTypes.GetMimeType("file.ts") !)); } // Static remote stream if (@static.HasValue && @static.Value && state.InputProtocol == MediaProtocol.Http) { StreamingHelpers.AddDlnaHeaders(state, Response.Headers, true, 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, 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) { await new ProgressiveFileCopier(state.MediaPath, null, _transcodingJobHelper, CancellationToken.None) { AllowEndOfFile = false }.WriteToAsync(Response.Body, CancellationToken.None) .ConfigureAwait(false); return(File(Response.Body, 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 encodingHelper = new EncodingHelper(_mediaEncoder, _fileSystem, _subtitleEncoder, _configuration); var ffmpegCommandLineArguments = encodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, outputPath, "superfast"); return(await FileStreamResponseHelpers.GetTranscodedFile( state, isHeadRequest, HttpContext, _transcodingJobHelper, ffmpegCommandLineArguments, _transcodingJobType, cancellationTokenSource).ConfigureAwait(false)); }
public async Task <ActionResult> GetAudioStream( [FromRoute, Required] Guid itemId, [FromRoute] 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?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?transcodingReasons, [FromQuery] int?audioStreamIndex, [FromQuery] int?videoStreamIndex, [FromQuery] EncodingContext?context, [FromQuery] Dictionary <string, string>?streamOptions) { StreamingRequestDto streamingRequest = new StreamingRequestDto { Id = itemId, Container = container, Static = @static ?? true, 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 ?? true, StartTimeTicks = startTimeTicks, Width = width, Height = height, VideoBitRate = videoBitRate, SubtitleStreamIndex = subtitleStreamIndex, SubtitleMethod = subtitleMethod, MaxRefFrames = maxRefFrames, MaxVideoBitDepth = maxVideoBitDepth, RequireAvc = requireAvc ?? true, DeInterlace = deInterlace ?? true, RequireNonAnamorphic = requireNonAnamorphic ?? true, TranscodingMaxAudioChannels = transcodingMaxAudioChannels, CpuCoreLimit = cpuCoreLimit, LiveStreamId = liveStreamId, EnableMpegtsM2TsMode = enableMpegtsM2TsMode ?? true, VideoCodec = videoCodec, SubtitleCodec = subtitleCodec, TranscodeReasons = transcodingReasons, AudioStreamIndex = audioStreamIndex, VideoStreamIndex = videoStreamIndex, Context = context ?? EncodingContext.Static, StreamOptions = streamOptions }; return(await _audioHelper.GetAudioStream(_transcodingJobType, streamingRequest).ConfigureAwait(false)); }
public async Task <ActionResult> GetLiveHlsStream( [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?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, [FromQuery] int?maxWidth, [FromQuery] int?maxHeight, [FromQuery] bool?enableSubtitlesInManifest) { VideoRequestDto streamingRequest = new VideoRequestDto { Id = itemId, Container = container, Static = @static ?? true, 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 ?? true, StartTimeTicks = startTimeTicks, Width = width, Height = height, VideoBitRate = videoBitRate, SubtitleStreamIndex = subtitleStreamIndex, SubtitleMethod = subtitleMethod, MaxRefFrames = maxRefFrames, MaxVideoBitDepth = maxVideoBitDepth, RequireAvc = requireAvc ?? true, DeInterlace = deInterlace ?? true, RequireNonAnamorphic = requireNonAnamorphic ?? true, TranscodingMaxAudioChannels = transcodingMaxAudioChannels, CpuCoreLimit = cpuCoreLimit, LiveStreamId = liveStreamId, EnableMpegtsM2TsMode = enableMpegtsM2TsMode ?? true, VideoCodec = videoCodec, SubtitleCodec = subtitleCodec, TranscodeReasons = transcodeReasons, AudioStreamIndex = audioStreamIndex, VideoStreamIndex = videoStreamIndex, Context = context, StreamOptions = streamOptions, MaxHeight = maxHeight, MaxWidth = maxWidth, EnableSubtitlesInManifest = enableSubtitlesInManifest ?? true }; var cancellationTokenSource = new CancellationTokenSource(); using var state = await StreamingHelpers.GetStreamingState( streamingRequest, Request, _authContext, _mediaSourceManager, _userManager, _libraryManager, _serverConfigurationManager, _mediaEncoder, _fileSystem, _subtitleEncoder, _configuration, _dlnaManager, _deviceManager, _transcodingJobHelper, TranscodingJobType, cancellationTokenSource.Token) .ConfigureAwait(false); TranscodingJobDto?job = null; var playlistPath = Path.ChangeExtension(state.OutputFilePath, ".m3u8"); if (!System.IO.File.Exists(playlistPath)) { var transcodingLock = _transcodingJobHelper.GetTranscodingLock(playlistPath); await transcodingLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false); try { if (!System.IO.File.Exists(playlistPath)) { // If the playlist doesn't already exist, startup ffmpeg try { job = await _transcodingJobHelper.StartFfMpeg( state, playlistPath, GetCommandLineArguments(playlistPath, state), Request, TranscodingJobType, cancellationTokenSource) .ConfigureAwait(false); job.IsLiveOutput = true; } catch { state.Dispose(); throw; } minSegments = state.MinSegments; if (minSegments > 0) { await HlsHelpers.WaitForMinimumSegmentCount(playlistPath, minSegments, _logger, cancellationTokenSource.Token).ConfigureAwait(false); } } } finally { transcodingLock.Release(); } } job ??= _transcodingJobHelper.OnTranscodeBeginRequest(playlistPath, TranscodingJobType); if (job != null) { _transcodingJobHelper.OnTranscodeEndRequest(job); } var playlistText = HlsHelpers.GetLivePlaylistText(playlistPath, state); return(Content(playlistText, MimeTypes.GetMimeType("playlist.m3u8"))); }
private bool ContainsSubtitleFormat(SubtitleProfile[] profiles, SubtitleDeliveryMethod method, string[] formats) { foreach (SubtitleProfile profile in profiles) { if (method == profile.Method && ListHelper.ContainsIgnoreCase(formats, profile.Format)) { return true; } } return false; }