make target bitrate whatever the input bitrate is

This commit is contained in:
matty 2024-09-10 23:26:38 -04:00
parent 016b5600e4
commit 98c7fc5eac
1 changed files with 323 additions and 299 deletions

622
dist/main.js vendored
View File

@ -11,349 +11,373 @@ const DEFAULT_CQ_H264 = 26;
const DEFAULT_CQ_HEVC = 28; const DEFAULT_CQ_HEVC = 28;
const DEFAULT_H264_PROFILE = "main"; const DEFAULT_H264_PROFILE = "main";
const DEFAULT_BITRATES = new Map([ const DEFAULT_BITRATES = new Map([
[0, 64 * 1000], [0, 64 * 1000],
[144, 320 * 1000], [144, 320 * 1000],
[360, 780 * 1000], [360, 780 * 1000],
[480, 1500 * 1000], [480, 1500 * 1000],
[720, 2800 * 1000], [720, 2800 * 1000],
[1080, 5200 * 1000], [1080, 5200 * 1000],
[1440, 10000 * 1000], [1440, 10000 * 1000],
[2160, 22000 * 1000] [2160, 22000 * 1000],
]); ]);
let pluginSettings = { let pluginSettings = {
hardwareDecode: DEFAULT_HARDWARE_DECODE, hardwareDecode: DEFAULT_HARDWARE_DECODE,
vodQuality: DEFAULT_VOD_QUALITY, vodQuality: DEFAULT_VOD_QUALITY,
liveQuality: DEFAULT_LIVE_QUALITY, liveQuality: DEFAULT_LIVE_QUALITY,
hevcProfile: DEFAULT_HEVC_PROFILE, hevcProfile: DEFAULT_HEVC_PROFILE,
cqH264: DEFAULT_CQ_H264, cqH264: DEFAULT_CQ_H264,
cqHEVC: DEFAULT_CQ_HEVC, cqHEVC: DEFAULT_CQ_HEVC,
h264Profile: DEFAULT_H264_PROFILE, h264Profile: DEFAULT_H264_PROFILE,
baseBitrate: new Map(DEFAULT_BITRATES) baseBitrate: new Map(DEFAULT_BITRATES),
}; };
let latestStreamNum = 9999; let latestStreamNum = 9999;
async function register({ settingsManager, peertubeHelpers, transcodingManager: transcode, registerSetting }) { async function register({
logger = peertubeHelpers.logger; settingsManager,
transcodingManager = transcode; peertubeHelpers,
logger.info("Registering peertube-plugin-nctv-hardware-encode"); transcodingManager: transcode,
const encoder = 'h264_nvenc'; registerSetting,
const hevc = 'hevc_nvenc'; }) {
const profileName = 'nctv-nvenc'; logger = peertubeHelpers.logger;
const hevcProfile = 'nctv-hevc'; transcodingManager = transcode;
transcodingManager.addVODProfile(encoder, profileName, vodBuilder); logger.info("Registering peertube-plugin-nctv-hardware-encode");
transcodingManager.addVODEncoderPriority('video', encoder, 1000); const encoder = "h264_nvenc";
const hevc = "hevc_nvenc";
const profileName = "nctv-nvenc";
const hevcProfile = "nctv-hevc";
transcodingManager.addVODProfile(encoder, profileName, vodBuilder);
transcodingManager.addVODEncoderPriority("video", encoder, 1000);
transcodingManager.addLiveProfile(encoder, profileName, liveBuilder); transcodingManager.addLiveProfile(encoder, profileName, liveBuilder);
transcodingManager.addLiveEncoderPriority('video', encoder, 1000); transcodingManager.addLiveEncoderPriority("video", encoder, 1000);
transcodingManager.addVODProfile(hevc, hevcProfile, hevcVODBuilder); transcodingManager.addVODProfile(hevc, hevcProfile, hevcVODBuilder);
transcodingManager.addVODEncoderPriority('video', hevc, 900); transcodingManager.addVODEncoderPriority("video", hevc, 900);
transcodingManager.addLiveProfile(hevc, hevcProfile, hevcLiveBuilder); transcodingManager.addLiveProfile(hevc, hevcProfile, hevcLiveBuilder);
transcodingManager.addLiveEncoderPriority('video', hevc, 900); transcodingManager.addLiveEncoderPriority("video", hevc, 900);
await loadSettings(settingsManager); await loadSettings(settingsManager);
registerSetting({
name: "hardware-decode",
label: "Hardware decode",
type: "input-checkbox",
descriptionHTML:
"Use hardware video decoder instead of software decoder. This will slightly improve performance but may cause some issues with some videos. If you encounter issues, disable this option and restart failed jobs.",
default: DEFAULT_HARDWARE_DECODE,
private: false,
});
registerSetting({
name: "cq-h264",
label: "CQ Value for H264_nvenc",
type: "input",
descriptionHTML:
"Sets the -cq value for h264_nvenc encoder. Valid values are between 0 and 51 (lossess and AIDS, respectively)",
default: DEFAULT_CQ_H264,
private: false,
});
registerSetting({
name: "cq-hevc",
label: "CQ Value for hevc_nvenc",
type: "input",
descriptionHTML:
"Sets the -cq value for hevc_nvenc encoder. Valid values are between 0 and 51 (lossess and AIDS, respectively)",
default: DEFAULT_CQ_HEVC,
private: false,
});
registerSetting({
name: "vod-quality",
label: "VOD Quality",
type: "select",
options: [
{ label: "fastest", value: "p1" },
{ label: "faster", value: "p2" },
{ label: "fast", value: "p3" },
{ label: "medium (default)", value: "p4" },
{ label: "slow", value: "p5" },
{ label: "slower", value: "p6" },
{ label: "slowest", value: "p7" },
],
descriptionHTML:
"This parameter controls the speed / quality tradeoff. Slower speed mean better quality. Faster speed mean lower quality. This setting is hardware dependent, you may need to experiment to find the best value for your hardware.",
default: DEFAULT_VOD_QUALITY.toString(),
private: false,
});
registerSetting({
name: "hevc-profile",
label: "HEVC Profile",
type: "select",
options: [
{ label: "main (default)", value: "main" },
{ label: "main10", value: "main10" },
{ label: "rext", value: "rext" },
],
descriptionHTML: "Set the HEVC profile",
default: DEFAULT_HEVC_PROFILE.toString(),
private: false,
});
registerSetting({
name: "h264-profile",
label: "H264 Profile",
type: "select",
options: [
{ label: "main (default)", value: "main" },
{ label: "high", value: "high" },
{ label: "high444p", value: "high444p" },
],
descriptionHTML: "Set the H264 profile",
default: DEFAULT_H264_PROFILE.toString(),
private: false,
});
registerSetting({
name: "live-quality",
label: "Live Quality",
type: "select",
options: [
{ label: "low latency", value: "ll" },
{ label: "high quality (default)", value: "hq" },
{ label: "low latency high performance", value: "ull" },
],
descriptionHTML:
"This parameter controls the speed / quality tradeoff. High performance mean lower quality.",
default: DEFAULT_LIVE_QUALITY.toString(),
private: false,
});
registerSetting({
name: "base-bitrate-description",
label: "Base bitrate",
type: "html",
html: "",
descriptionHTML: `The base bitrate for video in bits. We take the min bitrate between the bitrate setting and video bitrate.<br/>This is the bitrate used when the video is transcoded at 30 FPS. The bitrate will be scaled linearly between this value and the maximum bitrate when the video is transcoded at 60 FPS. Wrong values are replaced by default values.`,
private: true,
});
for (const [resolution, bitrate] of pluginSettings.baseBitrate) {
logger.info("registering bitrate setting: " + bitrate.toString());
registerSetting({ registerSetting({
name: 'hardware-decode', name: `base-bitrate-${resolution}`,
label: 'Hardware decode', label: `Base bitrate for ${printResolution(resolution)}`,
type: 'input-checkbox', type: "input",
descriptionHTML: 'Use hardware video decoder instead of software decoder. This will slightly improve performance but may cause some issues with some videos. If you encounter issues, disable this option and restart failed jobs.', default: DEFAULT_BITRATES.get(resolution)?.toString(),
default: DEFAULT_HARDWARE_DECODE, descriptionHTML: `Default value: ${DEFAULT_BITRATES.get(resolution)}`,
private: false private: false,
});
registerSetting({
name: 'cq-h264',
label: 'CQ Value for H264_nvenc',
type: 'input',
descriptionHTML: 'Sets the -cq value for h264_nvenc encoder. Valid values are between 0 and 51 (lossess and AIDS, respectively)',
default: DEFAULT_CQ_H264,
private: false
});
registerSetting({
name: 'cq-hevc',
label: 'CQ Value for hevc_nvenc',
type: 'input',
descriptionHTML: 'Sets the -cq value for hevc_nvenc encoder. Valid values are between 0 and 51 (lossess and AIDS, respectively)',
default: DEFAULT_CQ_HEVC,
private: false
});
registerSetting({
name: 'vod-quality',
label: 'VOD Quality',
type: 'select',
options: [
{ label: 'fastest', value: 'p1' },
{ label: 'faster', value: 'p2' },
{ label: 'fast', value: 'p3' },
{ label: 'medium (default)', value: 'p4' },
{ label: 'slow', value: 'p5' },
{ label: 'slower', value: 'p6' },
{ label: 'slowest', value: 'p7' }
],
descriptionHTML: 'This parameter controls the speed / quality tradeoff. Slower speed mean better quality. Faster speed mean lower quality. This setting is hardware dependent, you may need to experiment to find the best value for your hardware.',
default: DEFAULT_VOD_QUALITY.toString(),
private: false
});
registerSetting({
name: 'hevc-profile',
label: 'HEVC Profile',
type: 'select',
options: [
{ label: 'main (default)', value: 'main' },
{ label: 'main10', value: 'main10' },
{ label: 'rext', value: 'rext' }
],
descriptionHTML: 'Set the HEVC profile',
default: DEFAULT_HEVC_PROFILE.toString(),
private: false
});
registerSetting({
name: 'h264-profile',
label: 'H264 Profile',
type: 'select',
options: [
{ label: 'main (default)', value: 'main' },
{ label: 'high', value: 'high' },
{ label: 'high444p', value: 'high444p' }
],
descriptionHTML: 'Set the H264 profile',
default: DEFAULT_H264_PROFILE.toString(),
private: false
});
registerSetting({
name: 'live-quality',
label: 'Live Quality',
type: 'select',
options: [
{ label: 'low latency', value: 'll' },
{ label: 'high quality (default)', value: 'hq' },
{ label: 'low latency high performance', value: 'ull' }
],
descriptionHTML: 'This parameter controls the speed / quality tradeoff. High performance mean lower quality.',
default: DEFAULT_LIVE_QUALITY.toString(),
private: false
});
registerSetting({
name: 'base-bitrate-description',
label: 'Base bitrate',
type: 'html',
html: '',
descriptionHTML: `The base bitrate for video in bits. We take the min bitrate between the bitrate setting and video bitrate.<br/>This is the bitrate used when the video is transcoded at 30 FPS. The bitrate will be scaled linearly between this value and the maximum bitrate when the video is transcoded at 60 FPS. Wrong values are replaced by default values.`,
private: true,
});
for (const [resolution, bitrate] of pluginSettings.baseBitrate) {
logger.info("registering bitrate setting: " + bitrate.toString());
registerSetting({
name: `base-bitrate-${resolution}`,
label: `Base bitrate for ${printResolution(resolution)}`,
type: 'input',
default: DEFAULT_BITRATES.get(resolution)?.toString(),
descriptionHTML: `Default value: ${DEFAULT_BITRATES.get(resolution)}`,
private: false
});
}
settingsManager.onSettingsChange(async (settings) => {
loadSettings(settingsManager);
}); });
}
settingsManager.onSettingsChange(async (settings) => {
loadSettings(settingsManager);
});
} }
exports.register = register; exports.register = register;
async function unregister() { async function unregister() {
logger.info("Unregistering peertube-plugin-nctv-hardware-encode"); logger.info("Unregistering peertube-plugin-nctv-hardware-encode");
transcodingManager.removeAllProfilesAndEncoderPriorities(); transcodingManager.removeAllProfilesAndEncoderPriorities();
return true; return true;
} }
exports.unregister = unregister; exports.unregister = unregister;
async function loadSettings(settingsManager) { async function loadSettings(settingsManager) {
pluginSettings.hardwareDecode = await settingsManager.getSetting('hardware-decode') || DEFAULT_HARDWARE_DECODE; pluginSettings.hardwareDecode =
pluginSettings.vodQuality = await settingsManager.getSetting('vod-quality') || DEFAULT_VOD_QUALITY; (await settingsManager.getSetting("hardware-decode")) ||
pluginSettings.liveQuality = await settingsManager.getSetting('live-quality') || DEFAULT_LIVE_QUALITY; DEFAULT_HARDWARE_DECODE;
pluginSettings.hevcProfile = await settingsManager.getSetting('hevc-profile') || DEFAULT_HEVC_PROFILE; pluginSettings.vodQuality =
pluginSettings.cqH264 = parseInt(await settingsManager.getSetting('cq-h264')) || DEFAULT_CQ_H264; (await settingsManager.getSetting("vod-quality")) || DEFAULT_VOD_QUALITY;
pluginSettings.cqHEVC = parseInt(await settingsManager.getSetting('cq-hevc')) || DEFAULT_CQ_HEVC; pluginSettings.liveQuality =
pluginSettings.h264Profile = await settingsManager.getSetting('h264-profile') || DEFAULT_H264_PROFILE; (await settingsManager.getSetting("live-quality")) || DEFAULT_LIVE_QUALITY;
pluginSettings.hevcProfile =
(await settingsManager.getSetting("hevc-profile")) || DEFAULT_HEVC_PROFILE;
pluginSettings.cqH264 =
parseInt(await settingsManager.getSetting("cq-h264")) || DEFAULT_CQ_H264;
pluginSettings.cqHEVC =
parseInt(await settingsManager.getSetting("cq-hevc")) || DEFAULT_CQ_HEVC;
pluginSettings.h264Profile =
(await settingsManager.getSetting("h264-profile")) || DEFAULT_H264_PROFILE;
for (const [resolution, bitrate] of DEFAULT_BITRATES) { for (const [resolution, bitrate] of DEFAULT_BITRATES) {
const key = `base-bitrate-${resolution}`; const key = `base-bitrate-${resolution}`;
const storedValue = await settingsManager.getSetting(key); const storedValue = await settingsManager.getSetting(key);
pluginSettings.baseBitrate.set(resolution, parseInt(storedValue) || bitrate); pluginSettings.baseBitrate.set(
logger.info(`Bitrate ${printResolution(resolution)}: ${pluginSettings.baseBitrate.get(resolution)}`); resolution,
} parseInt(storedValue) || bitrate
logger.info(`Hardware decode: ${pluginSettings.hardwareDecode}`); );
logger.info(`VOD Quality: ${pluginSettings.vodQuality}`); logger.info(
logger.info(`Live Quality: ${pluginSettings.liveQuality}`); `Bitrate ${printResolution(resolution)}: ${pluginSettings.baseBitrate.get(
logger.info(`HEVC profile: ${pluginSettings.hevcProfile}`); resolution
logger.info(`H264 profile: ${pluginSettings.h264Profile}`); )}`
);
}
logger.info(`Hardware decode: ${pluginSettings.hardwareDecode}`);
logger.info(`VOD Quality: ${pluginSettings.vodQuality}`);
logger.info(`Live Quality: ${pluginSettings.liveQuality}`);
logger.info(`HEVC profile: ${pluginSettings.hevcProfile}`);
logger.info(`H264 profile: ${pluginSettings.h264Profile}`);
} }
function printResolution(resolution) { function printResolution(resolution) {
switch (resolution) { switch (resolution) {
case 0: return 'audio only'; case 0:
case 144: return "audio only";
case 360: case 144:
case 480: case 360:
case 720: case 480:
case 1080: case 720:
case 1440: case 1080:
return `${resolution}p`; case 1440:
case 2160: return '4K'; return `${resolution}p`;
default: return 'Unknown'; case 2160:
} return "4K";
default:
return "Unknown";
}
} }
function buildInitOptions() { function buildInitOptions() {
if (pluginSettings.hardwareDecode) { if (pluginSettings.hardwareDecode) {
return [ return ["-hwaccel cuda", "-hwaccel_output_format cuda"];
'-hwaccel cuda', } else {
'-hwaccel_output_format cuda' return ["-hwaccel cuda"];
]; }
}
else {
return [
'-hwaccel cuda'
];
}
} }
//H264_NVENC VOD BUILDER //H264_NVENC VOD BUILDER
async function vodBuilder(params) { async function vodBuilder(params) {
const { resolution, fps, streamNum, inputBitrate } = params; const { resolution, fps, streamNum, inputBitrate } = params;
const streamSuffix = streamNum == undefined ? '' : `:${streamNum}`; const streamSuffix = streamNum == undefined ? "" : `:${streamNum}`;
let targetBitrate = getTargetBitrate(resolution, fps); // let targetBitrate = getTargetBitrate(resolution, fps);
// let targetBitrate = inputBitrate; let targetBitrate = inputBitrate;
let shouldInitVaapi = (streamNum == undefined || streamNum <= latestStreamNum); let shouldInitVaapi = streamNum == undefined || streamNum <= latestStreamNum;
if (targetBitrate > inputBitrate) { // if (targetBitrate > inputBitrate) {
targetBitrate = inputBitrate; // targetBitrate = inputBitrate;
} // }
logger.info(`Building encoder options, received ${JSON.stringify(params)}`); logger.info(`Building encoder options, received ${JSON.stringify(params)}`);
if (shouldInitVaapi && streamNum != undefined) { if (shouldInitVaapi && streamNum != undefined) {
latestStreamNum = streamNum; latestStreamNum = streamNum;
} }
let options = { let options = {
scaleFilter: { scaleFilter: {
name: 'scale' name: "scale",
}, },
inputOptions: shouldInitVaapi ? buildInitOptions() : [], inputOptions: shouldInitVaapi ? buildInitOptions() : [],
outputOptions: [ outputOptions: [
`-preset ${pluginSettings.vodQuality}`, `-preset ${pluginSettings.vodQuality}`,
`-b:v${streamSuffix} ${targetBitrate}`, `-b:v${streamSuffix} ${targetBitrate}`,
`-bufsize ${targetBitrate * 2}`, `-bufsize ${targetBitrate * 2}`,
`-profile:v${streamSuffix} ${pluginSettings.h264Profile}`, `-profile:v${streamSuffix} ${pluginSettings.h264Profile}`,
`-cq ${pluginSettings.cqH264}`, `-cq ${pluginSettings.cqH264}`,
`-bf 4` `-bf 4`,
] ],
}; };
logger.info(`EncoderOptions: ${JSON.stringify(options)}, HEVC: false`); logger.info(`EncoderOptions: ${JSON.stringify(options)}, HEVC: false`);
return options; return options;
} }
//H264 Live builder //H264 Live builder
async function liveBuilder(params) { async function liveBuilder(params) {
const { resolution, fps, streamNum, inputBitrate } = params; const { resolution, fps, streamNum, inputBitrate } = params;
const streamSuffix = streamNum == undefined ? '' : `:${streamNum}`; const streamSuffix = streamNum == undefined ? "" : `:${streamNum}`;
let targetBitrate = getTargetBitrate(resolution, fps); //let targetBitrate = getTargetBitrate(resolution, fps);
let shouldInitVaapi = (streamNum == undefined || streamNum <= latestStreamNum); let targetBitrate = inputBitrate;
if (targetBitrate > inputBitrate) { let shouldInitVaapi = streamNum == undefined || streamNum <= latestStreamNum;
targetBitrate = inputBitrate; //if (targetBitrate > inputBitrate) {
} // targetBitrate = inputBitrate;
logger.info(`Building encoder options, received ${JSON.stringify(params)}`); // }
if (shouldInitVaapi && streamNum != undefined) { logger.info(`Building encoder options, received ${JSON.stringify(params)}`);
latestStreamNum = streamNum; if (shouldInitVaapi && streamNum != undefined) {
} latestStreamNum = streamNum;
}
let options = { let options = {
scaleFilter: { scaleFilter: {
name: 'scale' name: "scale",
}, },
inputOptions: shouldInitVaapi ? buildInitOptions() : [], inputOptions: shouldInitVaapi ? buildInitOptions() : [],
outputOptions: [ outputOptions: [
`-tune ${pluginSettings.liveQuality}`, `-tune ${pluginSettings.liveQuality}`,
`-r:v${streamSuffix} ${fps}`, `-r:v${streamSuffix} ${fps}`,
`-profile:v${streamSuffix} ${pluginSettings.h264Profile}`, `-profile:v${streamSuffix} ${pluginSettings.h264Profile}`,
`-cq ${pluginSettings.cqH264}`, `-cq ${pluginSettings.cqH264}`,
`-g:v${streamSuffix} ${fps * 2}`, `-g:v${streamSuffix} ${fps * 2}`,
`-b:v${streamSuffix} ${targetBitrate}`, `-b:v${streamSuffix} ${targetBitrate}`,
`-bufsize ${targetBitrate * 2}`, `-bufsize ${targetBitrate * 2}`,
`-bf 4` `-bf 4`,
] ],
}; };
logger.info(`EncoderOptions: ${JSON.stringify(options)}, HEVC: false`); logger.info(`EncoderOptions: ${JSON.stringify(options)}, HEVC: false`);
return options; return options;
} }
//HEVC VOD builder //HEVC VOD builder
async function hevcVODBuilder(params) { async function hevcVODBuilder(params) {
const { resolution, fps, streamNum, inputBitrate } = params; const { resolution, fps, streamNum, inputBitrate } = params;
const streamSuffix = streamNum == undefined ? '' : `:${streamNum}`; const streamSuffix = streamNum == undefined ? "" : `:${streamNum}`;
let targetBitrate = getTargetBitrate(resolution, fps); // let targetBitrate = getTargetBitrate(resolution, fps);
// let targetBitrate = inputBitrate; let targetBitrate = inputBitrate;
let shouldInitVaapi = (streamNum == undefined || streamNum <= latestStreamNum); let shouldInitVaapi = streamNum == undefined || streamNum <= latestStreamNum;
if (targetBitrate > inputBitrate) { // if (targetBitrate > inputBitrate) {
targetBitrate = inputBitrate; // targetBitrate = inputBitrate;
} // }
logger.info(`Building encoder options, received ${JSON.stringify(params)}`); logger.info(`Building encoder options, received ${JSON.stringify(params)}`);
if (shouldInitVaapi && streamNum != undefined) { if (shouldInitVaapi && streamNum != undefined) {
latestStreamNum = streamNum; latestStreamNum = streamNum;
} }
let options = { let options = {
scaleFilter: { scaleFilter: {
name: 'scale' name: "scale",
}, },
inputOptions: shouldInitVaapi ? buildInitOptions() : [], inputOptions: shouldInitVaapi ? buildInitOptions() : [],
outputOptions: [ outputOptions: [
`-preset ${pluginSettings.vodQuality}`, `-preset ${pluginSettings.vodQuality}`,
`-b:v${streamSuffix} ${targetBitrate}`, `-b:v${streamSuffix} ${targetBitrate}`,
`-bufsize ${targetBitrate * 2}`, `-bufsize ${targetBitrate * 2}`,
`-profile:v${streamSuffix} ${pluginSettings.hevcProfile}`, `-profile:v${streamSuffix} ${pluginSettings.hevcProfile}`,
`-cq ${pluginSettings.cqHEVC}` `-cq ${pluginSettings.cqHEVC}`,
] ],
}; };
logger.info(`EncoderOptions: ${JSON.stringify(options)}, HEVC: true`);
return options;
logger.info(`EncoderOptions: ${JSON.stringify(options)}, HEVC: true`);
return options;
} }
//HEVC Live builder //HEVC Live builder
async function hevcLiveBuilder(params) { async function hevcLiveBuilder(params) {
const { resolution, fps, streamNum, inputBitrate } = params; const { resolution, fps, streamNum, inputBitrate } = params;
const streamSuffix = streamNum == undefined ? '' : `:${streamNum}`; const streamSuffix = streamNum == undefined ? "" : `:${streamNum}`;
let targetBitrate = getTargetBitrate(resolution, fps); // let targetBitrate = getTargetBitrate(resolution, fps);
// let targetBitrate = inputBitrate; let targetBitrate = inputBitrate;
let shouldInitVaapi = (streamNum == undefined || streamNum <= latestStreamNum); let shouldInitVaapi = streamNum == undefined || streamNum <= latestStreamNum;
if (targetBitrate > inputBitrate) { // if (targetBitrate > inputBitrate) {
targetBitrate = inputBitrate; // targetBitrate = inputBitrate;
} // }
logger.info(`Building encoder options, received ${JSON.stringify(params)}`); logger.info(`Building encoder options, received ${JSON.stringify(params)}`);
if (shouldInitVaapi && streamNum != undefined) { if (shouldInitVaapi && streamNum != undefined) {
latestStreamNum = streamNum; latestStreamNum = streamNum;
} }
let options = { let options = {
scaleFilter: { scaleFilter: {
name: 'scale' name: "scale",
}, },
inputOptions: shouldInitVaapi ? buildInitOptions() : [], inputOptions: shouldInitVaapi ? buildInitOptions() : [],
outputOptions: [ outputOptions: [
`-tune ${pluginSettings.liveQuality}`, `-tune ${pluginSettings.liveQuality}`,
`-r:v${streamSuffix} ${fps}`, `-r:v${streamSuffix} ${fps}`,
`-profile:v${streamSuffix} ${pluginSettings.hevcProfile}`, `-profile:v${streamSuffix} ${pluginSettings.hevcProfile}`,
`-g:v${streamSuffix} ${fps * 2}`, `-g:v${streamSuffix} ${fps * 2}`,
`-b:v${streamSuffix} ${targetBitrate}`, `-b:v${streamSuffix} ${targetBitrate}`,
`-cq ${pluginSettings.cqHEVC}`, `-cq ${pluginSettings.cqHEVC}`,
`-bufsize ${targetBitrate * 2}` `-bufsize ${targetBitrate * 2}`,
] ],
}; };
logger.info(`EncoderOptions: ${JSON.stringify(options)}, HEVC: true`); logger.info(`EncoderOptions: ${JSON.stringify(options)}, HEVC: true`);
return options; return options;
} }
function getTargetBitrate(resolution, fps) { function getTargetBitrate(resolution, fps) {
const baseBitrate = pluginSettings.baseBitrate.get(resolution) || 0; const baseBitrate = pluginSettings.baseBitrate.get(resolution) || 0;
const maxBitrate = baseBitrate * 1.6; const maxBitrate = baseBitrate * 1.6;
const maxBitrateDifference = maxBitrate - baseBitrate; const maxBitrateDifference = maxBitrate - baseBitrate;
const maxFpsDifference = 60 - 30; const maxFpsDifference = 60 - 30;
return Math.floor(baseBitrate + (fps - 30) * (maxBitrateDifference / maxFpsDifference)); return Math.floor(
baseBitrate + (fps - 30) * (maxBitrateDifference / maxFpsDifference)
);
} }
//# sourceMappingURL=main.js.map //# sourceMappingURL=main.js.map