2021-01-16 19:46:19 -08:00
// This content populates the video variant modal, which is spawned from the variants table.
2021-01-10 02:37:22 -08:00
import React from 'react' ;
2021-02-14 18:46:34 -08:00
import { Row , Col , Slider , Collapse , Typography } from 'antd' ;
2021-02-07 17:03:02 -08:00
import { FieldUpdaterFunc , VideoVariant , UpdateArgs } from '../../types/config-section' ;
import TextField from './form-textfield' ;
2021-02-06 22:38:58 -05:00
import { DEFAULT_VARIANT_STATE } from '../../utils/config-constants' ;
2021-01-30 22:53:00 -08:00
import CPUUsageSelector from './cpu-usage' ;
2021-02-14 18:46:34 -08:00
import ToggleSwitch from './form-toggleswitch' ;
2021-01-10 02:37:22 -08:00
const { Panel } = Collapse ;
const VIDEO_VARIANT_DEFAULTS = {
framerate : {
2021-02-13 19:44:16 -05:00
min : 24 ,
max : 120 ,
2021-01-10 02:37:22 -08:00
defaultValue : 24 ,
unit : 'fps' ,
2021-02-13 19:44:16 -05:00
incrementBy : null ,
2021-02-15 22:09:34 +00:00
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.' ,
2021-01-10 02:37:22 -08:00
} ,
videoBitrate : {
min : 600 ,
2021-02-03 10:26:46 -08:00
max : 6000 ,
defaultValue : 1200 ,
2021-01-10 02:37:22 -08:00
unit : 'kbps' ,
incrementBy : 100 ,
2021-02-15 14:08:47 -08:00
tip : 'The overall quality of your stream is generally impacted most by bitrate.' ,
2021-01-10 02:37:22 -08:00
} ,
audioBitrate : {
min : 600 ,
max : 1200 ,
defaultValue : 800 ,
unit : 'kbps' ,
incrementBy : 100 ,
2021-01-31 01:38:20 -08:00
tip : 'nothing to see here' ,
2021-01-10 02:37:22 -08:00
} ,
videoPassthrough : {
2021-01-31 01:38:20 -08:00
tip : 'If No is selected, then you should set your desired Video Bitrate.' ,
2021-01-10 02:37:22 -08:00
} ,
audioPassthrough : {
2021-01-31 01:38:20 -08:00
tip : 'If No is selected, then you should set your desired Audio Bitrate.' ,
2021-01-10 02:37:22 -08:00
} ,
2021-02-07 17:03:02 -08:00
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." ,
} ,
2021-01-10 02:37:22 -08:00
} ;
interface VideoVariantFormProps {
dataState : VideoVariant ;
2021-01-16 19:46:19 -08:00
onUpdateField : FieldUpdaterFunc ;
2021-01-10 02:37:22 -08:00
}
2021-01-31 01:38:20 -08:00
export default function VideoVariantForm ( {
dataState = DEFAULT_VARIANT_STATE ,
onUpdateField ,
} : VideoVariantFormProps ) {
2021-01-10 02:37:22 -08:00
const handleFramerateChange = ( value : number ) = > {
2021-01-16 19:46:19 -08:00
onUpdateField ( { fieldName : 'framerate' , value } ) ;
2021-01-10 02:37:22 -08:00
} ;
const handleVideoBitrateChange = ( value : number ) = > {
2021-01-16 19:46:19 -08:00
onUpdateField ( { fieldName : 'videoBitrate' , value } ) ;
2021-01-10 02:37:22 -08:00
} ;
const handleVideoPassChange = ( value : boolean ) = > {
2021-01-16 19:46:19 -08:00
onUpdateField ( { fieldName : 'videoPassthrough' , value } ) ;
2021-01-10 02:37:22 -08:00
} ;
2021-01-30 22:53:00 -08:00
const handleVideoCpuUsageLevelChange = ( value : number ) = > {
2021-01-31 01:38:20 -08:00
onUpdateField ( { fieldName : 'cpuUsageLevel' , value } ) ;
} ;
2021-02-07 17:03:02 -08:00
const handleScaledWidthChanged = ( args : UpdateArgs ) = > {
const value = Number ( args . value ) ;
2021-02-12 23:55:59 -08:00
// eslint-disable-next-line no-restricted-globals
2021-02-07 19:41:52 -08:00
if ( isNaN ( value ) ) {
2021-02-07 17:03:02 -08:00
return ;
}
2021-02-07 19:41:52 -08:00
onUpdateField ( { fieldName : 'scaledWidth' , value : value || '' } ) ;
2021-02-07 17:03:02 -08:00
} ;
const handleScaledHeightChanged = ( args : UpdateArgs ) = > {
const value = Number ( args . value ) ;
2021-02-12 23:55:59 -08:00
// eslint-disable-next-line no-restricted-globals
2021-02-07 19:41:52 -08:00
if ( isNaN ( value ) ) {
2021-02-07 17:03:02 -08:00
return ;
}
2021-01-10 02:37:22 -08:00
2021-02-07 19:41:52 -08:00
onUpdateField ( { fieldName : 'scaledHeight' , value : value || '' } ) ;
2021-02-07 17:03:02 -08:00
} ;
2021-01-10 02:37:22 -08:00
const framerateDefaults = VIDEO_VARIANT_DEFAULTS . framerate ;
const framerateMin = framerateDefaults . min ;
const framerateMax = framerateDefaults . max ;
const framerateUnit = framerateDefaults . unit ;
2021-02-13 19:44:16 -05:00
const framerateMarks = {
[ framerateMin ] : ` ${ framerateMin } ${ framerateUnit } ` ,
30 : '' ,
60 : '' ,
[ framerateMax ] : ` ${ framerateMax } ${ framerateUnit } ` ,
} ;
2021-01-10 02:37:22 -08:00
const videoBitrateDefaults = VIDEO_VARIANT_DEFAULTS . videoBitrate ;
const videoBRMin = videoBitrateDefaults . min ;
const videoBRMax = videoBitrateDefaults . max ;
const videoBRUnit = videoBitrateDefaults . unit ;
2021-02-13 19:44:16 -05:00
const videoBRMarks = {
[ videoBRMin ] : ` ${ videoBRMin } ${ videoBRUnit } ` ,
3000 : 3000 ,
4500 : 4500 ,
[ videoBRMax ] : ` ${ videoBRMax } ${ videoBRUnit } ` ,
} ;
2021-01-10 02:37:22 -08:00
2021-02-13 19:44:16 -05:00
const selectedVideoBRnote = ( ) = > {
let note = ` Selected: ${ dataState . videoBitrate } ${ videoBRUnit } ` ;
2021-02-15 14:08:47 -08:00
if ( dataState . videoBitrate < 2000 ) {
2021-02-13 19:44:16 -05:00
note = ` ${ note } - Good for low bandwidth environments. ` ;
2021-02-15 14:08:47 -08:00
} else if ( dataState . videoBitrate < 3500 ) {
2021-02-13 19:44:16 -05:00
note = ` ${ note } - Good for most bandwidth environments. ` ;
} else {
note = ` ${ note } - Good for high bandwidth environments. ` ;
}
return note ;
} ;
const selectedFramerateNote = ( ) = > {
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 120 :
note = ` ${ note } - Experimental, use at your own risk! ` ;
break ;
default :
note = '' ;
}
return note ;
} ;
2021-01-10 02:37:22 -08:00
return (
2021-02-04 08:04:00 -08:00
< div className = "config-variant-form" >
2021-02-12 23:55:59 -08:00
< p className = "description" >
2021-02-15 22:09:34 +00:00
< a href = "https://owncast.online/docs/video" > Learn more < / a > about how each of these settings
can impact the performance of your server .
2021-02-12 23:55:59 -08:00
< / p >
2021-01-10 02:37:22 -08:00
2021-02-14 18:46:34 -08:00
< Row gutter = { 16 } >
2021-02-14 22:20:25 -08:00
< Col sm = { 24 } md = { 12 } >
2021-02-12 23:55:59 -08:00
{ /* ENCODER PRESET FIELD */ }
< div className = "form-module cpu-usage-container" >
< CPUUsageSelector
defaultValue = { dataState . cpuUsageLevel }
onChange = { handleVideoCpuUsageLevelChange }
2021-01-10 02:37:22 -08:00
/ >
2021-02-15 22:09:34 +00:00
< p className = "read-more-subtext" >
< a href = "https://owncast.online/docs/video/#cpu-usage" > Read more about CPU usage . < / a >
< / p >
2021-01-10 02:37:22 -08:00
< / div >
2021-02-04 08:04:00 -08:00
2021-02-14 18:46:34 -08:00
{ /* VIDEO PASSTHROUGH FIELD - currently disabled */ }
2021-02-12 23:55:59 -08:00
< div style = { { display : 'none' } } className = "form-module" >
2021-02-14 18:46:34 -08:00
< ToggleSwitch
label = "Use Video Passthrough?"
fieldName = "video-passthrough"
tip = { VIDEO_VARIANT_DEFAULTS . videoPassthrough . tip }
checked = { dataState . videoPassthrough }
onChange = { handleVideoPassChange }
/ >
2021-02-12 23:55:59 -08:00
< / div >
2021-02-14 18:46:34 -08:00
< / Col >
2021-02-12 23:55:59 -08:00
2021-02-14 22:20:25 -08:00
< Col sm = { 24 } md = { 12 } >
2021-02-12 23:55:59 -08:00
{ /* VIDEO BITRATE FIELD */ }
2021-02-14 18:46:34 -08:00
< div
2021-02-15 22:09:34 +00:00
className = { ` form-module bitrate-container ${
dataState . videoPassthrough ? 'disabled' : ''
} ` }
2021-02-14 18:46:34 -08:00
>
< Typography.Title level = { 3 } > Video Bitrate < / Typography.Title >
2021-02-12 23:55:59 -08:00
< p className = "description" > { VIDEO_VARIANT_DEFAULTS . videoBitrate . tip } < / p >
< div className = "segment-slider-container" >
2021-01-10 02:37:22 -08:00
< Slider
2021-02-12 23:55:59 -08:00
tipFormatter = { value = > ` ${ value } ${ videoBRUnit } ` }
disabled = { dataState . videoPassthrough === true }
defaultValue = { dataState . videoBitrate }
value = { dataState . videoBitrate }
onChange = { handleVideoBitrateChange }
step = { videoBitrateDefaults . incrementBy }
min = { videoBRMin }
max = { videoBRMax }
2021-02-13 19:44:16 -05:00
marks = { videoBRMarks }
2021-01-10 02:37:22 -08:00
/ >
2021-02-14 18:46:34 -08:00
< p className = "selected-value-note" > { selectedVideoBRnote ( ) } < / p >
2021-01-10 02:37:22 -08:00
< / div >
2021-02-15 22:09:34 +00:00
< p className = "read-more-subtext" >
< a href = "https://owncast.online/docs/video/#bitrate" > Read more about bitrates . < / a >
< / p >
2021-01-10 02:37:22 -08:00
< / div >
2021-02-14 18:46:34 -08:00
< / Col >
< / Row >
< Collapse className = "advanced-settings" >
< Panel header = "Advanced Settings" key = "1" >
< p className = "description" >
Resizing your content will take additional resources on your server . If you wish to
2021-02-15 14:08:47 -08:00
optionally resize your content for this stream output then you should either set the
width < strong > or < / strong > the height to keep your aspect ratio . { ' ' }
< a href = "https://owncast.online/docs/video/#resolution" > Read more about resolutions . < / a >
2021-02-14 18:46:34 -08:00
< / p >
< TextField
type = "number"
{ . . . VIDEO_VARIANT_DEFAULTS . scaledWidth }
value = { dataState . scaledWidth }
onChange = { handleScaledWidthChanged }
/ >
< TextField
type = "number"
{ . . . VIDEO_VARIANT_DEFAULTS . scaledHeight }
value = { dataState . scaledHeight }
onChange = { handleScaledHeightChanged }
/ >
2021-02-12 23:55:59 -08:00
2021-02-14 18:46:34 -08:00
{ /* FRAME RATE FIELD */ }
< div className = "form-module frame-rate" >
< Typography.Title level = { 3 } > Frame rate < / Typography.Title >
< p className = "description" > { VIDEO_VARIANT_DEFAULTS . framerate . tip } < / p >
< div className = "segment-slider-container" >
< Slider
tipFormatter = { value = > ` ${ value } ${ framerateUnit } ` }
defaultValue = { dataState . framerate }
value = { dataState . framerate }
onChange = { handleFramerateChange }
step = { framerateDefaults . incrementBy }
min = { framerateMin }
max = { framerateMax }
marks = { framerateMarks }
/ >
< p className = "selected-value-note" > { selectedFramerateNote ( ) } < / p >
2021-02-12 23:55:59 -08:00
< / div >
2021-02-15 22:09:34 +00:00
< p className = "read-more-subtext" >
< a href = "https://owncast.online/docs/video/#framerate" > Read more about framerates . < / a >
< / p >
2021-02-14 18:46:34 -08:00
< / div >
< / Panel >
< / Collapse >
2021-01-10 02:37:22 -08:00
< / div >
) ;
2021-01-31 01:38:20 -08:00
}