]>
Commit | Line | Data |
---|---|---|
0628157f | 1 | import { VideoResolution } from '@shared/models' |
679c12e6 C |
2 | |
3 | type BitPerPixel = { [ id in VideoResolution ]: number } | |
4 | ||
5 | // https://bitmovin.com/video-bitrate-streaming-hls-dash/ | |
6 | ||
67eeec8b C |
7 | const minLimitBitPerPixel: BitPerPixel = { |
8 | [VideoResolution.H_NOVIDEO]: 0, | |
9 | [VideoResolution.H_144P]: 0.02, | |
10 | [VideoResolution.H_240P]: 0.02, | |
11 | [VideoResolution.H_360P]: 0.02, | |
12 | [VideoResolution.H_480P]: 0.02, | |
13 | [VideoResolution.H_720P]: 0.02, | |
14 | [VideoResolution.H_1080P]: 0.02, | |
15 | [VideoResolution.H_1440P]: 0.02, | |
16 | [VideoResolution.H_4K]: 0.02 | |
17 | } | |
18 | ||
679c12e6 C |
19 | const averageBitPerPixel: BitPerPixel = { |
20 | [VideoResolution.H_NOVIDEO]: 0, | |
8dd754c7 | 21 | [VideoResolution.H_144P]: 0.19, |
679c12e6 C |
22 | [VideoResolution.H_240P]: 0.17, |
23 | [VideoResolution.H_360P]: 0.15, | |
24 | [VideoResolution.H_480P]: 0.12, | |
25 | [VideoResolution.H_720P]: 0.11, | |
26 | [VideoResolution.H_1080P]: 0.10, | |
27 | [VideoResolution.H_1440P]: 0.09, | |
28 | [VideoResolution.H_4K]: 0.08 | |
29 | } | |
30 | ||
31 | const maxBitPerPixel: BitPerPixel = { | |
32 | [VideoResolution.H_NOVIDEO]: 0, | |
8dd754c7 | 33 | [VideoResolution.H_144P]: 0.32, |
679c12e6 C |
34 | [VideoResolution.H_240P]: 0.29, |
35 | [VideoResolution.H_360P]: 0.26, | |
36 | [VideoResolution.H_480P]: 0.22, | |
37 | [VideoResolution.H_720P]: 0.19, | |
38 | [VideoResolution.H_1080P]: 0.17, | |
39 | [VideoResolution.H_1440P]: 0.16, | |
40 | [VideoResolution.H_4K]: 0.14 | |
41 | } | |
42 | ||
43 | function getAverageBitrate (options: { | |
44 | resolution: VideoResolution | |
45 | ratio: number | |
46 | fps: number | |
47 | }) { | |
48 | const targetBitrate = calculateBitrate({ ...options, bitPerPixel: averageBitPerPixel }) | |
49 | if (!targetBitrate) return 192 * 1000 | |
50 | ||
51 | return targetBitrate | |
52 | } | |
53 | ||
54 | function getMaxBitrate (options: { | |
55 | resolution: VideoResolution | |
56 | ratio: number | |
57 | fps: number | |
58 | }) { | |
59 | const targetBitrate = calculateBitrate({ ...options, bitPerPixel: maxBitPerPixel }) | |
60 | if (!targetBitrate) return 256 * 1000 | |
61 | ||
62 | return targetBitrate | |
63 | } | |
64 | ||
67eeec8b C |
65 | function getMinLimitBitrate (options: { |
66 | resolution: VideoResolution | |
67 | ratio: number | |
68 | fps: number | |
69 | }) { | |
70 | const minLimitBitrate = calculateBitrate({ ...options, bitPerPixel: minLimitBitPerPixel }) | |
71 | if (!minLimitBitrate) return 10 * 1000 | |
72 | ||
73 | return minLimitBitrate | |
74 | } | |
75 | ||
679c12e6 C |
76 | // --------------------------------------------------------------------------- |
77 | ||
78 | export { | |
79 | getAverageBitrate, | |
67eeec8b C |
80 | getMaxBitrate, |
81 | getMinLimitBitrate | |
679c12e6 C |
82 | } |
83 | ||
84 | // --------------------------------------------------------------------------- | |
85 | ||
86 | function calculateBitrate (options: { | |
87 | bitPerPixel: BitPerPixel | |
88 | resolution: VideoResolution | |
89 | ratio: number | |
90 | fps: number | |
91 | }) { | |
92 | const { bitPerPixel, resolution, ratio, fps } = options | |
93 | ||
94 | const resolutionsOrder = [ | |
95 | VideoResolution.H_4K, | |
96 | VideoResolution.H_1440P, | |
97 | VideoResolution.H_1080P, | |
98 | VideoResolution.H_720P, | |
99 | VideoResolution.H_480P, | |
100 | VideoResolution.H_360P, | |
101 | VideoResolution.H_240P, | |
8dd754c7 | 102 | VideoResolution.H_144P, |
679c12e6 C |
103 | VideoResolution.H_NOVIDEO |
104 | ] | |
105 | ||
106 | for (const toTestResolution of resolutionsOrder) { | |
107 | if (toTestResolution <= resolution) { | |
9f430a53 | 108 | return Math.floor(resolution * resolution * ratio * fps * bitPerPixel[toTestResolution]) |
679c12e6 C |
109 | } |
110 | } | |
111 | ||
112 | throw new Error('Unknown resolution ' + resolution) | |
113 | } |