aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Api/Helpers/StreamingHelpers.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Jellyfin.Api/Helpers/StreamingHelpers.cs')
-rw-r--r--Jellyfin.Api/Helpers/StreamingHelpers.cs33
1 files changed, 27 insertions, 6 deletions
diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs
index bfe71fd87..535ef27c3 100644
--- a/Jellyfin.Api/Helpers/StreamingHelpers.cs
+++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs
@@ -11,6 +11,7 @@ using Jellyfin.Extensions;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Streaming;
@@ -18,6 +19,7 @@ using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.Net.Http.Headers;
namespace Jellyfin.Api.Helpers;
@@ -107,7 +109,8 @@ public static class StreamingHelpers
?? state.SupportedSubtitleCodecs.FirstOrDefault();
}
- var item = libraryManager.GetItemById(streamingRequest.Id);
+ var item = libraryManager.GetItemById<BaseItem>(streamingRequest.Id)
+ ?? throw new ResourceNotFoundException();
state.IsInputVideo = item.MediaType == MediaType.Video;
@@ -125,7 +128,7 @@ public static class StreamingHelpers
if (mediaSource is null)
{
- var mediaSources = await mediaSourceManager.GetPlaybackMediaSources(libraryManager.GetItemById(streamingRequest.Id), null, false, false, cancellationToken).ConfigureAwait(false);
+ var mediaSources = await mediaSourceManager.GetPlaybackMediaSources(libraryManager.GetItemById<BaseItem>(streamingRequest.Id), null, false, false, cancellationToken).ConfigureAwait(false);
mediaSource = string.IsNullOrEmpty(streamingRequest.MediaSourceId)
? mediaSources[0]
@@ -139,6 +142,25 @@ public static class StreamingHelpers
}
else
{
+ // Enforce more restrictive transcoding profile for LiveTV due to compatability reasons
+ // Cap the MaxStreamingBitrate to 30Mbps, because we are unable to reliably probe source bitrate,
+ // which will cause the client to request extremely high bitrate that may fail the player/encoder
+ streamingRequest.VideoBitRate = streamingRequest.VideoBitRate > 30000000 ? 30000000 : streamingRequest.VideoBitRate;
+
+ if (streamingRequest.SegmentContainer is not null)
+ {
+ // Remove all fmp4 transcoding profiles, because it causes playback error and/or A/V sync issues
+ // Notably: Some channels won't play on FireFox and LG webOS
+ // Some channels from HDHomerun will experience A/V sync issues
+ streamingRequest.SegmentContainer = "ts";
+ streamingRequest.VideoCodec = "h264";
+ streamingRequest.AudioCodec = "aac";
+ state.SupportedVideoCodecs = ["h264"];
+ state.Request.VideoCodec = "h264";
+ state.SupportedAudioCodecs = ["aac"];
+ state.Request.AudioCodec = "aac";
+ }
+
var liveStreamInfo = await mediaSourceManager.GetLiveStreamWithDirectStreamProvider(streamingRequest.LiveStreamId, cancellationToken).ConfigureAwait(false);
mediaSource = liveStreamInfo.Item1;
state.DirectStreamProvider = liveStreamInfo.Item2;
@@ -163,6 +185,9 @@ public static class StreamingHelpers
}
var outputAudioCodec = streamingRequest.AudioCodec;
+ state.OutputAudioCodec = outputAudioCodec;
+ state.OutputContainer = (containerInternal ?? string.Empty).TrimStart('.');
+ state.OutputAudioChannels = encodingHelper.GetNumAudioChannelsParam(state, state.AudioStream, state.OutputAudioCodec);
if (EncodingHelper.LosslessAudioCodecs.Contains(outputAudioCodec))
{
state.OutputAudioBitrate = state.AudioStream.BitRate ?? 0;
@@ -177,10 +202,6 @@ public static class StreamingHelpers
containerInternal = ".pcm";
}
- state.OutputAudioCodec = outputAudioCodec;
- state.OutputContainer = (containerInternal ?? string.Empty).TrimStart('.');
- state.OutputAudioChannels = encodingHelper.GetNumAudioChannelsParam(state, state.AudioStream, state.OutputAudioCodec);
-
if (state.VideoRequest is not null)
{
state.OutputVideoCodec = state.Request.VideoCodec;