diff --git a/engine/server.ts b/engine/server.ts index 081cbc4a..f88f98bd 100644 --- a/engine/server.ts +++ b/engine/server.ts @@ -98,6 +98,8 @@ export interface ChannelProfile { bw: number; codecs: string; resolution: number[]; + videoRange?: string; + frameRate?: number; } export interface Channel { diff --git a/engine/session.js b/engine/session.js index 0663a5ae..2b8c1c07 100644 --- a/engine/session.js +++ b/engine/session.js @@ -993,7 +993,18 @@ class Session { const audioCodec = profile.codecs.split(",")[1]; return id.match(audioCodec); }); - m3u8 += '#EXT-X-STREAM-INF:BANDWIDTH=' + profile.bw + ',RESOLUTION=' + profile.resolution[0] + 'x' + profile.resolution[1] + ',CODECS="' + profile.codecs + '"' + (audioGroupId ? `,AUDIO="${audioGroupId}"` : '') + (hasClosedCaptions ? ',CLOSED-CAPTIONS="cc"' : '') + '\n'; + let videoRange = "SDR"; + if (profile.videoRange) { + videoRange = profile.videoRange; + } + + m3u8 += '#EXT-X-STREAM-INF:BANDWIDTH=' + profile.bw + + ',RESOLUTION=' + profile.resolution[0] + 'x' + profile.resolution[1] + + ',CODECS="' + profile.codecs + '"' + + ',VIDEO-RANGE="' + videoRange + '"' + + (profile.frameRate ? `,FRAME-RATE=${profile.frameRate.toFixed(3)}` : '') + + (audioGroupId ? `,AUDIO="${audioGroupId}"` : '') + + (hasClosedCaptions ? ',CLOSED-CAPTIONS="cc"' : '') + '\n'; m3u8 += "master" + profile.bw + ".m3u8;session=" + this._sessionId + "\n"; }); } else { diff --git a/server-uhd.ts b/server-uhd.ts index 051b7bfd..c7e95591 100644 --- a/server-uhd.ts +++ b/server-uhd.ts @@ -70,7 +70,8 @@ class RefChannelManager implements IChannelManager { _getProfile(): ChannelProfile[] { return [ { resolution: [1280, 720], bw: 3725519, codecs: "avc1.64001F,mp4a.40.2" }, - { resolution: [1280, 720], bw: 5903428, codecs: "avc1.64001F,ac-3" } + { resolution: [1280, 720], bw: 5903428, codecs: "avc1.64001F,ac-3" }, + { resolution: [1280, 720], bw: 6676458, videoRange: "PQ", frameRate: 24.000, codecs: "hvc1.2.4.L93.90,mp4a.40.2" }, ]; }