From f04f385f2b18f63370179178ff0a195ca3c20687 Mon Sep 17 00:00:00 2001 From: Gabe Kangas Date: Mon, 22 Mar 2021 20:34:52 -0700 Subject: [PATCH] Start codec selection in admin --- web/.vscode/settings.json | 13 ++ .../config/video-codec-selector.tsx | 125 ++++++++++++++++++ web/pages/config-video.tsx | 7 +- web/types/config-section.ts | 2 + web/utils/config-constants.tsx | 3 +- web/utils/server-status-context.tsx | 2 + 6 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 web/.vscode/settings.json create mode 100644 web/components/config/video-codec-selector.tsx diff --git a/web/.vscode/settings.json b/web/.vscode/settings.json new file mode 100644 index 000000000..97824caab --- /dev/null +++ b/web/.vscode/settings.json @@ -0,0 +1,13 @@ +{ + "cSpell.words": [ + "Owncast", + "antd", + "bitrates", + "chartkick", + "framerates", + "kbps", + "linkify", + "paypal", + "toggleswitch" + ] +} \ No newline at end of file diff --git a/web/components/config/video-codec-selector.tsx b/web/components/config/video-codec-selector.tsx new file mode 100644 index 000000000..7a2dee02e --- /dev/null +++ b/web/components/config/video-codec-selector.tsx @@ -0,0 +1,125 @@ +import React, { useContext, useState, useEffect } from 'react'; +import { Typography, Select } from 'antd'; +import { ServerStatusContext } from '../../utils/server-status-context'; +import { AlertMessageContext } from '../../utils/alert-message-context'; +import { + API_VIDEO_CODEC, + RESET_TIMEOUT, + postConfigUpdateToAPI, +} from '../../utils/config-constants'; +import { + createInputStatus, + StatusState, + STATUS_ERROR, + STATUS_PROCESSING, + STATUS_SUCCESS, +} from '../../utils/input-statuses'; +import FormStatusIndicator from './form-status-indicator'; + + +export default function CodecSelector() { + const serverStatusData = useContext(ServerStatusContext); + const { serverConfig, setFieldInConfigState } = serverStatusData || {}; + const { videoCodec, supportedCodecs } = serverConfig || {}; + const { Title } = Typography; + const { Option } = Select; + const [submitStatus, setSubmitStatus] = useState(null); + const { setMessage } = useContext(AlertMessageContext); + const [selectedCodec, setSelectedCodec] = useState(videoCodec); + + let resetTimer = null; + + useEffect(() => { + setSelectedCodec(videoCodec); + }, [videoCodec]); + + const resetStates = () => { + setSubmitStatus(null); + resetTimer = null; + clearTimeout(resetTimer); + }; + + async function handleChange(value) { + console.log(`selected ${value}`); + setSelectedCodec(value); + + await postConfigUpdateToAPI({ + apiPath: API_VIDEO_CODEC, + data: { value: value }, + onSuccess: () => { + setFieldInConfigState({ + fieldName: 'videoCodec', + value: value, + 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(function (codec) { + var title = codec; + if (title === 'libx264') { + title = 'Default (libx264)'; + } else if (title === 'h264_nvenc') { + title = 'NVIDIA GPU acceleration'; + } else if (title === 'h264_vaapi') { + title = 'VAAPI hardware encoding'; + } else if (title === 'h264_qsv') { + title = 'Intel QuickSync'; + } else if (title === 'h264_v4l2m2m') { + title = 'Video4Linux hardware encoding'; + } + + return ( + + ); + }) + + var description = ''; + if (selectedCodec === 'libx264') { + description = 'libx264 is default codec and generally the choice you will want to use unless you have access to more specialized options. It is also likely the only option for running on shared VPS environments.'; + } 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 = 'VAAPI may be supported by NVIDIA proprietary drivers, Mesa open-source drivers for AMD or Intel graphics cards.'; + } else if (selectedCodec === 'h264_qsv') { + description = "Quick Sync Video is Intel's brand for its dedicated video encoding and decoding hardware core. 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." + } + + return ( + <> + + Video Codec + +

+ Blurb about codecs go here. +

+
+ + +

+ {description} +

+
+ + ); +} diff --git a/web/pages/config-video.tsx b/web/pages/config-video.tsx index c7a4a52e4..afdc8a151 100644 --- a/web/pages/config-video.tsx +++ b/web/pages/config-video.tsx @@ -1,8 +1,9 @@ import React from 'react'; -import { Typography, Row, Col } from 'antd'; +import { Typography, Row, Col, Select } from 'antd'; import VideoVariantsTable from '../components/config/video-variants-table'; import VideoLatency from '../components/config/video-latency'; +import VideoCodecSelector from '../components/config/video-codec-selector'; const { Title } = Typography; @@ -29,6 +30,9 @@ export default function ConfigVideoSettings() {
+
+ +
@@ -39,3 +43,4 @@ export default function ConfigVideoSettings() {
); } + diff --git a/web/types/config-section.ts b/web/types/config-section.ts index c3e125c8e..e18d4bcc4 100644 --- a/web/types/config-section.ts +++ b/web/types/config-section.ts @@ -99,4 +99,6 @@ export interface ConfigDetails { videoSettings: VideoSettingsFields; webServerPort: string; yp: ConfigDirectoryFields; + supportedCodecs: string[]; + videoCodec: string; } diff --git a/web/utils/config-constants.tsx b/web/utils/config-constants.tsx index 72f921920..782a4420e 100644 --- a/web/utils/config-constants.tsx +++ b/web/utils/config-constants.tsx @@ -28,7 +28,8 @@ export const API_VIDEO_VARIANTS = '/video/streamoutputvariants'; export const API_WEB_PORT = '/webserverport'; export const API_YP_SWITCH = '/directoryenabled'; export const API_CHAT_DISABLE = '/chat/disable'; -export const API_EXTERNAL_ACTIONS = '/externalactions'; +export const API_EXTERNAL_ACTIONS = '/externalactions' +export const API_VIDEO_CODEC = '/video/codec'; export async function postConfigUpdateToAPI(args: ApiPostArgs) { const { apiPath, data, onSuccess, onError } = args; diff --git a/web/utils/server-status-context.tsx b/web/utils/server-status-context.tsx index ecc365e82..9e61d13d7 100644 --- a/web/utils/server-status-context.tsx +++ b/web/utils/server-status-context.tsx @@ -46,6 +46,8 @@ export const initialServerConfigState: ConfigDetails = { videoQualityVariants: [DEFAULT_VARIANT_STATE], }, externalActions: [], + supportedCodecs: [], + videoCodec: '', }; const initialServerStatusState = {