/// <summary> /// Initializes a new instance of the <see cref="ProgressiveFileCopier"/> class. /// </summary> /// <param name="directStreamProvider">Instance of the <see cref="IDirectStreamProvider"/> interface.</param> /// <param name="job">The transcoding job.</param> /// <param name="transcodingJobHelper">Instance of the <see cref="TranscodingJobHelper"/>.</param> /// <param name="cancellationToken">The cancellation token.</param> public ProgressiveFileCopier(IDirectStreamProvider directStreamProvider, TranscodingJobDto?job, TranscodingJobHelper transcodingJobHelper, CancellationToken cancellationToken) { _directStreamProvider = directStreamProvider; _job = job; _cancellationToken = cancellationToken; _transcodingJobHelper = transcodingJobHelper; }
/// <summary> /// Initializes a new instance of the <see cref="ProgressiveFileCopier"/> class. /// </summary> /// <param name="path">The path to copy from.</param> /// <param name="job">The transcoding job.</param> /// <param name="transcodingJobHelper">Instance of the <see cref="TranscodingJobHelper"/>.</param> /// <param name="cancellationToken">The cancellation token.</param> public ProgressiveFileCopier(string path, TranscodingJobDto?job, TranscodingJobHelper transcodingJobHelper, CancellationToken cancellationToken) { _path = path; _job = job; _cancellationToken = cancellationToken; _transcodingJobHelper = transcodingJobHelper; }
/// <summary> /// Initializes a new instance of the <see cref="ProgressiveFileStream"/> class. /// </summary> /// <param name="stream">The stream to progressively copy.</param> /// <param name="timeoutMs">The timeout duration in milliseconds.</param> public ProgressiveFileStream(Stream stream, int timeoutMs = 30000) { _job = null; _transcodingJobHelper = null; _timeoutMs = timeoutMs; _stream = stream; }
/// <summary> /// Initializes a new instance of the <see cref="ProgressiveFileStream"/> class. /// </summary> /// <param name="stream">The stream to progressively copy.</param> /// <param name="timeoutMs">The timeout duration in milliseconds.</param> public ProgressiveFileStream(Stream stream, int timeoutMs = 30000) { _job = null; _transcodingJobHelper = null; _timeoutMs = timeoutMs; _allowAsyncFileRead = AsyncFile.UseAsyncIO; _stream = stream; }
/// <summary> /// Initializes a new instance of the <see cref="ProgressiveFileStream"/> class. /// </summary> /// <param name="filePath">The path to the transcoded file.</param> /// <param name="job">The transcoding job information.</param> /// <param name="transcodingJobHelper">The transcoding job helper.</param> /// <param name="timeoutMs">The timeout duration in milliseconds.</param> public ProgressiveFileStream(string filePath, TranscodingJobDto?job, TranscodingJobHelper transcodingJobHelper, int timeoutMs = 30000) { _job = job; _transcodingJobHelper = transcodingJobHelper; _timeoutMs = timeoutMs; _stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous | FileOptions.SequentialScan); }
/// <summary> /// Initializes a new instance of the <see cref="ProgressiveFileStream"/> class. /// </summary> /// <param name="filePath">The path to the transcoded file.</param> /// <param name="job">The transcoding job information.</param> /// <param name="transcodingJobHelper">The transcoding job helper.</param> /// <param name="timeoutMs">The timeout duration in milliseconds.</param> public ProgressiveFileStream(string filePath, TranscodingJobDto?job, TranscodingJobHelper transcodingJobHelper, int timeoutMs = 30000) { _job = job; _transcodingJobHelper = transcodingJobHelper; _timeoutMs = timeoutMs; var fileOptions = FileOptions.SequentialScan; _allowAsyncFileRead = false; // use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039 if (AsyncFile.UseAsyncIO) { fileOptions |= FileOptions.Asynchronous; _allowAsyncFileRead = true; } _stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, fileOptions); }
/// <summary> /// Initializes a new instance of the <see cref="ProgressiveFileStream"/> class. /// </summary> /// <param name="filePath">The path to the transcoded file.</param> /// <param name="job">The transcoding job information.</param> /// <param name="transcodingJobHelper">The transcoding job helper.</param> public ProgressiveFileStream(string filePath, TranscodingJobDto?job, TranscodingJobHelper transcodingJobHelper) { _job = job; _transcodingJobHelper = transcodingJobHelper; _bytesWritten = 0; var fileOptions = FileOptions.SequentialScan; _allowAsyncFileRead = false; // use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039 if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { fileOptions |= FileOptions.Asynchronous; _allowAsyncFileRead = true; } _fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, fileOptions); }
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 ?? 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, 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, 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, _encodingHelper, _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"))); }