mirror of
https://github.com/owncast/owncast.git
synced 2024-11-22 21:03:19 +03:00
Gw/videovariantfixes (#53)
* A fix for issue https://github.com/owncast/owncast/issues/770 - merge CPU slider functionality into main video variant form - move slider constants into contants file for consistency and to reduce clutter on variant form file * disable other forms and add a notice about vieo passthrough enabling * Prettified Code! * Tweak message text * Prettified Code! Co-authored-by: gingervitis <gingervitis@users.noreply.github.com> Co-authored-by: Gabe Kangas <gabek@real-ity.com> Co-authored-by: gabek <gabek@users.noreply.github.com>
This commit is contained in:
parent
679ed7cc56
commit
49269dd175
4 changed files with 178 additions and 201 deletions
|
@ -1,76 +0,0 @@
|
|||
import React, { useContext, useState, useEffect } from 'react';
|
||||
import { Typography, Slider } from 'antd';
|
||||
import { ServerStatusContext } from '../../utils/server-status-context';
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
const SLIDER_MARKS = {
|
||||
1: 'lowest',
|
||||
2: '',
|
||||
3: '',
|
||||
4: '',
|
||||
5: 'highest',
|
||||
};
|
||||
|
||||
const TOOLTIPS = {
|
||||
1: 'Lowest CPU usage - lowest quality video',
|
||||
2: 'Low CPU usage - low quality video',
|
||||
3: 'Medium CPU usage - average quality video',
|
||||
4: 'High CPU usage - high quality video',
|
||||
5: 'Highest CPU usage - higher quality video',
|
||||
};
|
||||
interface Props {
|
||||
defaultValue: number;
|
||||
disabled: boolean;
|
||||
onChange: (arg: number) => void;
|
||||
}
|
||||
export default function CPUUsageSelector({ defaultValue, disabled, onChange }: Props) {
|
||||
const [selectedOption, setSelectedOption] = useState(null);
|
||||
|
||||
const serverStatusData = useContext(ServerStatusContext);
|
||||
const { serverConfig } = serverStatusData || {};
|
||||
const { videoSettings } = serverConfig || {};
|
||||
|
||||
if (!videoSettings) {
|
||||
return null;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setSelectedOption(defaultValue);
|
||||
}, [videoSettings]);
|
||||
|
||||
const handleChange = value => {
|
||||
setSelectedOption(value);
|
||||
onChange(value);
|
||||
};
|
||||
|
||||
const cpuUsageNote = () => {
|
||||
if (disabled) {
|
||||
return 'CPU usage selection is disabled when Video Passthrough is enabled.';
|
||||
}
|
||||
|
||||
return TOOLTIPS[selectedOption];
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="config-video-cpu-container">
|
||||
<Title level={3}>CPU Usage</Title>
|
||||
<p className="description">
|
||||
Reduce to improve server performance, or increase it to improve video quality.
|
||||
</p>
|
||||
<div className="segment-slider-container">
|
||||
<Slider
|
||||
tipFormatter={value => TOOLTIPS[value]}
|
||||
onChange={handleChange}
|
||||
min={1}
|
||||
max={Object.keys(SLIDER_MARKS).length}
|
||||
marks={SLIDER_MARKS}
|
||||
defaultValue={selectedOption}
|
||||
value={selectedOption}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<p className="selected-value-note">{cpuUsageNote()}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,62 +1,25 @@
|
|||
// This content populates the video variant modal, which is spawned from the variants table.
|
||||
// This content populates the video variant modal, which is spawned from the variants table. This relies on the `dataState` prop fed in by the table.
|
||||
import React from 'react';
|
||||
import { Popconfirm, Row, Col, Slider, Collapse, Typography } from 'antd';
|
||||
import { ExclamationCircleFilled } from '@ant-design/icons';
|
||||
import classNames from 'classnames';
|
||||
import { FieldUpdaterFunc, VideoVariant, UpdateArgs } from '../../types/config-section';
|
||||
import TextField from './form-textfield';
|
||||
import { DEFAULT_VARIANT_STATE } from '../../utils/config-constants';
|
||||
import CPUUsageSelector from './cpu-usage';
|
||||
import {
|
||||
DEFAULT_VARIANT_STATE,
|
||||
VIDEO_VARIANT_SETTING_DEFAULTS,
|
||||
ENCODER_PRESET_SLIDER_MARKS,
|
||||
ENCODER_PRESET_TOOLTIPS,
|
||||
VIDEO_BITRATE_DEFAULTS,
|
||||
VIDEO_BITRATE_SLIDER_MARKS,
|
||||
FRAMERATE_SLIDER_MARKS,
|
||||
FRAMERATE_DEFAULTS,
|
||||
FRAMERATE_TOOLTIPS,
|
||||
} from '../../utils/config-constants';
|
||||
import ToggleSwitch from './form-toggleswitch';
|
||||
|
||||
const { Panel } = Collapse;
|
||||
|
||||
const VIDEO_VARIANT_DEFAULTS = {
|
||||
framerate: {
|
||||
min: 24,
|
||||
max: 120,
|
||||
defaultValue: 24,
|
||||
unit: 'fps',
|
||||
incrementBy: null,
|
||||
tip:
|
||||
'Reducing your framerate will decrease the amount of video that needs to be encoded and sent to your viewers, saving CPU and bandwidth at the expense of smoothness. A lower value is generally is fine for most content.',
|
||||
},
|
||||
videoBitrate: {
|
||||
min: 600,
|
||||
max: 6000,
|
||||
defaultValue: 1200,
|
||||
unit: 'kbps',
|
||||
incrementBy: 100,
|
||||
tip: 'The overall quality of your stream is generally impacted most by bitrate.',
|
||||
},
|
||||
audioBitrate: {
|
||||
min: 600,
|
||||
max: 1200,
|
||||
defaultValue: 800,
|
||||
unit: 'kbps',
|
||||
incrementBy: 100,
|
||||
tip: 'nothing to see here',
|
||||
},
|
||||
videoPassthrough: {
|
||||
tip: 'If enabled, all other settings will be disabled. Otherwise configure as desired.',
|
||||
},
|
||||
audioPassthrough: {
|
||||
tip: 'If No is selected, then you should set your desired Audio Bitrate.',
|
||||
},
|
||||
scaledWidth: {
|
||||
fieldName: 'scaledWidth',
|
||||
label: 'Resized Width',
|
||||
maxLength: 4,
|
||||
placeholder: '1080',
|
||||
tip: "Optionally resize this content's width.",
|
||||
},
|
||||
scaledHeight: {
|
||||
fieldName: 'scaledHeight',
|
||||
label: 'Resized Height',
|
||||
maxLength: 4,
|
||||
placeholder: '720',
|
||||
tip: "Optionally resize this content's height.",
|
||||
},
|
||||
};
|
||||
interface VideoVariantFormProps {
|
||||
dataState: VideoVariant;
|
||||
onUpdateField: FieldUpdaterFunc;
|
||||
|
@ -66,6 +29,8 @@ export default function VideoVariantForm({
|
|||
dataState = DEFAULT_VARIANT_STATE,
|
||||
onUpdateField,
|
||||
}: VideoVariantFormProps) {
|
||||
const videoPassthroughEnabled = dataState.videoPassthrough;
|
||||
|
||||
const handleFramerateChange = (value: number) => {
|
||||
onUpdateField({ fieldName: 'framerate', value });
|
||||
};
|
||||
|
@ -99,40 +64,17 @@ export default function VideoVariantForm({
|
|||
// If passthrough is currently on, set it back to false on toggle.
|
||||
// Else let the Popconfirm turn it on.
|
||||
const handleVideoPassthroughToggle = (value: boolean) => {
|
||||
if (dataState.videoPassthrough) {
|
||||
if (videoPassthroughEnabled) {
|
||||
onUpdateField({ fieldName: 'videoPassthrough', value });
|
||||
}
|
||||
};
|
||||
|
||||
const framerateDefaults = VIDEO_VARIANT_DEFAULTS.framerate;
|
||||
const framerateMin = framerateDefaults.min;
|
||||
const framerateMax = framerateDefaults.max;
|
||||
const framerateUnit = framerateDefaults.unit;
|
||||
const framerateMarks = {
|
||||
[framerateMin]: `${framerateMin} ${framerateUnit}`,
|
||||
30: '',
|
||||
60: '',
|
||||
90: '',
|
||||
[framerateMax]: `${framerateMax} ${framerateUnit}`,
|
||||
};
|
||||
|
||||
const videoBitrateDefaults = VIDEO_VARIANT_DEFAULTS.videoBitrate;
|
||||
const videoBRMin = videoBitrateDefaults.min;
|
||||
const videoBRMax = videoBitrateDefaults.max;
|
||||
const videoBRUnit = videoBitrateDefaults.unit;
|
||||
const videoBRMarks = {
|
||||
[videoBRMin]: `${videoBRMin} ${videoBRUnit}`,
|
||||
3000: 3000,
|
||||
4500: 4500,
|
||||
[videoBRMax]: `${videoBRMax} ${videoBRUnit}`,
|
||||
};
|
||||
|
||||
// Slider notes
|
||||
const selectedVideoBRnote = () => {
|
||||
if (dataState.videoPassthrough) {
|
||||
if (videoPassthroughEnabled) {
|
||||
return 'Bitrate selection is disabled when Video Passthrough is enabled.';
|
||||
}
|
||||
|
||||
let note = `${dataState.videoBitrate}${videoBRUnit}`;
|
||||
let note = `${dataState.videoBitrate}${VIDEO_BITRATE_DEFAULTS.unit}`;
|
||||
if (dataState.videoBitrate < 2000) {
|
||||
note = `${note} - Good for low bandwidth environments.`;
|
||||
} else if (dataState.videoBitrate < 3500) {
|
||||
|
@ -143,35 +85,24 @@ export default function VideoVariantForm({
|
|||
return note;
|
||||
};
|
||||
const selectedFramerateNote = () => {
|
||||
if (dataState.videoPassthrough) {
|
||||
if (videoPassthroughEnabled) {
|
||||
return 'Framerate selection is disabled when Video Passthrough is enabled.';
|
||||
}
|
||||
|
||||
let note = `Selected: ${dataState.framerate}${framerateUnit}`;
|
||||
switch (dataState.framerate) {
|
||||
case 24:
|
||||
note = `${note} - Good for film, presentations, music, low power/bandwidth servers.`;
|
||||
break;
|
||||
case 30:
|
||||
note = `${note} - Good for slow/casual games, chat, general purpose.`;
|
||||
break;
|
||||
case 60:
|
||||
note = `${note} - Good for fast/action games, sports, HD video.`;
|
||||
break;
|
||||
case 90:
|
||||
note = `${note} - Good for newer fast games and hardware.`;
|
||||
break;
|
||||
case 120:
|
||||
note = `${note} - Experimental, use at your own risk!`;
|
||||
break;
|
||||
default:
|
||||
note = '';
|
||||
return FRAMERATE_TOOLTIPS[dataState.framerate] || '';
|
||||
};
|
||||
const cpuUsageNote = () => {
|
||||
if (videoPassthroughEnabled) {
|
||||
return 'CPU usage selection is disabled when Video Passthrough is enabled.';
|
||||
}
|
||||
return note;
|
||||
return ENCODER_PRESET_TOOLTIPS[dataState.cpuUsageLevel] || '';
|
||||
};
|
||||
|
||||
const classes = classNames({
|
||||
'config-variant-form': true,
|
||||
'video-passthrough-enabled': videoPassthroughEnabled,
|
||||
});
|
||||
return (
|
||||
<div className="config-variant-form">
|
||||
<div className={classes}>
|
||||
<p className="description">
|
||||
<a href="https://owncast.online/docs/video" target="_blank" rel="noopener noreferrer">
|
||||
Learn more
|
||||
|
@ -179,15 +110,34 @@ export default function VideoVariantForm({
|
|||
about how each of these settings can impact the performance of your server.
|
||||
</p>
|
||||
|
||||
{videoPassthroughEnabled && (
|
||||
<p className="passthrough-warning">
|
||||
NOTE: Video Passthrough for this output stream variant is <em>enabled</em>, disabling the
|
||||
below video encoding settings.
|
||||
</p>
|
||||
)}
|
||||
|
||||
<Row gutter={16}>
|
||||
<Col sm={24} md={12}>
|
||||
{/* ENCODER PRESET FIELD */}
|
||||
{/* ENCODER PRESET (CPU USAGE) FIELD */}
|
||||
<div className="form-module cpu-usage-container">
|
||||
<CPUUsageSelector
|
||||
defaultValue={dataState.cpuUsageLevel}
|
||||
onChange={handleVideoCpuUsageLevelChange}
|
||||
disabled={dataState.videoPassthrough}
|
||||
/>
|
||||
<Typography.Title level={3}>CPU Usage</Typography.Title>
|
||||
<p className="description">
|
||||
Reduce to improve server performance, or increase it to improve video quality.
|
||||
</p>
|
||||
<div className="segment-slider-container">
|
||||
<Slider
|
||||
tipFormatter={value => ENCODER_PRESET_TOOLTIPS[value]}
|
||||
onChange={handleVideoCpuUsageLevelChange}
|
||||
min={1}
|
||||
max={Object.keys(ENCODER_PRESET_SLIDER_MARKS).length}
|
||||
marks={ENCODER_PRESET_SLIDER_MARKS}
|
||||
defaultValue={dataState.cpuUsageLevel}
|
||||
value={dataState.cpuUsageLevel}
|
||||
disabled={dataState.videoPassthrough}
|
||||
/>
|
||||
<p className="selected-value-note">{cpuUsageNote()}</p>
|
||||
</div>
|
||||
<p className="read-more-subtext">
|
||||
<a
|
||||
href="https://owncast.online/docs/video/#cpu-usage"
|
||||
|
@ -208,18 +158,18 @@ export default function VideoVariantForm({
|
|||
}`}
|
||||
>
|
||||
<Typography.Title level={3}>Video Bitrate</Typography.Title>
|
||||
<p className="description">{VIDEO_VARIANT_DEFAULTS.videoBitrate.tip}</p>
|
||||
<p className="description">{VIDEO_BITRATE_DEFAULTS.tip}</p>
|
||||
<div className="segment-slider-container">
|
||||
<Slider
|
||||
tipFormatter={value => `${value} ${videoBRUnit}`}
|
||||
tipFormatter={value => `${value} ${VIDEO_BITRATE_DEFAULTS.unit}`}
|
||||
disabled={dataState.videoPassthrough}
|
||||
defaultValue={dataState.videoBitrate}
|
||||
value={dataState.videoBitrate}
|
||||
onChange={handleVideoBitrateChange}
|
||||
step={videoBitrateDefaults.incrementBy}
|
||||
min={videoBRMin}
|
||||
max={videoBRMax}
|
||||
marks={videoBRMarks}
|
||||
step={VIDEO_BITRATE_DEFAULTS.incrementBy}
|
||||
min={VIDEO_BITRATE_DEFAULTS.min}
|
||||
max={VIDEO_BITRATE_DEFAULTS.max}
|
||||
marks={VIDEO_BITRATE_SLIDER_MARKS}
|
||||
/>
|
||||
<p className="selected-value-note">{selectedVideoBRnote()}</p>
|
||||
</div>
|
||||
|
@ -256,14 +206,14 @@ export default function VideoVariantForm({
|
|||
<br />
|
||||
<TextField
|
||||
type="number"
|
||||
{...VIDEO_VARIANT_DEFAULTS.scaledWidth}
|
||||
{...VIDEO_VARIANT_SETTING_DEFAULTS.scaledWidth}
|
||||
value={dataState.scaledWidth}
|
||||
onChange={handleScaledWidthChanged}
|
||||
disabled={dataState.videoPassthrough}
|
||||
/>
|
||||
<TextField
|
||||
type="number"
|
||||
{...VIDEO_VARIANT_DEFAULTS.scaledHeight}
|
||||
{...VIDEO_VARIANT_SETTING_DEFAULTS.scaledHeight}
|
||||
value={dataState.scaledHeight}
|
||||
onChange={handleScaledHeightChanged}
|
||||
disabled={dataState.videoPassthrough}
|
||||
|
@ -272,7 +222,7 @@ export default function VideoVariantForm({
|
|||
</Col>
|
||||
<Col sm={24} md={12}>
|
||||
{/* VIDEO PASSTHROUGH FIELD */}
|
||||
<div className="form-module video-passthroug-module">
|
||||
<div className="form-module video-passthrough-module">
|
||||
<Typography.Title level={3}>Video Passthrough</Typography.Title>
|
||||
<p className="description">
|
||||
<p>
|
||||
|
@ -307,7 +257,7 @@ export default function VideoVariantForm({
|
|||
<ToggleSwitch
|
||||
label="Use Video Passthrough?"
|
||||
fieldName="video-passthrough"
|
||||
tip={VIDEO_VARIANT_DEFAULTS.videoPassthrough.tip}
|
||||
tip={VIDEO_VARIANT_SETTING_DEFAULTS.videoPassthrough.tip}
|
||||
checked={dataState.videoPassthrough}
|
||||
onChange={handleVideoPassthroughToggle}
|
||||
/>
|
||||
|
@ -320,17 +270,17 @@ export default function VideoVariantForm({
|
|||
{/* FRAME RATE FIELD */}
|
||||
<div className="form-module frame-rate-module">
|
||||
<Typography.Title level={3}>Frame rate</Typography.Title>
|
||||
<p className="description">{VIDEO_VARIANT_DEFAULTS.framerate.tip}</p>
|
||||
<p className="description">{FRAMERATE_DEFAULTS.tip}</p>
|
||||
<div className="segment-slider-container">
|
||||
<Slider
|
||||
tipFormatter={value => `${value} ${framerateUnit}`}
|
||||
tipFormatter={value => `${value} ${FRAMERATE_DEFAULTS.unit}`}
|
||||
defaultValue={dataState.framerate}
|
||||
value={dataState.framerate}
|
||||
onChange={handleFramerateChange}
|
||||
step={framerateDefaults.incrementBy}
|
||||
min={framerateMin}
|
||||
max={framerateMax}
|
||||
marks={framerateMarks}
|
||||
step={FRAMERATE_DEFAULTS.incrementBy}
|
||||
min={FRAMERATE_DEFAULTS.min}
|
||||
max={FRAMERATE_DEFAULTS.max}
|
||||
marks={FRAMERATE_SLIDER_MARKS}
|
||||
disabled={dataState.videoPassthrough}
|
||||
/>
|
||||
<p className="selected-value-note">{selectedFramerateNote()}</p>
|
||||
|
|
|
@ -15,6 +15,15 @@
|
|||
.description {
|
||||
margin-top: 0;
|
||||
}
|
||||
.passthrough-warning {
|
||||
text-align: center;
|
||||
padding: 1em;
|
||||
color: var(--ant-warning);
|
||||
font-size: 0.88em;
|
||||
font-weight: 500;
|
||||
background-color: var(--black-50);
|
||||
border-radius: var(--container-border-radius);
|
||||
}
|
||||
|
||||
.cpu-usage-container,
|
||||
.bitrate-container {
|
||||
|
@ -25,10 +34,17 @@
|
|||
margin-top: 1em;
|
||||
|
||||
.resolution-module,
|
||||
.video-passthroug-module {
|
||||
.video-passthrough-module {
|
||||
min-height: 30em;
|
||||
}
|
||||
}
|
||||
// make some things look disabled when passthrough is on
|
||||
&.video-passthrough-enabled {
|
||||
.form-module:not(.video-passthrough-module) {
|
||||
opacity: 0.25;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.variants-table {
|
||||
|
|
|
@ -144,8 +144,7 @@ export const FIELD_PROPS_YP = {
|
|||
apiPath: API_YP_SWITCH,
|
||||
configPath: 'yp',
|
||||
label: 'Enable directory',
|
||||
tip:
|
||||
'Turn this ON if you want to show up in the directory.',
|
||||
tip: 'Turn this ON if you want to show up in the directory.',
|
||||
};
|
||||
|
||||
export const DEFAULT_VARIANT_STATE: VideoVariant = {
|
||||
|
@ -159,6 +158,94 @@ export const DEFAULT_VARIANT_STATE: VideoVariant = {
|
|||
scaledWidth: null,
|
||||
};
|
||||
|
||||
export const VIDEO_VARIANT_SETTING_DEFAULTS = {
|
||||
// this one is currently unused
|
||||
audioBitrate: {
|
||||
min: 600,
|
||||
max: 1200,
|
||||
defaultValue: 800,
|
||||
unit: 'kbps',
|
||||
incrementBy: 100,
|
||||
tip: 'nothing to see here',
|
||||
},
|
||||
videoPassthrough: {
|
||||
tip: 'If enabled, all other settings will be disabled. Otherwise configure as desired.',
|
||||
},
|
||||
audioPassthrough: {
|
||||
tip: 'If No is selected, then you should set your desired Audio Bitrate.',
|
||||
},
|
||||
scaledWidth: {
|
||||
fieldName: 'scaledWidth',
|
||||
label: 'Resized Width',
|
||||
maxLength: 4,
|
||||
placeholder: '1080',
|
||||
tip: "Optionally resize this content's width.",
|
||||
},
|
||||
scaledHeight: {
|
||||
fieldName: 'scaledHeight',
|
||||
label: 'Resized Height',
|
||||
maxLength: 4,
|
||||
placeholder: '720',
|
||||
tip: "Optionally resize this content's height.",
|
||||
},
|
||||
};
|
||||
|
||||
// VIDEO VARIANT FORM - framerate
|
||||
export const FRAMERATE_DEFAULTS = {
|
||||
min: 24,
|
||||
max: 120,
|
||||
defaultValue: 24,
|
||||
unit: 'fps',
|
||||
incrementBy: null,
|
||||
tip:
|
||||
'Reducing your framerate will decrease the amount of video that needs to be encoded and sent to your viewers, saving CPU and bandwidth at the expense of smoothness. A lower value is generally is fine for most content.',
|
||||
};
|
||||
export const FRAMERATE_SLIDER_MARKS = {
|
||||
[FRAMERATE_DEFAULTS.min]: `${FRAMERATE_DEFAULTS.min} ${FRAMERATE_DEFAULTS.unit}`,
|
||||
30: '',
|
||||
60: '',
|
||||
90: '',
|
||||
[FRAMERATE_DEFAULTS.max]: `${FRAMERATE_DEFAULTS.max} ${FRAMERATE_DEFAULTS.unit}`,
|
||||
};
|
||||
export const FRAMERATE_TOOLTIPS = {
|
||||
[FRAMERATE_DEFAULTS.min]: `${FRAMERATE_DEFAULTS.min}fps - Good for film, presentations, music, low power/bandwidth servers.`,
|
||||
30: '30fps - Good for slow/casual games, chat, general purpose.',
|
||||
60: '60fps - Good for fast/action games, sports, HD video.',
|
||||
90: '90fps - Good for newer fast games and hardware.',
|
||||
[FRAMERATE_DEFAULTS.max]: `${FRAMERATE_DEFAULTS.max}fps - Experimental, use at your own risk!`,
|
||||
};
|
||||
// VIDEO VARIANT FORM - bitrate
|
||||
export const VIDEO_BITRATE_DEFAULTS = {
|
||||
min: 600,
|
||||
max: 6000,
|
||||
defaultValue: 1200,
|
||||
unit: 'kbps',
|
||||
incrementBy: 100,
|
||||
tip: 'The overall quality of your stream is generally impacted most by bitrate.',
|
||||
};
|
||||
export const VIDEO_BITRATE_SLIDER_MARKS = {
|
||||
[VIDEO_BITRATE_DEFAULTS.min]: `${VIDEO_BITRATE_DEFAULTS.min} ${VIDEO_BITRATE_DEFAULTS.unit}`,
|
||||
3000: 3000,
|
||||
4500: 4500,
|
||||
[VIDEO_BITRATE_DEFAULTS.max]: `${VIDEO_BITRATE_DEFAULTS.max} ${VIDEO_BITRATE_DEFAULTS.unit}`,
|
||||
};
|
||||
// VIDEO VARIANT FORM - encoder preset
|
||||
// CPU
|
||||
export const ENCODER_PRESET_SLIDER_MARKS = {
|
||||
1: 'lowest',
|
||||
2: '',
|
||||
3: '',
|
||||
4: '',
|
||||
5: 'highest',
|
||||
};
|
||||
export const ENCODER_PRESET_TOOLTIPS = {
|
||||
1: 'Lowest CPU usage - lowest quality video',
|
||||
2: 'Low CPU usage - low quality video',
|
||||
3: 'Medium CPU usage - average quality video',
|
||||
4: 'High CPU usage - high quality video',
|
||||
5: 'Highest CPU usage - higher quality video',
|
||||
};
|
||||
|
||||
export const DEFAULT_SOCIAL_HANDLE: SocialHandle = {
|
||||
url: '',
|
||||
platform: '',
|
||||
|
|
Loading…
Reference in a new issue