|
|
|
@ -15,6 +15,7 @@ using Jellyfin.Api.Models.StreamingDtos;
|
|
|
|
|
using Jellyfin.Data.Enums;
|
|
|
|
|
using Jellyfin.Extensions;
|
|
|
|
|
using Jellyfin.MediaEncoding.Hls.Playlist;
|
|
|
|
|
using MediaBrowser.Common.Api;
|
|
|
|
|
using MediaBrowser.Common.Configuration;
|
|
|
|
|
using MediaBrowser.Controller.Configuration;
|
|
|
|
|
using MediaBrowser.Controller.Library;
|
|
|
|
@ -36,16 +37,14 @@ namespace Jellyfin.Api.Controllers;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Dynamic hls controller.
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Route("")]
|
|
|
|
|
[Authorize]
|
|
|
|
|
[Authorize(Policy = Policies.Playback)]
|
|
|
|
|
public class DynamicHlsController : BaseJellyfinApiController
|
|
|
|
|
{
|
|
|
|
|
private const string DefaultVodEncoderPreset = "veryfast";
|
|
|
|
|
private const string DefaultEventEncoderPreset = "superfast";
|
|
|
|
|
private const TranscodingJobType TranscodingJobType = MediaBrowser.Controller.MediaEncoding.TranscodingJobType.Hls;
|
|
|
|
|
private const TranscodingJobType DefaultTranscodingJobType = TranscodingJobType.Hls;
|
|
|
|
|
|
|
|
|
|
private readonly Version _minFFmpegFlacInMp4 = new Version(6, 0);
|
|
|
|
|
|
|
|
|
|
private readonly ILibraryManager _libraryManager;
|
|
|
|
|
private readonly IUserManager _userManager;
|
|
|
|
|
private readonly IMediaSourceManager _mediaSourceManager;
|
|
|
|
@ -285,7 +284,7 @@ public class DynamicHlsController : BaseJellyfinApiController
|
|
|
|
|
_mediaEncoder,
|
|
|
|
|
_encodingHelper,
|
|
|
|
|
_transcodeManager,
|
|
|
|
|
TranscodingJobType,
|
|
|
|
|
DefaultTranscodingJobType,
|
|
|
|
|
cancellationToken)
|
|
|
|
|
.ConfigureAwait(false);
|
|
|
|
|
|
|
|
|
@ -306,7 +305,7 @@ public class DynamicHlsController : BaseJellyfinApiController
|
|
|
|
|
playlistPath,
|
|
|
|
|
GetCommandLineArguments(playlistPath, state, true, 0),
|
|
|
|
|
Request.HttpContext.User.GetUserId(),
|
|
|
|
|
TranscodingJobType,
|
|
|
|
|
DefaultTranscodingJobType,
|
|
|
|
|
cancellationTokenSource)
|
|
|
|
|
.ConfigureAwait(false);
|
|
|
|
|
job.IsLiveOutput = true;
|
|
|
|
@ -326,7 +325,7 @@ public class DynamicHlsController : BaseJellyfinApiController
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
job ??= _transcodeManager.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
|
|
|
|
|
job ??= _transcodeManager.OnTranscodeBeginRequest(playlistPath, DefaultTranscodingJobType);
|
|
|
|
|
|
|
|
|
|
if (job is not null)
|
|
|
|
|
{
|
|
|
|
@ -508,7 +507,7 @@ public class DynamicHlsController : BaseJellyfinApiController
|
|
|
|
|
EnableTrickplay = enableTrickplay
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return await _dynamicHlsHelper.GetMasterHlsPlaylist(TranscodingJobType, streamingRequest, enableAdaptiveBitrateStreaming).ConfigureAwait(false);
|
|
|
|
|
return await _dynamicHlsHelper.GetMasterHlsPlaylist(DefaultTranscodingJobType, streamingRequest, enableAdaptiveBitrateStreaming).ConfigureAwait(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -674,7 +673,7 @@ public class DynamicHlsController : BaseJellyfinApiController
|
|
|
|
|
EnableAdaptiveBitrateStreaming = enableAdaptiveBitrateStreaming
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return await _dynamicHlsHelper.GetMasterHlsPlaylist(TranscodingJobType, streamingRequest, enableAdaptiveBitrateStreaming).ConfigureAwait(false);
|
|
|
|
|
return await _dynamicHlsHelper.GetMasterHlsPlaylist(DefaultTranscodingJobType, streamingRequest, enableAdaptiveBitrateStreaming).ConfigureAwait(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -1379,7 +1378,7 @@ public class DynamicHlsController : BaseJellyfinApiController
|
|
|
|
|
_mediaEncoder,
|
|
|
|
|
_encodingHelper,
|
|
|
|
|
_transcodeManager,
|
|
|
|
|
TranscodingJobType,
|
|
|
|
|
DefaultTranscodingJobType,
|
|
|
|
|
cancellationTokenSource.Token)
|
|
|
|
|
.ConfigureAwait(false);
|
|
|
|
|
|
|
|
|
@ -1417,7 +1416,7 @@ public class DynamicHlsController : BaseJellyfinApiController
|
|
|
|
|
_mediaEncoder,
|
|
|
|
|
_encodingHelper,
|
|
|
|
|
_transcodeManager,
|
|
|
|
|
TranscodingJobType,
|
|
|
|
|
DefaultTranscodingJobType,
|
|
|
|
|
cancellationToken)
|
|
|
|
|
.ConfigureAwait(false);
|
|
|
|
|
|
|
|
|
@ -1431,7 +1430,7 @@ public class DynamicHlsController : BaseJellyfinApiController
|
|
|
|
|
|
|
|
|
|
if (System.IO.File.Exists(segmentPath))
|
|
|
|
|
{
|
|
|
|
|
job = _transcodeManager.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
|
|
|
|
|
job = _transcodeManager.OnTranscodeBeginRequest(playlistPath, DefaultTranscodingJobType);
|
|
|
|
|
_logger.LogDebug("returning {0} [it exists, try 1]", segmentPath);
|
|
|
|
|
return await GetSegmentResult(state, playlistPath, segmentPath, segmentExtension, segmentId, job, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
}
|
|
|
|
@ -1441,7 +1440,7 @@ public class DynamicHlsController : BaseJellyfinApiController
|
|
|
|
|
var startTranscoding = false;
|
|
|
|
|
if (System.IO.File.Exists(segmentPath))
|
|
|
|
|
{
|
|
|
|
|
job = _transcodeManager.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
|
|
|
|
|
job = _transcodeManager.OnTranscodeBeginRequest(playlistPath, DefaultTranscodingJobType);
|
|
|
|
|
_logger.LogDebug("returning {0} [it exists, try 2]", segmentPath);
|
|
|
|
|
return await GetSegmentResult(state, playlistPath, segmentPath, segmentExtension, segmentId, job, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
}
|
|
|
|
@ -1492,7 +1491,7 @@ public class DynamicHlsController : BaseJellyfinApiController
|
|
|
|
|
playlistPath,
|
|
|
|
|
GetCommandLineArguments(playlistPath, state, false, segmentId),
|
|
|
|
|
Request.HttpContext.User.GetUserId(),
|
|
|
|
|
TranscodingJobType,
|
|
|
|
|
DefaultTranscodingJobType,
|
|
|
|
|
cancellationTokenSource).ConfigureAwait(false);
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
@ -1505,7 +1504,7 @@ public class DynamicHlsController : BaseJellyfinApiController
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
job = _transcodeManager.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
|
|
|
|
|
job = _transcodeManager.OnTranscodeBeginRequest(playlistPath, DefaultTranscodingJobType);
|
|
|
|
|
if (job?.TranscodingThrottler is not null)
|
|
|
|
|
{
|
|
|
|
|
await job.TranscodingThrottler.UnpauseTranscoding().ConfigureAwait(false);
|
|
|
|
@ -1514,7 +1513,7 @@ public class DynamicHlsController : BaseJellyfinApiController
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_logger.LogDebug("returning {0} [general case]", segmentPath);
|
|
|
|
|
job ??= _transcodeManager.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
|
|
|
|
|
job ??= _transcodeManager.OnTranscodeBeginRequest(playlistPath, DefaultTranscodingJobType);
|
|
|
|
|
return await GetSegmentResult(state, playlistPath, segmentPath, segmentExtension, segmentId, job, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1970,7 +1969,7 @@ public class DynamicHlsController : BaseJellyfinApiController
|
|
|
|
|
|
|
|
|
|
private int? GetCurrentTranscodingIndex(string playlist, string segmentExtension)
|
|
|
|
|
{
|
|
|
|
|
var job = _transcodeManager.GetTranscodingJob(playlist, TranscodingJobType);
|
|
|
|
|
var job = _transcodeManager.GetTranscodingJob(playlist, DefaultTranscodingJobType);
|
|
|
|
|
|
|
|
|
|
if (job is null || job.HasExited)
|
|
|
|
|
{
|
|
|
|
|