2021-12-29 14:44:58 +01:00
|
|
|
import { VideoResolution } from '@shared/models'
|
2021-08-06 13:35:25 +02:00
|
|
|
|
|
|
|
type BitPerPixel = { [ id in VideoResolution ]: number }
|
|
|
|
|
|
|
|
// https://bitmovin.com/video-bitrate-streaming-hls-dash/
|
|
|
|
|
2021-11-10 11:04:00 +01:00
|
|
|
const minLimitBitPerPixel: BitPerPixel = {
|
|
|
|
[VideoResolution.H_NOVIDEO]: 0,
|
|
|
|
[VideoResolution.H_144P]: 0.02,
|
|
|
|
[VideoResolution.H_240P]: 0.02,
|
|
|
|
[VideoResolution.H_360P]: 0.02,
|
|
|
|
[VideoResolution.H_480P]: 0.02,
|
|
|
|
[VideoResolution.H_720P]: 0.02,
|
|
|
|
[VideoResolution.H_1080P]: 0.02,
|
|
|
|
[VideoResolution.H_1440P]: 0.02,
|
|
|
|
[VideoResolution.H_4K]: 0.02
|
|
|
|
}
|
|
|
|
|
2021-08-06 13:35:25 +02:00
|
|
|
const averageBitPerPixel: BitPerPixel = {
|
|
|
|
[VideoResolution.H_NOVIDEO]: 0,
|
2021-11-05 10:23:02 +01:00
|
|
|
[VideoResolution.H_144P]: 0.19,
|
2021-08-06 13:35:25 +02:00
|
|
|
[VideoResolution.H_240P]: 0.17,
|
|
|
|
[VideoResolution.H_360P]: 0.15,
|
|
|
|
[VideoResolution.H_480P]: 0.12,
|
|
|
|
[VideoResolution.H_720P]: 0.11,
|
|
|
|
[VideoResolution.H_1080P]: 0.10,
|
|
|
|
[VideoResolution.H_1440P]: 0.09,
|
|
|
|
[VideoResolution.H_4K]: 0.08
|
|
|
|
}
|
|
|
|
|
|
|
|
const maxBitPerPixel: BitPerPixel = {
|
|
|
|
[VideoResolution.H_NOVIDEO]: 0,
|
2021-11-05 10:23:02 +01:00
|
|
|
[VideoResolution.H_144P]: 0.32,
|
2021-08-06 13:35:25 +02:00
|
|
|
[VideoResolution.H_240P]: 0.29,
|
|
|
|
[VideoResolution.H_360P]: 0.26,
|
|
|
|
[VideoResolution.H_480P]: 0.22,
|
|
|
|
[VideoResolution.H_720P]: 0.19,
|
|
|
|
[VideoResolution.H_1080P]: 0.17,
|
|
|
|
[VideoResolution.H_1440P]: 0.16,
|
|
|
|
[VideoResolution.H_4K]: 0.14
|
|
|
|
}
|
|
|
|
|
2023-05-05 10:53:04 +02:00
|
|
|
function getAverageTheoreticalBitrate (options: {
|
2021-08-06 13:35:25 +02:00
|
|
|
resolution: VideoResolution
|
|
|
|
ratio: number
|
|
|
|
fps: number
|
|
|
|
}) {
|
|
|
|
const targetBitrate = calculateBitrate({ ...options, bitPerPixel: averageBitPerPixel })
|
|
|
|
if (!targetBitrate) return 192 * 1000
|
|
|
|
|
|
|
|
return targetBitrate
|
|
|
|
}
|
|
|
|
|
2023-05-05 10:53:04 +02:00
|
|
|
function getMaxTheoreticalBitrate (options: {
|
2021-08-06 13:35:25 +02:00
|
|
|
resolution: VideoResolution
|
|
|
|
ratio: number
|
|
|
|
fps: number
|
|
|
|
}) {
|
|
|
|
const targetBitrate = calculateBitrate({ ...options, bitPerPixel: maxBitPerPixel })
|
|
|
|
if (!targetBitrate) return 256 * 1000
|
|
|
|
|
|
|
|
return targetBitrate
|
|
|
|
}
|
|
|
|
|
2023-05-05 10:53:04 +02:00
|
|
|
function getMinTheoreticalBitrate (options: {
|
2021-11-10 11:04:00 +01:00
|
|
|
resolution: VideoResolution
|
|
|
|
ratio: number
|
|
|
|
fps: number
|
|
|
|
}) {
|
|
|
|
const minLimitBitrate = calculateBitrate({ ...options, bitPerPixel: minLimitBitPerPixel })
|
|
|
|
if (!minLimitBitrate) return 10 * 1000
|
|
|
|
|
|
|
|
return minLimitBitrate
|
|
|
|
}
|
|
|
|
|
2021-08-06 13:35:25 +02:00
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
export {
|
2023-05-05 10:53:04 +02:00
|
|
|
getAverageTheoreticalBitrate,
|
|
|
|
getMaxTheoreticalBitrate,
|
|
|
|
getMinTheoreticalBitrate
|
2021-08-06 13:35:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
function calculateBitrate (options: {
|
|
|
|
bitPerPixel: BitPerPixel
|
|
|
|
resolution: VideoResolution
|
|
|
|
ratio: number
|
|
|
|
fps: number
|
|
|
|
}) {
|
|
|
|
const { bitPerPixel, resolution, ratio, fps } = options
|
|
|
|
|
|
|
|
const resolutionsOrder = [
|
|
|
|
VideoResolution.H_4K,
|
|
|
|
VideoResolution.H_1440P,
|
|
|
|
VideoResolution.H_1080P,
|
|
|
|
VideoResolution.H_720P,
|
|
|
|
VideoResolution.H_480P,
|
|
|
|
VideoResolution.H_360P,
|
|
|
|
VideoResolution.H_240P,
|
2021-11-05 10:23:02 +01:00
|
|
|
VideoResolution.H_144P,
|
2021-08-06 13:35:25 +02:00
|
|
|
VideoResolution.H_NOVIDEO
|
|
|
|
]
|
|
|
|
|
|
|
|
for (const toTestResolution of resolutionsOrder) {
|
|
|
|
if (toTestResolution <= resolution) {
|
2021-10-12 09:18:54 +02:00
|
|
|
return Math.floor(resolution * resolution * ratio * fps * bitPerPixel[toTestResolution])
|
2021-08-06 13:35:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new Error('Unknown resolution ' + resolution)
|
|
|
|
}
|