Compare commits
No commits in common. "main" and "add-h264-profile" have entirely different histories.
main
...
add-h264-p
7
LICENSE
7
LICENSE
@ -1,6 +1,7 @@
|
|||||||
MIT+NIGGER License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) NiceCrew Technologies
|
Copyright (c) 2023 Ryan He
|
||||||
|
Copyright (c) 2021 Théo Le Calvar
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -12,8 +13,6 @@ furnished to do so, subject to the following conditions:
|
|||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all
|
||||||
copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
The above copyright notice, this permission notice and the word "NIGGER" shall be included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
310
dist/main.js
vendored
310
dist/main.js
vendored
@ -18,7 +18,7 @@ const DEFAULT_BITRATES = new Map([
|
|||||||
[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,
|
||||||
@ -28,124 +28,114 @@ let pluginSettings = {
|
|||||||
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({
|
async function register({ settingsManager, peertubeHelpers, transcodingManager: transcode, registerSetting }) {
|
||||||
settingsManager,
|
|
||||||
peertubeHelpers,
|
|
||||||
transcodingManager: transcode,
|
|
||||||
registerSetting,
|
|
||||||
}) {
|
|
||||||
logger = peertubeHelpers.logger;
|
logger = peertubeHelpers.logger;
|
||||||
transcodingManager = transcode;
|
transcodingManager = transcode;
|
||||||
logger.info("Registering peertube-plugin-nctv-hardware-encode");
|
logger.info("Registering peertube-plugin-nctv-hardware-encode");
|
||||||
const encoder = "h264_nvenc";
|
const encoder = 'h264_nvenc';
|
||||||
const hevc = "hevc_nvenc";
|
const hevc = 'hevc_nvenc';
|
||||||
const profileName = "nctv-nvenc";
|
const profileName = 'nctv-nvenc';
|
||||||
const hevcProfile = "nctv-hevc";
|
const hevcProfile = 'nctv-hevc';
|
||||||
transcodingManager.addVODProfile(encoder, profileName, vodBuilder);
|
transcodingManager.addVODProfile(encoder, profileName, vodBuilder);
|
||||||
transcodingManager.addVODEncoderPriority("video", encoder, 1000);
|
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({
|
registerSetting({
|
||||||
name: "hardware-decode",
|
name: 'hardware-decode',
|
||||||
label: "Hardware decode",
|
label: 'Hardware decode',
|
||||||
type: "input-checkbox",
|
type: 'input-checkbox',
|
||||||
descriptionHTML:
|
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.',
|
||||||
"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,
|
default: DEFAULT_HARDWARE_DECODE,
|
||||||
private: false,
|
private: false
|
||||||
});
|
});
|
||||||
registerSetting({
|
registerSetting({
|
||||||
name: "cq-h264",
|
name: 'cq-h264',
|
||||||
label: "CQ Value for H264_nvenc",
|
label: 'CQ Value for H264_nvenc',
|
||||||
type: "input",
|
type: 'input',
|
||||||
descriptionHTML:
|
descriptionHTML: 'Sets the -cq value for h264_nvenc encoder. Valid values are between 0 and 51 (lossess and AIDS, respectively)',
|
||||||
"Sets the -cq value for h264_nvenc encoder. Valid values are between 0 and 51 (lossess and AIDS, respectively)",
|
|
||||||
default: DEFAULT_CQ_H264,
|
default: DEFAULT_CQ_H264,
|
||||||
private: false,
|
private: false
|
||||||
});
|
});
|
||||||
registerSetting({
|
registerSetting({
|
||||||
name: "cq-hevc",
|
name: 'cq-hevc',
|
||||||
label: "CQ Value for hevc_nvenc",
|
label: 'CQ Value for hevc_nvenc',
|
||||||
type: "input",
|
type: 'input',
|
||||||
descriptionHTML:
|
descriptionHTML: 'Sets the -cq value for hevc_nvenc encoder. Valid values are between 0 and 51 (lossess and AIDS, respectively)',
|
||||||
"Sets the -cq value for hevc_nvenc encoder. Valid values are between 0 and 51 (lossess and AIDS, respectively)",
|
|
||||||
default: DEFAULT_CQ_HEVC,
|
default: DEFAULT_CQ_HEVC,
|
||||||
private: false,
|
private: false
|
||||||
});
|
});
|
||||||
registerSetting({
|
registerSetting({
|
||||||
name: "vod-quality",
|
name: 'vod-quality',
|
||||||
label: "VOD Quality",
|
label: 'VOD Quality',
|
||||||
type: "select",
|
type: 'select',
|
||||||
options: [
|
options: [
|
||||||
{ label: "fastest", value: "p1" },
|
{ label: 'fastest', value: 'p1' },
|
||||||
{ label: "faster", value: "p2" },
|
{ label: 'faster', value: 'p2' },
|
||||||
{ label: "fast", value: "p3" },
|
{ label: 'fast', value: 'p3' },
|
||||||
{ label: "medium (default)", value: "p4" },
|
{ label: 'medium (default)', value: 'p4' },
|
||||||
{ label: "slow", value: "p5" },
|
{ label: 'slow', value: 'p5' },
|
||||||
{ label: "slower", value: "p6" },
|
{ label: 'slower', value: 'p6' },
|
||||||
{ label: "slowest", value: "p7" },
|
{ label: 'slowest', value: 'p7' }
|
||||||
],
|
],
|
||||||
descriptionHTML:
|
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.',
|
||||||
"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(),
|
default: DEFAULT_VOD_QUALITY.toString(),
|
||||||
private: false,
|
private: false
|
||||||
});
|
});
|
||||||
registerSetting({
|
registerSetting({
|
||||||
name: "hevc-profile",
|
name: 'hevc-profile',
|
||||||
label: "HEVC Profile",
|
label: 'HEVC Profile',
|
||||||
type: "select",
|
type: 'select',
|
||||||
options: [
|
options: [
|
||||||
{ label: "main (default)", value: "main" },
|
{ label: 'main (default)', value: 'main' },
|
||||||
{ label: "main10", value: "main10" },
|
{ label: 'main10', value: 'main10' },
|
||||||
{ label: "rext", value: "rext" },
|
{ label: 'rext', value: 'rext' }
|
||||||
],
|
],
|
||||||
descriptionHTML: "Set the HEVC profile",
|
descriptionHTML: 'Set the HEVC profile',
|
||||||
default: DEFAULT_HEVC_PROFILE.toString(),
|
default: DEFAULT_HEVC_PROFILE.toString(),
|
||||||
private: false,
|
private: false
|
||||||
});
|
});
|
||||||
registerSetting({
|
registerSetting({
|
||||||
name: "h264-profile",
|
name: 'h264-profile',
|
||||||
label: "H264 Profile",
|
label: 'H264 Profile',
|
||||||
type: "select",
|
type: 'select',
|
||||||
options: [
|
options: [
|
||||||
{ label: "main (default)", value: "main" },
|
{ label: 'main (default)', value: 'main' },
|
||||||
{ label: "high", value: "high" },
|
{ label: 'high', value: 'high' },
|
||||||
{ label: "high444p", value: "high444p" },
|
{ label: 'high444p', value: 'high444p' }
|
||||||
],
|
],
|
||||||
descriptionHTML: "Set the H264 profile",
|
descriptionHTML: 'Set the H264 profile',
|
||||||
default: DEFAULT_H264_PROFILE.toString(),
|
default: DEFAULT_H264_PROFILE.toString(),
|
||||||
private: false,
|
private: false
|
||||||
});
|
});
|
||||||
registerSetting({
|
registerSetting({
|
||||||
name: "live-quality",
|
name: 'live-quality',
|
||||||
label: "Live Quality",
|
label: 'Live Quality',
|
||||||
type: "select",
|
type: 'select',
|
||||||
options: [
|
options: [
|
||||||
{ label: "low latency", value: "ll" },
|
{ label: 'low latency', value: 'll' },
|
||||||
{ label: "high quality (default)", value: "hq" },
|
{ label: 'high quality (default)', value: 'hq' },
|
||||||
{ label: "low latency high performance", value: "ull" },
|
{ label: 'low latency high performance', value: 'ull' }
|
||||||
],
|
],
|
||||||
descriptionHTML:
|
descriptionHTML: 'This parameter controls the speed / quality tradeoff. High performance mean lower quality.',
|
||||||
"This parameter controls the speed / quality tradeoff. High performance mean lower quality.",
|
|
||||||
default: DEFAULT_LIVE_QUALITY.toString(),
|
default: DEFAULT_LIVE_QUALITY.toString(),
|
||||||
private: false,
|
private: false
|
||||||
});
|
});
|
||||||
registerSetting({
|
registerSetting({
|
||||||
name: "base-bitrate-description",
|
name: 'base-bitrate-description',
|
||||||
label: "Base bitrate",
|
label: 'Base bitrate',
|
||||||
type: "html",
|
type: 'html',
|
||||||
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.`,
|
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,
|
private: true,
|
||||||
});
|
});
|
||||||
@ -154,10 +144,10 @@ async function register({
|
|||||||
registerSetting({
|
registerSetting({
|
||||||
name: `base-bitrate-${resolution}`,
|
name: `base-bitrate-${resolution}`,
|
||||||
label: `Base bitrate for ${printResolution(resolution)}`,
|
label: `Base bitrate for ${printResolution(resolution)}`,
|
||||||
type: "input",
|
type: 'input',
|
||||||
default: DEFAULT_BITRATES.get(resolution)?.toString(),
|
default: DEFAULT_BITRATES.get(resolution)?.toString(),
|
||||||
descriptionHTML: `Default value: ${DEFAULT_BITRATES.get(resolution)}`,
|
descriptionHTML: `Default value: ${DEFAULT_BITRATES.get(resolution)}`,
|
||||||
private: false,
|
private: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
settingsManager.onSettingsChange(async (settings) => {
|
settingsManager.onSettingsChange(async (settings) => {
|
||||||
@ -172,34 +162,19 @@ async function unregister() {
|
|||||||
}
|
}
|
||||||
exports.unregister = unregister;
|
exports.unregister = unregister;
|
||||||
async function loadSettings(settingsManager) {
|
async function loadSettings(settingsManager) {
|
||||||
pluginSettings.hardwareDecode =
|
pluginSettings.hardwareDecode = await settingsManager.getSetting('hardware-decode') || DEFAULT_HARDWARE_DECODE;
|
||||||
(await settingsManager.getSetting("hardware-decode")) ||
|
pluginSettings.vodQuality = await settingsManager.getSetting('vod-quality') || DEFAULT_VOD_QUALITY;
|
||||||
DEFAULT_HARDWARE_DECODE;
|
pluginSettings.liveQuality = await settingsManager.getSetting('live-quality') || DEFAULT_LIVE_QUALITY;
|
||||||
pluginSettings.vodQuality =
|
pluginSettings.hevcProfile = await settingsManager.getSetting('hevc-profile') || DEFAULT_HEVC_PROFILE;
|
||||||
(await settingsManager.getSetting("vod-quality")) || DEFAULT_VOD_QUALITY;
|
pluginSettings.cqH264 = parseInt(await settingsManager.getSetting('cq-h264')) || DEFAULT_CQ_H264;
|
||||||
pluginSettings.liveQuality =
|
pluginSettings.cqHEVC = parseInt(await settingsManager.getSetting('cq-hevc')) || DEFAULT_CQ_HEVC;
|
||||||
(await settingsManager.getSetting("live-quality")) || DEFAULT_LIVE_QUALITY;
|
pluginSettings.h264Profile = await settingsManager.getSetting('h264-profile') || DEFAULT_H264_PROFILE;
|
||||||
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(
|
pluginSettings.baseBitrate.set(resolution, parseInt(storedValue) || bitrate);
|
||||||
resolution,
|
logger.info(`Bitrate ${printResolution(resolution)}: ${pluginSettings.baseBitrate.get(resolution)}`);
|
||||||
parseInt(storedValue) || bitrate
|
|
||||||
);
|
|
||||||
logger.info(
|
|
||||||
`Bitrate ${printResolution(resolution)}: ${pluginSettings.baseBitrate.get(
|
|
||||||
resolution
|
|
||||||
)}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
logger.info(`Hardware decode: ${pluginSettings.hardwareDecode}`);
|
logger.info(`Hardware decode: ${pluginSettings.hardwareDecode}`);
|
||||||
logger.info(`VOD Quality: ${pluginSettings.vodQuality}`);
|
logger.info(`VOD Quality: ${pluginSettings.vodQuality}`);
|
||||||
@ -209,8 +184,7 @@ async function loadSettings(settingsManager) {
|
|||||||
}
|
}
|
||||||
function printResolution(resolution) {
|
function printResolution(resolution) {
|
||||||
switch (resolution) {
|
switch (resolution) {
|
||||||
case 0:
|
case 0: return 'audio only';
|
||||||
return "audio only";
|
|
||||||
case 144:
|
case 144:
|
||||||
case 360:
|
case 360:
|
||||||
case 480:
|
case 480:
|
||||||
@ -218,17 +192,21 @@ function printResolution(resolution) {
|
|||||||
case 1080:
|
case 1080:
|
||||||
case 1440:
|
case 1440:
|
||||||
return `${resolution}p`;
|
return `${resolution}p`;
|
||||||
case 2160:
|
case 2160: return '4K';
|
||||||
return "4K";
|
default: return 'Unknown';
|
||||||
default:
|
|
||||||
return "Unknown";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function buildInitOptions() {
|
function buildInitOptions() {
|
||||||
if (pluginSettings.hardwareDecode) {
|
if (pluginSettings.hardwareDecode) {
|
||||||
return ["-hwaccel cuda", "-hwaccel_output_format cuda"];
|
return [
|
||||||
} else {
|
'-hwaccel cuda',
|
||||||
return ["-hwaccel cuda"];
|
'-hwaccel_output_format cuda'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return [
|
||||||
|
'-hwaccel cuda'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,10 +214,10 @@ function buildInitOptions() {
|
|||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
@ -249,7 +227,7 @@ async function vodBuilder(params) {
|
|||||||
}
|
}
|
||||||
let options = {
|
let options = {
|
||||||
scaleFilter: {
|
scaleFilter: {
|
||||||
name: "scale",
|
name: 'scale'
|
||||||
},
|
},
|
||||||
inputOptions: shouldInitVaapi ? buildInitOptions() : [],
|
inputOptions: shouldInitVaapi ? buildInitOptions() : [],
|
||||||
outputOptions: [
|
outputOptions: [
|
||||||
@ -258,45 +236,8 @@ async function vodBuilder(params) {
|
|||||||
`-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`);
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
//H264 Live builder
|
|
||||||
|
|
||||||
async function liveBuilder(params) {
|
|
||||||
const { resolution, fps, streamNum, inputBitrate } = params;
|
|
||||||
const streamSuffix = streamNum == undefined ? "" : `:${streamNum}`;
|
|
||||||
let targetBitrate = getTargetBitrate(resolution, fps);
|
|
||||||
// let targetBitrate = inputBitrate;
|
|
||||||
let shouldInitVaapi = streamNum == undefined || streamNum <= latestStreamNum;
|
|
||||||
if (targetBitrate > inputBitrate) {
|
|
||||||
targetBitrate = inputBitrate;
|
|
||||||
}
|
|
||||||
logger.info(`Building encoder options, received ${JSON.stringify(params)}`);
|
|
||||||
if (shouldInitVaapi && streamNum != undefined) {
|
|
||||||
latestStreamNum = streamNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
let options = {
|
|
||||||
scaleFilter: {
|
|
||||||
name: "scale",
|
|
||||||
},
|
|
||||||
inputOptions: shouldInitVaapi ? buildInitOptions() : [],
|
|
||||||
outputOptions: [
|
|
||||||
`-tune ${pluginSettings.liveQuality}`,
|
|
||||||
`-r:v${streamSuffix} ${fps}`,
|
|
||||||
`-profile:v${streamSuffix} ${pluginSettings.h264Profile}`,
|
|
||||||
`-cq ${pluginSettings.cqH264}`,
|
|
||||||
`-g:v${streamSuffix} ${fps * 2}`,
|
|
||||||
`-b:v${streamSuffix} ${targetBitrate}`,
|
|
||||||
`-bufsize ${targetBitrate * 2}`,
|
|
||||||
`-bf 4`,
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
logger.info(`EncoderOptions: ${JSON.stringify(options)}, HEVC: false`);
|
logger.info(`EncoderOptions: ${JSON.stringify(options)}, HEVC: false`);
|
||||||
@ -306,10 +247,10 @@ async function liveBuilder(params) {
|
|||||||
//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;
|
||||||
}
|
}
|
||||||
@ -319,7 +260,7 @@ async function hevcVODBuilder(params) {
|
|||||||
}
|
}
|
||||||
let options = {
|
let options = {
|
||||||
scaleFilter: {
|
scaleFilter: {
|
||||||
name: "scale",
|
name: 'scale'
|
||||||
},
|
},
|
||||||
inputOptions: shouldInitVaapi ? buildInitOptions() : [],
|
inputOptions: shouldInitVaapi ? buildInitOptions() : [],
|
||||||
outputOptions: [
|
outputOptions: [
|
||||||
@ -327,22 +268,23 @@ async function hevcVODBuilder(params) {
|
|||||||
`-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`);
|
logger.info(`EncoderOptions: ${JSON.stringify(options)}, HEVC: true`);
|
||||||
return options;
|
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;
|
||||||
}
|
}
|
||||||
@ -353,7 +295,7 @@ async function hevcLiveBuilder(params) {
|
|||||||
|
|
||||||
let options = {
|
let options = {
|
||||||
scaleFilter: {
|
scaleFilter: {
|
||||||
name: "scale",
|
name: 'scale'
|
||||||
},
|
},
|
||||||
inputOptions: shouldInitVaapi ? buildInitOptions() : [],
|
inputOptions: shouldInitVaapi ? buildInitOptions() : [],
|
||||||
outputOptions: [
|
outputOptions: [
|
||||||
@ -363,21 +305,55 @@ async function hevcLiveBuilder(params) {
|
|||||||
`-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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//H264 Live builder
|
||||||
|
|
||||||
|
async function liveBuilder(params) {
|
||||||
|
const { resolution, fps, streamNum, inputBitrate } = params;
|
||||||
|
const streamSuffix = streamNum == undefined ? '' : `:${streamNum}`;
|
||||||
|
let targetBitrate = getTargetBitrate(resolution, fps);
|
||||||
|
// let targetBitrate = inputBitrate;
|
||||||
|
let shouldInitVaapi = (streamNum == undefined || streamNum <= latestStreamNum);
|
||||||
|
if (targetBitrate > inputBitrate) {
|
||||||
|
targetBitrate = inputBitrate;
|
||||||
|
}
|
||||||
|
logger.info(`Building encoder options, received ${JSON.stringify(params)}`);
|
||||||
|
if (shouldInitVaapi && streamNum != undefined) {
|
||||||
|
latestStreamNum = streamNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
let options = {
|
||||||
|
scaleFilter: {
|
||||||
|
name: 'scale'
|
||||||
|
},
|
||||||
|
inputOptions: shouldInitVaapi ? buildInitOptions() : [],
|
||||||
|
outputOptions: [
|
||||||
|
`-tune ${pluginSettings.liveQuality}`,
|
||||||
|
`-r:v${streamSuffix} ${fps}`,
|
||||||
|
`-profile:v${streamSuffix} ${pluginSettings.h264Profile}`,
|
||||||
|
`-cq ${pluginSettings.cqH264}`,
|
||||||
|
`-g:v${streamSuffix} ${fps * 2}`,
|
||||||
|
`-b:v${streamSuffix} ${targetBitrate}`,
|
||||||
|
`-bufsize ${targetBitrate * 2}`,
|
||||||
|
`-bf 4`
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
logger.info(`EncoderOptions: ${JSON.stringify(options)}, HEVC: false`);
|
||||||
|
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.4;
|
||||||
const maxBitrateDifference = maxBitrate - baseBitrate;
|
const maxBitrateDifference = maxBitrate - baseBitrate;
|
||||||
const maxFpsDifference = 60 - 30;
|
const maxFpsDifference = 60 - 30;
|
||||||
return Math.floor(
|
return Math.floor(baseBitrate + (fps - 30) * (maxBitrateDifference / maxFpsDifference));
|
||||||
baseBitrate + (fps - 30) * (maxBitrateDifference / maxFpsDifference)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
//# sourceMappingURL=main.js.map
|
//# sourceMappingURL=main.js.map
|
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "peertube-plugin-nctv-nvenc-transcode",
|
"name": "peertube-plugin-nctv-nvenc-transcode",
|
||||||
"version": "1.2.3",
|
"version": "1.2.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "Plugin that adds transcode profiles which use h264_nvenc and hevc_nvenc for hardware acceleration.",
|
"description": "Plugin that adds transcode profiles which use NVIDIA NVENC for hardware acceleration",
|
||||||
"engine": {
|
"engine": {
|
||||||
"peertube": ">=5.1.0"
|
"peertube": ">=5.1.0"
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user