Browse Source

fix subsequent hls session work ahead (#1419)

pull/1420/head
Jason Dove 3 years ago committed by GitHub
parent
commit
a90348740d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      CHANGELOG.md
  2. 20
      ErsatzTV.Application/Streaming/HlsSessionWorker.cs
  3. 4
      ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs
  4. 15
      ErsatzTV/Controllers/ArtworkController.cs

2
CHANGELOG.md

@ -28,7 +28,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Fix adding alternate schedule - Fix adding alternate schedule
### Changed ### Changed
- Optimize transcoding session to only work ahead (at max speed) for 2 minutes before throttling to realtime - Optimize transcoding session to only work ahead (at max speed) for 3 minutes before throttling to realtime
- This should *greatly* reduce cpu/gpu use when joining a channel, particularly with long content - This should *greatly* reduce cpu/gpu use when joining a channel, particularly with long content
- Allow manually editing (typing) schedule item fixed start time - Allow manually editing (typing) schedule item fixed start time
- Use different control for editing schedule item duration, and allow 24-hour duration - Use different control for editing schedule item duration, and allow 24-hour duration

20
ErsatzTV.Application/Streaming/HlsSessionWorker.cs

@ -19,6 +19,8 @@ namespace ErsatzTV.Application.Streaming;
public class HlsSessionWorker : IHlsSessionWorker public class HlsSessionWorker : IHlsSessionWorker
{ {
public static readonly TimeSpan WorkAheadDuration = TimeSpan.FromMinutes(3);
private static readonly SemaphoreSlim Slim = new(1, 1); private static readonly SemaphoreSlim Slim = new(1, 1);
private static int _workAheadCount; private static int _workAheadCount;
private readonly IMediator _mediator; private readonly IMediator _mediator;
@ -269,17 +271,27 @@ public class HlsSessionWorker : IHlsSessionWorker
{ {
Interlocked.Increment(ref _workAheadCount); Interlocked.Increment(ref _workAheadCount);
_logger.LogInformation("HLS segmenter will work ahead for channel {Channel}", _channelNumber); _logger.LogInformation("HLS segmenter will work ahead for channel {Channel}", _channelNumber);
HlsSessionState nextState = _state switch
{
HlsSessionState.SeekAndRealtime => HlsSessionState.SeekAndWorkAhead,
HlsSessionState.ZeroAndRealtime => HlsSessionState.ZeroAndWorkAhead,
_ => _state
};
if (nextState != _state)
{
_logger.LogDebug("HLS session state accelerating {Last} => {Next}", _state, nextState);
_state = nextState;
}
} }
else else
{ {
_logger.LogInformation( _logger.LogInformation(
"HLS segmenter will NOT work ahead for channel {Channel}", "HLS segmenter will NOT work ahead for channel {Channel}",
_channelNumber); _channelNumber);
}
// throttle to realtime if needed // throttle to realtime if needed
if (realtime)
{
HlsSessionState nextState = _state switch HlsSessionState nextState = _state switch
{ {
HlsSessionState.SeekAndWorkAhead => HlsSessionState.SeekAndRealtime, HlsSessionState.SeekAndWorkAhead => HlsSessionState.SeekAndRealtime,

4
ErsatzTV.Application/Streaming/Queries/GetPlayoutItemProcessByChannelNumberHandler.cs

@ -182,9 +182,9 @@ public class GetPlayoutItemProcessByChannelNumberHandler : FFmpegProcessHandler<
// _logger.LogDebug("PRE Start: {Start}, Finish {Finish}", start, finish); // _logger.LogDebug("PRE Start: {Start}, Finish {Finish}", start, finish);
// _logger.LogDebug("PRE in: {In}, out: {Out}", inPoint, outPoint); // _logger.LogDebug("PRE in: {In}, out: {Out}", inPoint, outPoint);
if (!request.HlsRealtime && duration > TimeSpan.FromMinutes(2)) if (!request.HlsRealtime && duration > HlsSessionWorker.WorkAheadDuration)
{ {
finish = effectiveNow + TimeSpan.FromMinutes(2); finish = effectiveNow + HlsSessionWorker.WorkAheadDuration;
outPoint = finish - start + inPoint; outPoint = finish - start + inPoint;
isComplete = false; isComplete = false;

15
ErsatzTV/Controllers/ArtworkController.cs

@ -138,9 +138,9 @@ public class ArtworkController : ControllerBase
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
#if DEBUG_NO_SYNC #if DEBUG_NO_SYNC
await Task.CompletedTask;
return NotFound(); return NotFound();
#endif #else
Either<BaseError, PlexConnectionParametersViewModel> connectionParameters = Either<BaseError, PlexConnectionParametersViewModel> connectionParameters =
await _mediator.Send(new GetPlexConnectionParameters(plexMediaSourceId), cancellationToken); await _mediator.Send(new GetPlexConnectionParameters(plexMediaSourceId), cancellationToken);
@ -165,14 +165,15 @@ public class ArtworkController : ControllerBase
stream, stream,
response.Content.Headers.ContentType?.MediaType ?? "image/jpeg"); response.Content.Headers.ContentType?.MediaType ?? "image/jpeg");
}); });
#endif
} }
private async Task<IActionResult> GetJellyfinArtwork(string path, CancellationToken cancellationToken) private async Task<IActionResult> GetJellyfinArtwork(string path, CancellationToken cancellationToken)
{ {
#if DEBUG_NO_SYNC #if DEBUG_NO_SYNC
await Task.CompletedTask;
return NotFound(); return NotFound();
#endif #else
Either<BaseError, JellyfinConnectionParametersViewModel> connectionParameters = Either<BaseError, JellyfinConnectionParametersViewModel> connectionParameters =
await _mediator.Send(new GetJellyfinConnectionParameters(), cancellationToken); await _mediator.Send(new GetJellyfinConnectionParameters(), cancellationToken);
@ -196,14 +197,15 @@ public class ArtworkController : ControllerBase
stream, stream,
response.Content.Headers.ContentType?.MediaType ?? "image/jpeg"); response.Content.Headers.ContentType?.MediaType ?? "image/jpeg");
}); });
#endif
} }
private async Task<IActionResult> GetEmbyArtwork(string path, CancellationToken cancellationToken) private async Task<IActionResult> GetEmbyArtwork(string path, CancellationToken cancellationToken)
{ {
#if DEBUG_NO_SYNC #if DEBUG_NO_SYNC
await Task.CompletedTask;
return NotFound(); return NotFound();
#endif #else
Either<BaseError, EmbyConnectionParametersViewModel> connectionParameters = Either<BaseError, EmbyConnectionParametersViewModel> connectionParameters =
await _mediator.Send(new GetEmbyConnectionParameters(), cancellationToken); await _mediator.Send(new GetEmbyConnectionParameters(), cancellationToken);
@ -227,5 +229,6 @@ public class ArtworkController : ControllerBase
stream, stream,
response.Content.Headers.ContentType?.MediaType ?? "image/jpeg"); response.Content.Headers.ContentType?.MediaType ?? "image/jpeg");
}); });
#endif
} }
} }

Loading…
Cancel
Save