Retain selectable audio languages and DVB subtitles through live continuity

This commit is contained in:
2026-10-23 23:50:46 +02:00
parent 9a056b3070
commit bd7395f045
17 changed files with 666 additions and 57 deletions
+28 -9
View File
@@ -1226,17 +1226,36 @@ namespace Jellyfin.Plugin.Enigma2
var streamUrl = string.Format("{0}/{1}{2}", baseUrl, channelOid, trancodingUrl);
streamUrl = _streamRelay.Register(streamUrl);
// Background recordings keep the original source: never record an
// endless status slate or guess a viewer language for a timer.
if (Plugin.Instance.Configuration.EnableContinuitySlates && _continuity != null && feedback != null)
{
feedback.Report("waiting_for_stream");
return await _continuity.Open(streamUrl, feedback.Language, cancellationToken).ConfigureAwait(false);
}
var fields = channelOid.Split(':');
var programme = !Plugin.Instance.Configuration.TranscodedStream && fields.Length > 3 && int.TryParse(fields[3], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var sid) ? sid : (int?)null;
var probe = _streamProbe.Get(streamUrl, cancellationToken, programme);
var streams = await (_feedback == null ? probe : _feedback.AwaitStream(probe, feedback, cancellationToken)).ConfigureAwait(false);
var useSlates = Plugin.Instance.Configuration.EnableContinuitySlates && _continuity != null && feedback != null;
List<MediaStream> streams;
try
{
var probe = _streamProbe.Get(streamUrl, cancellationToken, programme);
var known = useSlates ? _streamProbe.LastKnown(streamUrl, programme) : null;
if (known != null && !probe.IsCompleted)
{
streams = known; // Do not delay an outage slate by another full metadata timeout.
_ = probe.ContinueWith(t => { _ = t.Exception; }, TaskContinuationOptions.OnlyOnFaulted);
}
else streams = await (_feedback == null ? probe : _feedback.AwaitStream(probe, feedback, cancellationToken)).ConfigureAwait(false);
}
catch (Exception) when (useSlates && !cancellationToken.IsCancellationRequested)
{
streams = _streamProbe.LastKnown(streamUrl, programme);
_logger.LogWarning("[Enigma2] Broadcast track analysis unavailable; keeping continuity with {MetadataState} metadata", streams == null ? "unknown" : "last-known");
}
// Rich programs use one explicitly ordered local transport, so native
// Jellyfin maps the chosen language/subtitle instead of auto-selecting audio and adding -sn.
var richProgram = streams != null && (streams.Count(s => s.Type == MediaStreamType.Audio) > 1 || streams.Any(s => s.Type == MediaStreamType.Subtitle));
if (_continuity != null && (useSlates || richProgram))
{
feedback?.Report("waiting_for_stream");
var tracks = streams == null ? BroadcastTracks.Fallback(Plugin.Instance.Configuration.PreserveSourceResolution)
: new BroadcastTracks(streams, useSlates, Plugin.Instance.Configuration.PreserveSourceResolution);
return await _continuity.Open(streamUrl, feedback?.Language ?? "en", cancellationToken, tracks, useSlates).ConfigureAwait(false);
}
// A live TS may enumerate its EPG/data PID before AV on the next open.
// Jellyfin maps positions in MediaStreams rather than MPEG-TS PID values.