Record coordinated reception results and prepare scoped web H264 option
This commit is contained in:
@@ -1,9 +1,39 @@
|
||||
// Jellyfin Web's supported window plugin API supplies the native playback manager.
|
||||
window.DecoderChannelPlayback = async () => class DecoderChannelPlayback {
|
||||
constructor({ playbackManager, toast, appRouter, loading, events }) {
|
||||
constructor({ playbackManager, toast, appRouter, loading, events, appHost }) {
|
||||
this.id = 'decoder-channel-playback';
|
||||
this.name = 'Decoder channel playback';
|
||||
this.type = 'integration';
|
||||
// Limit only this provider's web live TV negotiation, preserving the shared client profile.
|
||||
if (appHost?.getDeviceProfile && !appHost.getDeviceProfile.decoderH264Policy) {
|
||||
const originalProfile = appHost.getDeviceProfile;
|
||||
const getDeviceProfile = async function (item, options) {
|
||||
const profile = await originalProfile.call(this, item, options);
|
||||
const api = window.ApiClient;
|
||||
if (!profile || item?.Type !== 'TvChannel' || window.NativeShell ||
|
||||
playbackManager.getCurrentPlayer()?.isLocalPlayer === false || !api?.getCurrentUserId() ||
|
||||
(item.ServerId && item.ServerId !== api.serverId())) return profile;
|
||||
try {
|
||||
// Fresh policy per negotiation; an unavailable endpoint preserves native behavior.
|
||||
let timeout;
|
||||
const request = api.ajax({ type: 'GET', dataType: 'json',
|
||||
url: api.getUrl('DecoderIntegration/WebPlaybackPolicy', { channelId: item.Id }) });
|
||||
const policy = await Promise.race([request, new Promise(resolve => { timeout = setTimeout(() => resolve(null), 2000); })])
|
||||
.finally(() => clearTimeout(timeout));
|
||||
if (!policy?.IsEnigmaChannel || !policy.PreferH264) return profile;
|
||||
const video = p => p.Type === 'Video' && (!p.Context || p.Context === 'Streaming');
|
||||
const h264 = p => (p.VideoCodec || '').split(',').some(c => c.trim().toLowerCase() === 'h264');
|
||||
if (!profile.TranscodingProfiles?.some(p => video(p) && h264(p))) return profile;
|
||||
const copy = JSON.parse(JSON.stringify(profile));
|
||||
copy.TranscodingProfiles = copy.TranscodingProfiles.filter(p => !video(p) || h264(p))
|
||||
.map(p => video(p) ? { ...p, VideoCodec: 'h264' } : p);
|
||||
return copy;
|
||||
} catch { return profile; }
|
||||
};
|
||||
getDeviceProfile.decoderH264Policy = true;
|
||||
try { appHost.getDeviceProfile = getDeviceProfile; }
|
||||
catch { /* A client exposing a read-only host keeps its native negotiation. */ }
|
||||
}
|
||||
let generation = 0, starting = null, cancelButton = null, watcher = null;
|
||||
const clearControls = () => { clearInterval(watcher); watcher = null; cancelButton?.remove(); cancelButton = null; };
|
||||
events.on(playbackManager, 'playbackstop', () => { if (!starting) clearControls(); });
|
||||
|
||||
Reference in New Issue
Block a user