From d76b2b79b7e162a1399f39b289a110b4635dc9fd Mon Sep 17 00:00:00 2001 From: Gabe Kangas Date: Sun, 10 Dec 2023 16:16:05 -0800 Subject: [PATCH] feat(video): first steps in supporting more modern versions of ffmpeg --- controllers/admin/serverConfig.go | 2 +- core/transcoder/codecs.go | 248 ++++++++++++++++-- core/transcoder/transcoder.go | 10 +- .../transcoder_vaapi-legacy_test.go | 50 ++++ core/transcoder/transcoder_vaapi_test.go | 4 +- models/videoCodec.go | 7 + web/components/admin/CodecSelector.tsx | 35 +-- web/types/config-section.ts | 4 +- web/types/video-codec.ts | 5 + 9 files changed, 313 insertions(+), 52 deletions(-) create mode 100644 core/transcoder/transcoder_vaapi-legacy_test.go create mode 100644 models/videoCodec.go create mode 100644 web/types/video-codec.ts diff --git a/controllers/admin/serverConfig.go b/controllers/admin/serverConfig.go index 2429fdfa1..01f05d2d4 100644 --- a/controllers/admin/serverConfig.go +++ b/controllers/admin/serverConfig.go @@ -111,7 +111,7 @@ type serverConfigAdminResponse struct { VideoServingEndpoint string `json:"videoServingEndpoint"` S3 models.S3 `json:"s3"` Federation federationConfigResponse `json:"federation"` - SupportedCodecs []string `json:"supportedCodecs"` + SupportedCodecs []models.VideoCodec `json:"supportedCodecs"` ExternalActions []models.ExternalAction `json:"externalActions"` ForbiddenUsernames []string `json:"forbiddenUsernames"` SuggestedUsernames []string `json:"suggestedUsernames"` diff --git a/core/transcoder/codecs.go b/core/transcoder/codecs.go index 25564a908..e710eae40 100644 --- a/core/transcoder/codecs.go +++ b/core/transcoder/codecs.go @@ -7,6 +7,7 @@ import ( "os/exec" "strings" + "github.com/owncast/owncast/models" log "github.com/sirupsen/logrus" ) @@ -14,6 +15,7 @@ import ( type Codec interface { Name() string DisplayName() string + Key() string GlobalFlags() string PixelFormat() string Scaler() string @@ -21,17 +23,18 @@ type Codec interface { ExtraFilters() string VariantFlags(v *HLSVariant) string GetPresetForLevel(l int) string + GetRepresentation() models.VideoCodec } var supportedCodecs = map[string]string{ (&Libx264Codec{}).Name(): "libx264", (&OmxCodec{}).Name(): "omx", - (&VaapiCodec{}).Name(): "vaapi", + (&VaapiLegacyCodec{}).Name(): "vaapi (legacy)", + (&VaapiCodec{}).Name(): "vaapi (ffmpeg 5+)", (&NvencCodec{}).Name(): "NVIDIA nvenc", (&VideoToolboxCodec{}).Name(): "videotoolbox", } -// Libx264Codec represents an instance of the Libx264 Codec. type Libx264Codec struct{} // Name returns the codec name. @@ -41,7 +44,12 @@ func (c *Libx264Codec) Name() string { // DisplayName returns the human readable name of the codec. func (c *Libx264Codec) DisplayName() string { - return "x264" + return "x264 (Default)" +} + +// Name returns the codec key. +func (c *Libx264Codec) Key() string { + return c.Name() } // GlobalFlags are the global flags used with this codec in the transcoder. @@ -100,6 +108,15 @@ func (c *Libx264Codec) GetPresetForLevel(l int) string { return preset } +// GetRepresentation returns the simplified codec representation of this codec. +func (c *Libx264Codec) GetRepresentation() models.VideoCodec { + return models.VideoCodec{ + Name: c.Name(), + DisplayName: c.DisplayName(), + Key: c.Key(), + } +} + // OmxCodec represents an instance of the Omx codec. type OmxCodec struct{} @@ -113,6 +130,11 @@ func (c *OmxCodec) DisplayName() string { return "OpenMAX (omx)" } +// Name returns the codec key. +func (c *OmxCodec) Key() string { + return c.Name() +} + // GlobalFlags are the global flags used with this codec in the transcoder. func (c *OmxCodec) GlobalFlags() string { return "" @@ -165,7 +187,99 @@ func (c *OmxCodec) GetPresetForLevel(l int) string { return preset } -// VaapiCodec represents an instance of the Vaapi codec. +// GetRepresentation returns the simplified codec representation of this codec. +func (c *OmxCodec) GetRepresentation() models.VideoCodec { + return models.VideoCodec{ + Name: c.Name(), + DisplayName: c.DisplayName(), + Key: c.Key(), + } +} + +// VaapiLegacyCodec represents an instance of the Vaapi codec. +type VaapiLegacyCodec struct{} + +// Name returns the codec name. +func (c *VaapiLegacyCodec) Name() string { + return "h264_vaapi" //nolint:goconst +} + +// DisplayName returns the human readable name of the codec. +func (c *VaapiLegacyCodec) DisplayName() string { + return "VA-API (Legacy)" +} + +// Name returns the codec key. +func (c *VaapiLegacyCodec) Key() string { + return "h264_vaapi_legacy" +} + +// GlobalFlags are the global flags used with this codec in the transcoder. +func (c *VaapiLegacyCodec) GlobalFlags() string { + flags := []string{ + "-hwaccel", "vaapi", + "-hwaccel_output_format", "vaapi", + "-vaapi_device", "/dev/dri/renderD128", + } + + return strings.Join(flags, " ") +} + +// PixelFormat is the pixel format required for this codec. +func (c *VaapiLegacyCodec) PixelFormat() string { + return "vaapi_vld" +} + +// Scaler is the scaler used for resizing the video in the transcoder. +func (c *VaapiLegacyCodec) Scaler() string { + return "scale_vaapi" +} + +// ExtraFilters are the extra filters required for this codec in the transcoder. +func (c *VaapiLegacyCodec) ExtraFilters() string { + return "" +} + +// ExtraArguments are the extra arguments used with this codec in the transcoder. +func (c *VaapiLegacyCodec) ExtraArguments() string { + return "" +} + +// VariantFlags returns a string representing a single variant processed by this codec. +func (c *VaapiLegacyCodec) VariantFlags(v *HLSVariant) string { + return "" +} + +// GetPresetForLevel returns the string preset for this codec given an integer level. +func (c *VaapiLegacyCodec) GetPresetForLevel(l int) string { + presetMapping := map[int]string{ + 0: "ultrafast", + 1: "superfast", + 2: "veryfast", + 3: "faster", + 4: "fast", + } + + preset, ok := presetMapping[l] + if !ok { + defaultPreset := presetMapping[1] + log.Errorf("Invalid level for vaapi preset %d, defaulting to %s", l, defaultPreset) + return defaultPreset + } + + return preset +} + +// GetRepresentation returns the simplified codec representation of this codec. +func (c *VaapiLegacyCodec) GetRepresentation() models.VideoCodec { + return models.VideoCodec{ + Name: c.Name(), + DisplayName: c.DisplayName(), + Key: c.Key(), + } +} + +// VaapiCodec represents the vaapi codec included in ffmpeg 5.0+. type VaapiCodec struct{} // Name returns the codec name. @@ -175,7 +289,12 @@ func (c *VaapiCodec) Name() string { // DisplayName returns the human readable name of the codec. func (c *VaapiCodec) DisplayName() string { - return "VA-API" + return "VA-API (ffmpeg 5+)" +} + +// Name returns the codec key. +func (c *VaapiCodec) Key() string { + return "h264_vaapi" } // GlobalFlags are the global flags used with this codec in the transcoder. @@ -191,7 +310,7 @@ func (c *VaapiCodec) GlobalFlags() string { // PixelFormat is the pixel format required for this codec. func (c *VaapiCodec) PixelFormat() string { - return "vaapi_vld" + return "vaapi" } // Scaler is the scaler used for resizing the video in the transcoder. @@ -234,6 +353,15 @@ func (c *VaapiCodec) GetPresetForLevel(l int) string { return preset } +// GetRepresentation returns the simplified codec representation of this codec. +func (c *VaapiCodec) GetRepresentation() models.VideoCodec { + return models.VideoCodec{ + Name: c.Name(), + DisplayName: c.DisplayName(), + Key: c.Key(), + } +} + // NvencCodec represents an instance of the Nvenc Codec. type NvencCodec struct{} @@ -247,6 +375,11 @@ func (c *NvencCodec) DisplayName() string { return "nvidia nvenc" } +// Name returns the codec key. +func (c *NvencCodec) Key() string { + return c.Name() +} + // GlobalFlags are the global flags used with this codec in the transcoder. func (c *NvencCodec) GlobalFlags() string { flags := []string{ @@ -302,6 +435,15 @@ func (c *NvencCodec) GetPresetForLevel(l int) string { return preset } +// GetRepresentation returns the simplified codec representation of this codec. +func (c *NvencCodec) GetRepresentation() models.VideoCodec { + return models.VideoCodec{ + Name: c.Name(), + DisplayName: c.DisplayName(), + Key: c.Key(), + } +} + // QuicksyncCodec represents an instance of the Intel Quicksync Codec. type QuicksyncCodec struct{} @@ -315,6 +457,11 @@ func (c *QuicksyncCodec) DisplayName() string { return "Intel QuickSync" } +// Name returns the codec key. +func (c *QuicksyncCodec) Key() string { + return c.Name() +} + // GlobalFlags are the global flags used with this codec in the transcoder. func (c *QuicksyncCodec) GlobalFlags() string { return "" @@ -365,6 +512,15 @@ func (c *QuicksyncCodec) GetPresetForLevel(l int) string { return preset } +// GetRepresentation returns the simplified codec representation of this codec. +func (c *QuicksyncCodec) GetRepresentation() models.VideoCodec { + return models.VideoCodec{ + Name: c.Name(), + DisplayName: c.DisplayName(), + Key: c.Key(), + } +} + // Video4Linux represents an instance of the V4L Codec. type Video4Linux struct{} @@ -378,6 +534,11 @@ func (c *Video4Linux) DisplayName() string { return "Video4Linux" } +// Name returns the codec key. +func (c *Video4Linux) Key() string { + return c.Name() +} + // GlobalFlags are the global flags used with this codec in the transcoder. func (c *Video4Linux) GlobalFlags() string { return "" @@ -427,6 +588,15 @@ func (c *Video4Linux) GetPresetForLevel(l int) string { return preset } +// GetRepresentation returns the simplified codec representation of this codec. +func (c *Video4Linux) GetRepresentation() models.VideoCodec { + return models.VideoCodec{ + Name: c.Name(), + DisplayName: c.DisplayName(), + Key: c.Key(), + } +} + // VideoToolboxCodec represents an instance of the VideoToolbox codec. type VideoToolboxCodec struct{} @@ -440,6 +610,11 @@ func (c *VideoToolboxCodec) DisplayName() string { return "VideoToolbox" } +// Name returns the codec key. +func (c *VideoToolboxCodec) Key() string { + return c.Name() +} + // GlobalFlags are the global flags used with this codec in the transcoder. func (c *VideoToolboxCodec) GlobalFlags() string { var flags []string @@ -502,25 +677,35 @@ func (c *VideoToolboxCodec) GetPresetForLevel(l int) string { return preset } +// GetRepresentation returns the simplified codec representation of this codec. +func (c *VideoToolboxCodec) GetRepresentation() models.VideoCodec { + return models.VideoCodec{ + Name: c.Name(), + DisplayName: c.DisplayName(), + Key: c.Key(), + } +} + // GetCodecs will return the supported codecs available on the system. -func GetCodecs(ffmpegPath string) []string { - codecs := make([]string, 0) +func GetCodecs(ffmpegPath string) []models.VideoCodec { + codecs := make([]models.VideoCodec, 0) cmd := exec.Command(ffmpegPath, "-encoders") out, err := cmd.CombinedOutput() if err != nil { - log.Errorln(err) return codecs } - response := string(out) lines := strings.Split(response, "\n") for _, line := range lines { if strings.Contains(line, "H.264") { fields := strings.Fields(line) - codec := fields[1] - if _, supported := supportedCodecs[codec]; supported { - codecs = append(codecs, codec) + codecString := fields[1] + supportedCodecsForName := getCodec(codecString) + for _, codec := range supportedCodecsForName { + if _, supported := supportedCodecs[codecString]; supported { + codecs = append(codecs, codec.GetRepresentation()) + } } } } @@ -528,19 +713,44 @@ func GetCodecs(ffmpegPath string) []string { return codecs } -func getCodec(name string) Codec { +func getCodec(name string) []Codec { switch name { case (&NvencCodec{}).Name(): - return &NvencCodec{} + return []Codec{&NvencCodec{}} + case (&VaapiLegacyCodec{}).Name(): + return []Codec{&VaapiLegacyCodec{}, &VaapiCodec{}} case (&VaapiCodec{}).Name(): - return &VaapiCodec{} + return []Codec{&VaapiLegacyCodec{}, &VaapiCodec{}} case (&QuicksyncCodec{}).Name(): - return &QuicksyncCodec{} + return []Codec{&QuicksyncCodec{}} case (&OmxCodec{}).Name(): - return &OmxCodec{} + return []Codec{&OmxCodec{}} case (&Video4Linux{}).Name(): - return &Video4Linux{} + return []Codec{&Video4Linux{}} case (&VideoToolboxCodec{}).Name(): + return []Codec{&VideoToolboxCodec{}} + case (&Libx264Codec{}).Name(): + return []Codec{&Libx264Codec{}} + default: + return []Codec{} + } +} + +func getCodecForKey(key string) Codec { + switch key { + case (&NvencCodec{}).Key(): + return &NvencCodec{} + case (&VaapiLegacyCodec{}).Key(): + return &VaapiLegacyCodec{} + case (&VaapiCodec{}).Key(): + return &VaapiCodec{} + case (&QuicksyncCodec{}).Key(): + return &QuicksyncCodec{} + case (&OmxCodec{}).Key(): + return &OmxCodec{} + case (&Video4Linux{}).Key(): + return &Video4Linux{} + case (&VideoToolboxCodec{}).Key(): return &VideoToolboxCodec{} default: return &Libx264Codec{} diff --git a/core/transcoder/transcoder.go b/core/transcoder/transcoder.go index ff1bbaa72..bdad8e8fc 100644 --- a/core/transcoder/transcoder.go +++ b/core/transcoder/transcoder.go @@ -274,6 +274,8 @@ func getVariantFromConfigQuality(quality models.StreamOutputVariant, index int) // NewTranscoder will return a new Transcoder, populated by the config. func NewTranscoder() *Transcoder { ffmpegPath := utils.ValidatedFfmpegPath(data.GetFfMpegPath()) + codecKey := data.GetVideoCodec() + codec := getCodecForKey(codecKey) transcoder := new(Transcoder) transcoder.ffmpegPath = ffmpegPath @@ -281,7 +283,7 @@ func NewTranscoder() *Transcoder { transcoder.currentStreamOutputSettings = data.GetStreamOutputVariants() transcoder.currentLatencyLevel = data.GetStreamLatencyLevel() - transcoder.codec = getCodec(data.GetVideoCodec()) + transcoder.codec = codec transcoder.segmentOutputPath = config.HLSStoragePath transcoder.playlistOutputPath = config.HLSStoragePath @@ -448,7 +450,7 @@ func (t *Transcoder) SetInternalHTTPPort(port string) { t.internalListenerPort = port } -// SetCodec will set the codec to be used for the transocder. -func (t *Transcoder) SetCodec(codecName string) { - t.codec = getCodec(codecName) +// SetCodec will set the codec to be used for the transcoder. +func (t *Transcoder) SetCodec(codecKey string) { + t.codec = getCodecForKey(codecKey) } diff --git a/core/transcoder/transcoder_vaapi-legacy_test.go b/core/transcoder/transcoder_vaapi-legacy_test.go new file mode 100644 index 000000000..17497fff9 --- /dev/null +++ b/core/transcoder/transcoder_vaapi-legacy_test.go @@ -0,0 +1,50 @@ +package transcoder + +import ( + "path/filepath" + "testing" + + "github.com/owncast/owncast/models" +) + +func TestFFmpegVaapiLegacyCommand(t *testing.T) { + latencyLevel := models.GetLatencyLevel(2) + codec := VaapiLegacyCodec{} + + transcoder := new(Transcoder) + transcoder.ffmpegPath = filepath.Join("fake", "path", "ffmpeg") + transcoder.SetInput("fakecontent.flv") + transcoder.SetOutputPath("fakeOutput") + transcoder.SetIdentifier("jdofFGg") + transcoder.SetInternalHTTPPort("8123") + transcoder.SetCodec(codec.Key()) + transcoder.currentLatencyLevel = latencyLevel + + variant := HLSVariant{} + variant.videoBitrate = 1200 + variant.isAudioPassthrough = true + variant.SetVideoFramerate(30) + variant.SetCPUUsageLevel(2) + transcoder.AddVariant(variant) + + variant2 := HLSVariant{} + variant2.videoBitrate = 3500 + variant2.isAudioPassthrough = true + variant2.SetVideoFramerate(24) + variant2.SetCPUUsageLevel(4) + transcoder.AddVariant(variant2) + + variant3 := HLSVariant{} + variant3.isAudioPassthrough = true + variant3.isVideoPassthrough = true + transcoder.AddVariant(variant3) + + cmd := transcoder.getString() + + expectedLogPath := filepath.Join("data", "logs", "transcoder.log") + expected := `FFREPORT=file="` + expectedLogPath + `":level=32 ` + transcoder.ffmpegPath + ` -hide_banner -loglevel warning -hwaccel vaapi -hwaccel_output_format vaapi -vaapi_device /dev/dri/renderD128 -fflags +genpts -flags +cgop -i fakecontent.flv -map v:0 -c:v:0 h264_vaapi -b:v:0 1008k -maxrate:v:0 1088k -g:v:0 90 -keyint_min:v:0 90 -r:v:0 30 -map a:0? -c:a:0 copy -preset veryfast -map v:0 -c:v:1 h264_vaapi -b:v:1 3308k -maxrate:v:1 3572k -g:v:1 72 -keyint_min:v:1 72 -r:v:1 24 -map a:0? -c:a:1 copy -preset fast -map v:0 -c:v:2 copy -map a:0? -c:a:2 copy -preset ultrafast -var_stream_map "v:0,a:0 v:1,a:1 v:2,a:2 " -f hls -hls_time 3 -hls_list_size 10 -hls_flags program_date_time+independent_segments+omit_endlist -segment_format_options mpegts_flags=mpegts_copyts=1 -pix_fmt vaapi_vld -sc_threshold 0 -master_pl_name stream.m3u8 -hls_segment_filename http://127.0.0.1:8123/%v/stream-jdofFGg-%d.ts -max_muxing_queue_size 400 -method PUT http://127.0.0.1:8123/%v/stream.m3u8` + + if cmd != expected { + t.Errorf("ffmpeg command does not match expected.\nGot %s\n, want: %s", cmd, expected) + } +} diff --git a/core/transcoder/transcoder_vaapi_test.go b/core/transcoder/transcoder_vaapi_test.go index affa7fcac..a7d6be69c 100644 --- a/core/transcoder/transcoder_vaapi_test.go +++ b/core/transcoder/transcoder_vaapi_test.go @@ -17,7 +17,7 @@ func TestFFmpegVaapiCommand(t *testing.T) { transcoder.SetOutputPath("fakeOutput") transcoder.SetIdentifier("jdofFGg") transcoder.SetInternalHTTPPort("8123") - transcoder.SetCodec(codec.Name()) + transcoder.SetCodec(codec.Key()) transcoder.currentLatencyLevel = latencyLevel variant := HLSVariant{} @@ -42,7 +42,7 @@ func TestFFmpegVaapiCommand(t *testing.T) { cmd := transcoder.getString() expectedLogPath := filepath.Join("data", "logs", "transcoder.log") - expected := `FFREPORT=file="` + expectedLogPath + `":level=32 ` + transcoder.ffmpegPath + ` -hide_banner -loglevel warning -hwaccel vaapi -hwaccel_output_format vaapi -vaapi_device /dev/dri/renderD128 -fflags +genpts -flags +cgop -i fakecontent.flv -map v:0 -c:v:0 h264_vaapi -b:v:0 1008k -maxrate:v:0 1088k -g:v:0 90 -keyint_min:v:0 90 -r:v:0 30 -map a:0? -c:a:0 copy -preset veryfast -map v:0 -c:v:1 h264_vaapi -b:v:1 3308k -maxrate:v:1 3572k -g:v:1 72 -keyint_min:v:1 72 -r:v:1 24 -map a:0? -c:a:1 copy -preset fast -map v:0 -c:v:2 copy -map a:0? -c:a:2 copy -preset ultrafast -var_stream_map "v:0,a:0 v:1,a:1 v:2,a:2 " -f hls -hls_time 3 -hls_list_size 10 -hls_flags program_date_time+independent_segments+omit_endlist -segment_format_options mpegts_flags=mpegts_copyts=1 -pix_fmt vaapi_vld -sc_threshold 0 -master_pl_name stream.m3u8 -hls_segment_filename http://127.0.0.1:8123/%v/stream-jdofFGg-%d.ts -max_muxing_queue_size 400 -method PUT http://127.0.0.1:8123/%v/stream.m3u8` + expected := `FFREPORT=file="` + expectedLogPath + `":level=32 ` + transcoder.ffmpegPath + ` -hide_banner -loglevel warning -hwaccel vaapi -hwaccel_output_format vaapi -vaapi_device /dev/dri/renderD128 -fflags +genpts -flags +cgop -i fakecontent.flv -map v:0 -c:v:0 h264_vaapi -b:v:0 1008k -maxrate:v:0 1088k -g:v:0 90 -keyint_min:v:0 90 -r:v:0 30 -map a:0? -c:a:0 copy -preset veryfast -map v:0 -c:v:1 h264_vaapi -b:v:1 3308k -maxrate:v:1 3572k -g:v:1 72 -keyint_min:v:1 72 -r:v:1 24 -map a:0? -c:a:1 copy -preset fast -map v:0 -c:v:2 copy -map a:0? -c:a:2 copy -preset ultrafast -var_stream_map "v:0,a:0 v:1,a:1 v:2,a:2 " -f hls -hls_time 3 -hls_list_size 10 -hls_flags program_date_time+independent_segments+omit_endlist -segment_format_options mpegts_flags=mpegts_copyts=1 -pix_fmt vaapi -sc_threshold 0 -master_pl_name stream.m3u8 -hls_segment_filename http://127.0.0.1:8123/%v/stream-jdofFGg-%d.ts -max_muxing_queue_size 400 -method PUT http://127.0.0.1:8123/%v/stream.m3u8` if cmd != expected { t.Errorf("ffmpeg command does not match expected.\nGot %s\n, want: %s", cmd, expected) diff --git a/models/videoCodec.go b/models/videoCodec.go new file mode 100644 index 000000000..5325900ab --- /dev/null +++ b/models/videoCodec.go @@ -0,0 +1,7 @@ +package models + +type VideoCodec struct { + Name string `json:"name"` + DisplayName string `json:"displayName"` + Key string `json:"key"` +} diff --git a/web/components/admin/CodecSelector.tsx b/web/components/admin/CodecSelector.tsx index 49d7ff542..ba1ca8c8b 100644 --- a/web/components/admin/CodecSelector.tsx +++ b/web/components/admin/CodecSelector.tsx @@ -77,30 +77,12 @@ export const CodecSelector: FC = () => { }); } - 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 ( - - ); - }); + // console.log(supportedCodecs); + const items = supportedCodecs.map(codec => ( + + )); let description = ''; if (selectedCodec === 'libx264') { @@ -109,9 +91,12 @@ export const CodecSelector: FC = () => { } 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_legacy') { + description = + 'For versions of ffmpeg < 5.0. VA-API may be supported by your NVIDIA proprietary drivers, Mesa open-source drivers for AMD or Intel graphics.'; } 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.'; + 'For versions of ffmpeg > 5.0. 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."; diff --git a/web/types/config-section.ts b/web/types/config-section.ts index 948a60375..0f4cbd6f3 100644 --- a/web/types/config-section.ts +++ b/web/types/config-section.ts @@ -1,5 +1,7 @@ // TS types for elements on the Config pages +import { VideoCodec } from './video-codec'; + // for dropdown export interface SocialHandleDropdownItem { icon: string; @@ -147,7 +149,7 @@ export interface ConfigDetails { socketHostOverride: string; videoServingEndpoint: string; yp: ConfigDirectoryFields; - supportedCodecs: string[]; + supportedCodecs: VideoCodec[]; videoCodec: string; forbiddenUsernames: string[]; suggestedUsernames: string[]; diff --git a/web/types/video-codec.ts b/web/types/video-codec.ts new file mode 100644 index 000000000..927f4de74 --- /dev/null +++ b/web/types/video-codec.ts @@ -0,0 +1,5 @@ +export interface VideoCodec { + name: string; + displayName: string; + key: string; +}