owncast/web/components/config/CodecSelector.tsx
James Young d1f3fffe2f
reafctor: normalize component formatting (#2082)
* refactor: move/rename BanUserButton file

* refactor: move/rename Chart file

* refactor: update generic component filenames to PascalCase

* refactor: update config component filenames to PascalCase

* refactor: update AdminLayout component filename to PascalCase

* refactor: update/move VideoJS component

* chore(eslint): disable bad react/require-default-props rule

* refactor: normalize ActionButton component

* refactor: normalize ActionButtonRow component

* refactor: normalize FollowButton component

* refactor: normalize NotifyButton component

* refactor: normalize ChatActionMessage component

* refactor: normalize ChatContainer component

* refactor: normalize ChatJoinMessage component

* refactor: normalize ChatModerationActionMenu component

* refactor: normalize ChatModerationDetailsModal component

* refactor: normalize ChatModeratorNotification component

* refactor: normalize ChatSocialMessage component

* refactor: normalize ChatSystemMessage component

* refactor: normalize ChatTextField component

* refactor: normalize ChatUserBadge component

* refactor: normalize ChatUserMessage component

* refactor: normalize ContentHeader component

* refactor: normalize OwncastLogo component

* refactor: normalize UserDropdown component

* chore(eslint): modify react/function-component-definition rule

* refactor: normalize CodecSelector component

* refactor: update a bunch of functional components using eslint

* refactor: update a bunch of functional components using eslint, pt2

* refactor: update a bunch of functional components using eslint, pt3

* refactor: replace all component->component default imports with named imports

* refactor: replace all component-stories->component default imports with named imports

* refactor: remove default exports from most components

* chore(eslint): add eslint config files for the components and pages dirs

* fix: use-before-define error in ChatContainer

* Fix ChatContainer import

* Only process .tsx files in Next builds

Co-authored-by: Gabe Kangas <gabek@real-ity.com>
2022-09-07 00:00:28 -07:00

174 lines
6 KiB
TypeScript

import { Popconfirm, Select, Typography } from 'antd';
import React, { FC, useContext, useEffect, useState } from 'react';
import { AlertMessageContext } from '../../utils/alert-message-context';
import {
API_VIDEO_CODEC,
postConfigUpdateToAPI,
RESET_TIMEOUT,
} from '../../utils/config-constants';
import {
createInputStatus,
StatusState,
STATUS_ERROR,
STATUS_SUCCESS,
} from '../../utils/input-statuses';
import { ServerStatusContext } from '../../utils/server-status-context';
import { FormStatusIndicator } from './FormStatusIndicator';
export type CodecSelectorProps = {};
export const CodecSelector: FC<CodecSelectorProps> = () => {
const serverStatusData = useContext(ServerStatusContext);
const { serverConfig, setFieldInConfigState } = serverStatusData || {};
const { videoCodec, supportedCodecs } = serverConfig || {};
const { Title } = Typography;
const { Option } = Select;
const [submitStatus, setSubmitStatus] = useState<StatusState>(null);
const { setMessage } = useContext(AlertMessageContext);
const [selectedCodec, setSelectedCodec] = useState(videoCodec);
const [pendingSaveCodec, setPendingSavecodec] = useState(videoCodec);
const [confirmPopupVisible, setConfirmPopupVisible] = React.useState(false);
let resetTimer = null;
useEffect(() => {
setSelectedCodec(videoCodec);
}, [videoCodec]);
const resetStates = () => {
setSubmitStatus(null);
resetTimer = null;
clearTimeout(resetTimer);
};
function handleChange(value) {
setPendingSavecodec(value);
setConfirmPopupVisible(true);
}
async function save() {
setSelectedCodec(pendingSaveCodec);
setPendingSavecodec('');
setConfirmPopupVisible(false);
await postConfigUpdateToAPI({
apiPath: API_VIDEO_CODEC,
data: { value: pendingSaveCodec },
onSuccess: () => {
setFieldInConfigState({
fieldName: 'videoCodec',
value: pendingSaveCodec,
path: 'videoSettings',
});
setSubmitStatus(createInputStatus(STATUS_SUCCESS, 'Video codec updated.'));
resetTimer = setTimeout(resetStates, RESET_TIMEOUT);
if (serverStatusData.online) {
setMessage(
'Your latency buffer setting will take effect the next time you begin a live stream.',
);
}
},
onError: (message: string) => {
setSubmitStatus(createInputStatus(STATUS_ERROR, message));
resetTimer = setTimeout(resetStates, RESET_TIMEOUT);
},
});
}
const items = supportedCodecs.map(codec => {
let title = codec;
if (title === 'libx264') {
title = 'Default (libx264)';
} else if (title === 'h264_nvenc') {
title = 'NVIDIA GPU acceleration';
} else if (title === 'h264_vaapi') {
title = 'VA-API hardware encoding';
} else if (title === 'h264_qsv') {
title = 'Intel QuickSync';
} else if (title === 'h264_v4l2m2m') {
title = 'Video4Linux hardware encoding';
} else if (title === 'h264_omx') {
title = 'OpenMax (omx) for Raspberry Pi';
} else if (title === 'h264_videotoolbox') {
title = 'Apple VideoToolbox (hardware)';
}
return (
<Option key={codec} value={codec}>
{title}
</Option>
);
});
let description = '';
if (selectedCodec === 'libx264') {
description =
'libx264 is the default codec and generally the only working choice for shared VPS environments. This is likely what you should be using unless you know you have set up other options.';
} else if (selectedCodec === 'h264_nvenc') {
description =
'You can use your NVIDIA GPU for encoding if you have a modern NVIDIA card with encoding cores.';
} else if (selectedCodec === 'h264_vaapi') {
description =
'VA-API may be supported by your NVIDIA proprietary drivers, Mesa open-source drivers for AMD or Intel graphics.';
} else if (selectedCodec === 'h264_qsv') {
description =
"Quick Sync Video is Intel's brand for its dedicated video encoding and decoding hardware. It may be an option if you have a modern Intel CPU with integrated graphics.";
} else if (selectedCodec === 'h264_v4l2m2m') {
description =
'Video4Linux is an interface to multiple different hardware encoding platforms such as Intel and AMD.';
} else if (selectedCodec === 'h264_omx') {
description = 'OpenMax is a codec most often used with a Raspberry Pi.';
} else if (selectedCodec === 'h264_videotoolbox') {
description =
'Apple VideoToolbox is a low-level framework that provides direct access to hardware encoders and decoders.';
}
return (
<>
<Title level={3} className="section-title">
Video Codec
</Title>
<div className="description">
If you have access to specific hardware with the drivers and software installed for them,
you may be able to improve your video encoding performance.
<p>
<a
href="https://owncast.online/docs/codecs?source=admin"
target="_blank"
rel="noopener noreferrer"
>
Read the documentation about this setting before changing it or you may make your stream
unplayable.
</a>
</p>
</div>
<div className="segment-slider-container">
<Popconfirm
title={`Are you sure you want to change your video codec to ${pendingSaveCodec} and understand what this means?`}
visible={confirmPopupVisible}
placement="leftBottom"
onConfirm={save}
onCancel={() => setConfirmPopupVisible(false)}
okText="Yes"
cancelText="No"
>
<Select
defaultValue={selectedCodec}
value={selectedCodec}
style={{ width: '100%' }}
onChange={handleChange}
>
{items}
</Select>
</Popconfirm>
<FormStatusIndicator status={submitStatus} />
<p id="selected-codec-note" className="selected-value-note">
{description}
</p>
</div>
</>
);
};