Retune VP8/VP9 codecs

Add new params
cpuUsed: 0
tileColumns: 0
tune: screen

In VP9 it will use multithreaded encoding now.

Keyframe interval was not set properly wasting bitrate. By default. It
is changed to 120 frames instead of 5.
This commit is contained in:
sergystepanov 2026-06-11 21:44:33 +03:00
parent 2897339258
commit 9c42f1cc59
3 changed files with 501 additions and 401 deletions

View file

@ -20,360 +20,366 @@ version: 3
# new decentralized library of games
library:
# optional alias file for overriding game names from the basePath path
aliasFile: alias.txt
# root folder for the library (where games are stored)
basePath: assets/games
# a list of ignored words in the ROM filenames
ignored:
- neogeo
- pgm
# DOSBox filesystem state
- .pure
# an explicit list of supported file extensions
# which overrides Libretro emulator ROMs configs
supported:
# print some additional info
verbose: true
# enable library directory live reload
# (experimental)
watchMode: false
coordinator:
# debugging switch
# - shows debug logs
# - allows selecting worker instances
debug: false
# selects free workers:
# - empty value (default, any free)
# - ping (with the lowest ping)
selector:
monitoring:
port: 6601
# enable Go profiler HTTP server
profilingEnabled: false
metricEnabled: false
urlPrefix: /coordinator
# a custom Origins for incoming Websocket connections:
# "" -- checks same origin policy
# "*" -- allows all
# "your address" -- checks for that address
origin:
userWs:
workerWs:
# max websocket message size in bytes
maxWsSize: 32000000
# HTTP(S) server config
server:
address: :8000
cacheControl: "max-age=259200, must-revalidate"
frameOptions: ""
https: false
# Letsencrypt or self cert config
tls:
address: :443
# allowed host name
domain:
# if both are set then will use certs
# and Letsencryt instead
httpsCert:
httpsKey:
analytics:
inject: false
gtag:
worker:
# show more logs
debug: false
library:
# optional alias file for overriding game names from the basePath path
aliasFile: alias.txt
# root folder for the library (where games are stored)
basePath: assets/games
network:
# a coordinator address to connect to
coordinatorAddress: localhost:8000
# where to connect
endpoint: /wso
# ping endpoint
pingEndpoint: /echo
# set public ping address (IP or hostname)
publicAddress:
# make coordinator connection secure (wss)
secure: false
# ISO Alpha-2 country code to group workers by zones
zone:
monitoring:
# monitoring server port
port: 6602
profilingEnabled: false
# monitoring server URL prefix
metricEnabled: false
urlPrefix: /worker
server:
address: :9000
https: false
tls:
address: :444
# LetsEncrypt config
# allowed host name
domain:
# Own certs config
httpsCert:
httpsKey:
# optional server tag
tag:
# a list of ignored words in the ROM filenames
ignored:
- neogeo
- pgm
# DOSBox filesystem state
- .pure
# an explicit list of supported file extensions
# which overrides Libretro emulator ROMs configs
supported:
# print some additional info
verbose: true
# enable library directory live reload
# (experimental)
watchMode: false
coordinator:
# debugging switch
# - shows debug logs
# - allows selecting worker instances
debug: false
# selects free workers:
# - empty value (default, any free)
# - ping (with the lowest ping)
selector:
monitoring:
port: 6601
# enable Go profiler HTTP server
profilingEnabled: false
metricEnabled: false
urlPrefix: /coordinator
# a custom Origins for incoming Websocket connections:
# "" -- checks same origin policy
# "*" -- allows all
# "your address" -- checks for that address
origin:
userWs:
workerWs:
# max websocket message size in bytes
maxWsSize: 32000000
# HTTP(S) server config
server:
address: :8000
cacheControl: "max-age=259200, must-revalidate"
frameOptions: ""
https: false
# Letsencrypt or self cert config
tls:
address: :443
# allowed host name
domain:
# if both are set then will use certs
# and Letsencryt instead
httpsCert:
httpsKey:
analytics:
inject: false
gtag:
worker:
# show more logs
debug: false
library:
# root folder for the library (where games are stored)
basePath: assets/games
network:
# a coordinator address to connect to
coordinatorAddress: localhost:8000
# where to connect
endpoint: /wso
# ping endpoint
pingEndpoint: /echo
# set public ping address (IP or hostname)
publicAddress:
# make coordinator connection secure (wss)
secure: false
# ISO Alpha-2 country code to group workers by zones
zone:
monitoring:
# monitoring server port
port: 6602
profilingEnabled: false
# monitoring server URL prefix
metricEnabled: false
urlPrefix: /worker
server:
address: :9000
https: false
tls:
address: :444
# LetsEncrypt config
# allowed host name
domain:
# Own certs config
httpsCert:
httpsKey:
# optional server tag
tag:
emulator:
# set the total number of threads for the image processing
# (removed)
threads: 0
# set the total number of threads for the image processing
# (removed)
threads: 0
# enable autosave for emulator states if set to a non-zero value of seconds
autosaveSec: 0
# enable autosave for emulator states if set to a non-zero value of seconds
autosaveSec: 0
# save directory for emulator states
# special tag {user} will be replaced with current user's home dir
storage: "{user}/.cr/save"
# save directory for emulator states
# special tag {user} will be replaced with current user's home dir
storage: "{user}/.cr/save"
# path for storing emulator generated files
localPath: "./libretro"
# path for storing emulator generated files
localPath: "./libretro"
# checks if the system supports running an emulator at startup
failFast: true
# checks if the system supports running an emulator at startup
failFast: true
# do not send late video frames
skipLateFrames: false
# do not send late video frames
skipLateFrames: false
# log dropped frames (temp)
logDroppedFrames: false
# log dropped frames (temp)
logDroppedFrames: false
libretro:
# use zip compression for emulator save states
saveCompression: true
# Sets a limiter function for some spammy core callbacks.
# 0 - disabled, otherwise -- time in milliseconds for ignoring repeated calls except the last.
debounceMs: 0
# Allow duplicate frames
dup: true
# Libretro cores logging level: DEBUG = 0, INFO, WARN, ERROR, DUMMY = INT_MAX
logLevel: 1
cores:
paths:
libs: assets/cores
# Config params for Libretro cores repository,
# available types are:
# - buildbot (the default Libretro nightly repository)
# - github (GitHub raw repository with a similar structure to buildbot)
# - raw (just a link to a zip file extracted as is)
repo:
# enable auto-download for the list of cores (list->lib)
sync: true
# external cross-process mutex lock
extLock: "{user}/.cr/cloud-game.lock"
map:
darwin:
amd64:
arch: x86_64
ext: .dylib
os: osx
vendor: apple
arm64:
arch: arm64
ext: .dylib
os: osx
vendor: apple
linux:
amd64:
arch: x86_64
ext: .so
os: linux
arm:
arch: armv7-neon-hf
ext: .so
os: linux
windows:
amd64:
arch: x86_64
ext: .dll
os: windows
main:
type: buildbot
url: https://buildbot.libretro.com/nightly
# if repo has file compression
compression: zip
# a secondary repo to use i.e. for not found in the main cores
secondary:
type: github
url: https://github.com/sergystepanov/libretro-spiegel/raw/main
compression: zip
# Libretro core configuration
#
# The emulator selection will happen in this order:
# - based on the folder name in the folder param
# - based on the folder name (core name) in the list (i.e. nes, snes)
# - based on the rom names in the roms param
#
# Available config params:
# - altRepo (bool) prioritize secondary repo as the download source
# - lib (string)
# - roms ([]string)
# - scale (int) scales the output video frames by this factor.
# - folder (string)
# By default emulator selection is based on the folder named as cores
# in the list (i.e. nes, snes) but if you specify folder param,
# then it will try to load the ROM file from that folder first.
# - width (int) -- broken
# - height (int) -- broken
# - ratio (float)
# - isGlAllowed (bool)
# - usesLibCo (bool)
# - hasMultitap (bool) -- (removed)
# - coreAspectRatio (bool) -- (deprecated) correct the aspect ratio on the client with the info from the core.
# - hid (map[int][]int)
# A list of device IDs to bind to the input ports.
# Can be seen in human readable form in the console when worker.debug is enabled.
# Some cores allow binding multiple devices to a single port (DosBox), but typically,
# you should bind just one device to one port.
# - kbMouseSupport (bool) -- (temp) a flag if the core needs the keyboard and mouse on the client
# - nonBlockingSave (bool) -- write save file in a non-blocking way, needed for huge save files
# - vfr (bool)
# (experimental)
# Enable variable frame rate only for cores that can't produce a constant frame rate.
# By default, we assume that cores output frames at a constant rate which equals
# their tick rate (1/system FPS), but OpenGL cores like N64 may have significant
# frame rendering time inconsistencies. In general, VFR for CFR cores leads to
# noticeable video stutter (with the current frame rendering time calculations).
# - options ([]string) a list of Libretro core options for tweaking.
# All keys of the options should be in the double quotes in order to preserve upper-case symbols.
# - options4rom (rom[[]string])
# A list of core options to override for a specific core depending on the current ROM name.
# - hacks ([]string) a list of hacks.
# Available:
# - skip_hw_context_destroy -- don't destroy OpenGL context during Libretro core deinit.
# May help with crashes, for example, with PPSSPP.
# - skip_same_thread_save -- skip thread lock save (used with PPSSPP).
# - uniqueSaveDir (bool) -- needed only for cores (like DosBox) that persist their state into one shared file.
# This will allow for concurrent reading and saving of current states.
# - saveStateFs (string) -- the name of the file that will be initially copied into the save folder.
# All * symbols will be replaced to the name of the ROM.
list:
gba:
lib: mgba_libretro
roms: [ "gba", "gbc" ]
options:
mgba_audio_low_pass_filter: disabled
mgba_audio_low_pass_range: 50
pcsx:
lib: pcsx_rearmed_libretro
roms: [ "cue", "chd" ]
# example of folder override
folder: psx
# see: https://github.com/libretro/pcsx_rearmed/blob/master/frontend/libretro_core_options.h
options:
"pcsx_rearmed_show_bios_bootlogo": enabled
"pcsx_rearmed_drc": enabled
"pcsx_rearmed_display_internal_fps": disabled
# MAME core requires additional manual setup, please read:
# https://docs.libretro.com/library/fbneo/
mame:
lib: fbneo_libretro
folder: mame
roms: [ "zip" ]
nes:
lib: nestopia_libretro
roms: [ "nes" ]
options:
nestopia_aspect: "uncorrected"
snes:
lib: snes9x_libretro
roms: [ "smc", "sfc", "swc", "fig", "bs" ]
hid:
# set the 2nd port to RETRO_DEVICE_JOYPAD_MULTITAP ((1<<8) | 1) as SNES9x requires it
# in order to support up to 5-player games
# see: https://nintendo.fandom.com/wiki/Super_Multitap
1: 257
n64:
lib: mupen64plus_next_libretro
roms: [ "n64", "v64", "z64" ]
isGlAllowed: true
usesLibCo: true
vfr: true
# see: https://github.com/libretro/mupen64plus-libretro-nx/blob/master/libretro/libretro_core_options.h
options:
"mupen64plus-169screensize": 640x360
"mupen64plus-43screensize": 320x240
"mupen64plus-EnableCopyColorToRDRAM": Off
"mupen64plus-EnableCopyDepthToRDRAM": Off
"mupen64plus-EnableEnhancedTextureStorage": True
"mupen64plus-EnableFBEmulation": True
"mupen64plus-EnableLegacyBlending": True
"mupen64plus-FrameDuping": True
"mupen64plus-MaxTxCacheSize": 8000
"mupen64plus-ThreadedRenderer": False
"mupen64plus-cpucore": dynamic_recompiler
"mupen64plus-pak1": memory
"mupen64plus-rdp-plugin": gliden64
"mupen64plus-rsp-plugin": hle
"mupen64plus-astick-sensitivity": 100
dos:
lib: dosbox_pure_libretro
roms: [ "zip", "cue" ]
folder: dos
kbMouseSupport: true
nonBlockingSave: true
saveStateFs: "*.pure.zip"
hid:
0: [ 257, 513 ]
1: [ 257, 513 ]
2: [ 257, 513 ]
3: [ 257, 513 ]
options:
"dosbox_pure_conf": "outside"
"dosbox_pure_force60fps": "true"
libretro:
# use zip compression for emulator save states
saveCompression: true
# Sets a limiter function for some spammy core callbacks.
# 0 - disabled, otherwise -- time in milliseconds for ignoring repeated calls except the last.
debounceMs: 0
# Allow duplicate frames
dup: true
# Libretro cores logging level: DEBUG = 0, INFO, WARN, ERROR, DUMMY = INT_MAX
logLevel: 1
cores:
paths:
libs: assets/cores
# Config params for Libretro cores repository,
# available types are:
# - buildbot (the default Libretro nightly repository)
# - github (GitHub raw repository with a similar structure to buildbot)
# - raw (just a link to a zip file extracted as is)
repo:
# enable auto-download for the list of cores (list->lib)
sync: true
# external cross-process mutex lock
extLock: "{user}/.cr/cloud-game.lock"
map:
darwin:
amd64:
arch: x86_64
ext: .dylib
os: osx
vendor: apple
arm64:
arch: arm64
ext: .dylib
os: osx
vendor: apple
linux:
amd64:
arch: x86_64
ext: .so
os: linux
arm:
arch: armv7-neon-hf
ext: .so
os: linux
windows:
amd64:
arch: x86_64
ext: .dll
os: windows
main:
type: buildbot
url: https://buildbot.libretro.com/nightly
# if repo has file compression
compression: zip
# a secondary repo to use i.e. for not found in the main cores
secondary:
type: github
url: https://github.com/sergystepanov/libretro-spiegel/raw/main
compression: zip
# Libretro core configuration
#
# The emulator selection will happen in this order:
# - based on the folder name in the folder param
# - based on the folder name (core name) in the list (i.e. nes, snes)
# - based on the rom names in the roms param
#
# Available config params:
# - altRepo (bool) prioritize secondary repo as the download source
# - lib (string)
# - roms ([]string)
# - scale (int) scales the output video frames by this factor.
# - folder (string)
# By default emulator selection is based on the folder named as cores
# in the list (i.e. nes, snes) but if you specify folder param,
# then it will try to load the ROM file from that folder first.
# - width (int) -- broken
# - height (int) -- broken
# - ratio (float)
# - isGlAllowed (bool)
# - usesLibCo (bool)
# - hasMultitap (bool) -- (removed)
# - coreAspectRatio (bool) -- (deprecated) correct the aspect ratio on the client with the info from the core.
# - hid (map[int][]int)
# A list of device IDs to bind to the input ports.
# Can be seen in human readable form in the console when worker.debug is enabled.
# Some cores allow binding multiple devices to a single port (DosBox), but typically,
# you should bind just one device to one port.
# - kbMouseSupport (bool) -- (temp) a flag if the core needs the keyboard and mouse on the client
# - nonBlockingSave (bool) -- write save file in a non-blocking way, needed for huge save files
# - vfr (bool)
# (experimental)
# Enable variable frame rate only for cores that can't produce a constant frame rate.
# By default, we assume that cores output frames at a constant rate which equals
# their tick rate (1/system FPS), but OpenGL cores like N64 may have significant
# frame rendering time inconsistencies. In general, VFR for CFR cores leads to
# noticeable video stutter (with the current frame rendering time calculations).
# - options ([]string) a list of Libretro core options for tweaking.
# All keys of the options should be in the double quotes in order to preserve upper-case symbols.
# - options4rom (rom[[]string])
# A list of core options to override for a specific core depending on the current ROM name.
# - hacks ([]string) a list of hacks.
# Available:
# - skip_hw_context_destroy -- don't destroy OpenGL context during Libretro core deinit.
# May help with crashes, for example, with PPSSPP.
# - skip_same_thread_save -- skip thread lock save (used with PPSSPP).
# - uniqueSaveDir (bool) -- needed only for cores (like DosBox) that persist their state into one shared file.
# This will allow for concurrent reading and saving of current states.
# - saveStateFs (string) -- the name of the file that will be initially copied into the save folder.
# All * symbols will be replaced to the name of the ROM.
list:
gba:
lib: mgba_libretro
roms: ["gba", "gbc"]
options:
mgba_audio_low_pass_filter: disabled
mgba_audio_low_pass_range: 50
pcsx:
lib: pcsx_rearmed_libretro
roms: ["cue", "chd"]
# example of folder override
folder: psx
# see: https://github.com/libretro/pcsx_rearmed/blob/master/frontend/libretro_core_options.h
options:
"pcsx_rearmed_show_bios_bootlogo": enabled
"pcsx_rearmed_drc": enabled
"pcsx_rearmed_display_internal_fps": disabled
# MAME core requires additional manual setup, please read:
# https://docs.libretro.com/library/fbneo/
mame:
lib: fbneo_libretro
folder: mame
roms: ["zip"]
nes:
lib: nestopia_libretro
roms: ["nes"]
options:
nestopia_aspect: "uncorrected"
snes:
lib: snes9x_libretro
roms: ["smc", "sfc", "swc", "fig", "bs"]
hid:
# set the 2nd port to RETRO_DEVICE_JOYPAD_MULTITAP ((1<<8) | 1) as SNES9x requires it
# in order to support up to 5-player games
# see: https://nintendo.fandom.com/wiki/Super_Multitap
1: 257
n64:
lib: mupen64plus_next_libretro
roms: ["n64", "v64", "z64"]
isGlAllowed: true
usesLibCo: true
vfr: true
# see: https://github.com/libretro/mupen64plus-libretro-nx/blob/master/libretro/libretro_core_options.h
options:
"mupen64plus-169screensize": 640x360
"mupen64plus-43screensize": 320x240
"mupen64plus-EnableCopyColorToRDRAM": Off
"mupen64plus-EnableCopyDepthToRDRAM": Off
"mupen64plus-EnableEnhancedTextureStorage": True
"mupen64plus-EnableFBEmulation": True
"mupen64plus-EnableLegacyBlending": True
"mupen64plus-FrameDuping": True
"mupen64plus-MaxTxCacheSize": 8000
"mupen64plus-ThreadedRenderer": False
"mupen64plus-cpucore": dynamic_recompiler
"mupen64plus-pak1": memory
"mupen64plus-rdp-plugin": gliden64
"mupen64plus-rsp-plugin": hle
"mupen64plus-astick-sensitivity": 100
dos:
lib: dosbox_pure_libretro
roms: ["zip", "cue"]
folder: dos
kbMouseSupport: true
nonBlockingSave: true
saveStateFs: "*.pure.zip"
hid:
0: [257, 513]
1: [257, 513]
2: [257, 513]
3: [257, 513]
options:
"dosbox_pure_conf": "outside"
"dosbox_pure_force60fps": "true"
encoder:
audio:
# audio frame duration needed for WebRTC (Opus)
# most of the emulators have ~1400 samples per a video frame,
# so we keep the frame buffer roughly half of that size or 2 RTC packets per frame
# (deprecated) due to frames
frame: 10
# dynamic frames for Opus encoder
frames:
- 10
- 5
# speex (2), linear (1) or nearest neighbour (0) audio resampler
# linear should sound slightly better than 0
resampler: 2
video:
# h264, vpx (vp8) or vp9
codec: h264
# Threaded encoder if supported, 0 - auto, 1 - nope, >1 - multi-threaded
threads: 0
# see: https://trac.ffmpeg.org/wiki/Encode/H.264
h264:
# crf, cbr
mode: crf
# Constant Rate Factor (CRF) 0-51 (default: 23)
crf: 23
# Rate control options
# set the maximum bitrate
maxRate: 0
# set the expected client buffer size
bufSize: 0
# ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow, placebo
preset: superfast
# baseline, main, high, high10, high422, high444
profile: baseline
# film, animation, grain, stillimage, psnr, ssim, fastdecode, zerolatency
tune: zerolatency
# 0-3
logLevel: 0
# see: https://www.webmproject.org/docs/encoder-parameters
vpx:
# target bitrate (KBit/s)
bitrate: 1200
# force keyframe interval
keyframeInterval: 5
audio:
# audio frame duration needed for WebRTC (Opus)
# most of the emulators have ~1400 samples per a video frame,
# so we keep the frame buffer roughly half of that size or 2 RTC packets per frame
# (deprecated) due to frames
frame: 10
# dynamic frames for Opus encoder
frames:
- 10
- 5
# speex (2), linear (1) or nearest neighbour (0) audio resampler
# linear should sound slightly better than 0
resampler: 2
video:
# h264, vpx (vp8) or vp9
codec: h264
# Threaded encoder if supported, 0 - auto, 1 - nope, >1 - multi-threaded
threads: 0
# see: https://trac.ffmpeg.org/wiki/Encode/H.264
h264:
# crf, cbr
mode: crf
# Constant Rate Factor (CRF) 0-51 (default: 23)
crf: 23
# Rate control options
# set the maximum bitrate
maxRate: 0
# set the expected client buffer size
bufSize: 0
# ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow, placebo
preset: superfast
# baseline, main, high, high10, high422, high444
profile: baseline
# film, animation, grain, stillimage, psnr, ssim, fastdecode, zerolatency
tune: zerolatency
# 0-3
logLevel: 0
# see: https://www.webmproject.org/docs/encoder-parameters
vpx:
# target bitrate (KBit/s)
bitrate: 1200
# force keyframe interval
keyframeInterval: 120
# speed/quality tradeoff (0=auto, 1=slow, 8=fast)
cpuUsed: 0
# log2 of tile columns (0=auto, 0-6). VP9 only.
tileColumns: 0
# content tuning: "screen" for games. VP9 only.
tune: screen
# game recording
# (experimental)
@ -382,66 +388,66 @@ encoder:
# video as a list of PNG-encoded images, and
# one additional FFMPEG concat demux file
recording:
enabled: false
# name contains the name of the recording dir (or zip)
# format:
# %date:go_time_format% -- refer: https://go.dev/src/time/format.go
# %user% -- user name who started the recording
# %game% -- game name (game ROM name)
# %rand:len% -- a random string of given length
# as example: 20210101101010_yeE_user1_badApple
name: "%date:20060102150405%_%rand:3%_%user%_%game%"
# zip and remove recording dir on completion
zip: true
# save directory
folder: ./recording
enabled: false
# name contains the name of the recording dir (or zip)
# format:
# %date:go_time_format% -- refer: https://go.dev/src/time/format.go
# %user% -- user name who started the recording
# %game% -- game name (game ROM name)
# %rand:len% -- a random string of given length
# as example: 20210101101010_yeE_user1_badApple
name: "%date:20060102150405%_%rand:3%_%user%_%game%"
# zip and remove recording dir on completion
zip: true
# save directory
folder: ./recording
# cloud storage options
# it is mandatory to use a cloud storage when running
# a distributed multi-server configuration in order to
# share save states between nodes (resume games on a different worker)
storage:
# cloud storage provider:
# - empty (No op storage stub)
# - s3 (S3 API compatible object storage)
provider:
s3Endpoint:
s3BucketName:
s3AccessKeyId:
s3SecretAccessKey:
# cloud storage provider:
# - empty (No op storage stub)
# - s3 (S3 API compatible object storage)
provider:
s3Endpoint:
s3BucketName:
s3AccessKeyId:
s3SecretAccessKey:
webrtc:
# turn off default Pion interceptors (see: https://github.com/pion/interceptor)
# (performance)
disableDefaultInterceptors: false
# indicates the role of the DTLS transport (see: https://github.com/pion/webrtc/blob/master/dtlsrole.go)
# (debug)
# - (default)
# - 1 (auto)
# - 2 (client)
# - 3 (server)
dtlsRole:
# a list of STUN/TURN servers to use
iceServers:
- urls: stun:stun.l.google.com:19302
# configures whether the ice agent should be a lite agent (true/false)
# (performance)
# don't use iceServers when enabled
iceLite: false
# ICE configuration
# by default, ICE ports are random and unlimited
# alternatives:
# 1. instead of random unlimited port range for
# WebRTC connections, these params limit port range of ICE connections
icePorts:
min:
max:
includeLoopbackCandidate: false
# 2. select a single port to forward all ICE connections there
singlePort:
# override ICE candidate IP, see: https://github.com/pion/webrtc/issues/835,
# can be used for Docker bridged network internal IP override
iceIpMap:
# set additional log level for WebRTC separately
# -1 - trace, 6 - nothing, ..., debug - 0
logLevel: 6
# turn off default Pion interceptors (see: https://github.com/pion/interceptor)
# (performance)
disableDefaultInterceptors: false
# indicates the role of the DTLS transport (see: https://github.com/pion/webrtc/blob/master/dtlsrole.go)
# (debug)
# - (default)
# - 1 (auto)
# - 2 (client)
# - 3 (server)
dtlsRole:
# a list of STUN/TURN servers to use
iceServers:
- urls: stun:stun.l.google.com:19302
# configures whether the ice agent should be a lite agent (true/false)
# (performance)
# don't use iceServers when enabled
iceLite: false
# ICE configuration
# by default, ICE ports are random and unlimited
# alternatives:
# 1. instead of random unlimited port range for
# WebRTC connections, these params limit port range of ICE connections
icePorts:
min:
max:
includeLoopbackCandidate: false
# 2. select a single port to forward all ICE connections there
singlePort:
# override ICE candidate IP, see: https://github.com/pion/webrtc/issues/835,
# can be used for Docker bridged network internal IP override
iceIpMap:
# set additional log level for WebRTC separately
# -1 - trace, 6 - nothing, ..., debug - 0
logLevel: 6

View file

@ -71,6 +71,9 @@ type Video struct {
Vpx struct {
Bitrate uint
KeyframeInterval uint
CpuUsed int
TileColumns int
Tune string
}
}

View file

@ -14,6 +14,10 @@ package vpx
#define VP8_FOURCC 0x30385056
#define VP9_FOURCC 0x30395056
#ifndef VP9E_TUNE_SCREEN
#define VP9E_TUNE_SCREEN 1
#endif
typedef struct VpxInterface {
const char *const name;
const uint32_t fourcc;
@ -43,6 +47,30 @@ FrameBuffer get_frame_buffer(vpx_codec_ctx_t *codec, vpx_codec_iter_t *iter) {
return fb;
}
vpx_codec_err_t set_vpx_cpu_used(vpx_codec_ctx_t *ctx, int value) {
return vpx_codec_control_(ctx, VP8E_SET_CPUUSED, value);
}
vpx_codec_err_t set_vp9_tile_columns(vpx_codec_ctx_t *ctx, int value) {
return vpx_codec_control_(ctx, VP9E_SET_TILE_COLUMNS, value);
}
vpx_codec_err_t set_vp9_tune_content(vpx_codec_ctx_t *ctx, int value) {
return vpx_codec_control_(ctx, VP9E_SET_TUNE_CONTENT, value);
}
vpx_codec_err_t set_vp9_row_mt(vpx_codec_ctx_t *ctx, int value) {
return vpx_codec_control_(ctx, VP9E_SET_ROW_MT, value);
}
vpx_codec_err_t set_vp8_auto_alt_ref(vpx_codec_ctx_t *ctx, int value) {
return vpx_codec_control_(ctx, VP8E_SET_ENABLEAUTOALTREF, value);
}
vpx_codec_err_t set_vp8_noise_sensitivity(vpx_codec_ctx_t *ctx, int value) {
return vpx_codec_control_(ctx, VP8E_SET_NOISE_SENSITIVITY, value);
}
const VpxInterface vpx_encoders[] = {
{ "vp8", VP8_FOURCC, &vpx_codec_vp8_cx },
{ "vp9", VP9_FOURCC, &vpx_codec_vp9_cx },
@ -80,6 +108,7 @@ void vpx_img_read(vpx_image_t *dst, void *src) {
import "C"
import (
"fmt"
"runtime"
"unsafe"
)
@ -94,11 +123,32 @@ type Vpx struct {
func (vpx *Vpx) SetFlip(b bool) { vpx.flipped = b }
func autoThreads(configured, cpus int) int {
if configured != 0 {
return configured
}
reserve := cpus / 4
if reserve < 1 {
reserve = 1
}
if t := cpus - reserve; t > 0 {
return t
}
return 1
}
type Options struct {
// Target bandwidth to use for this stream, in kilobits per second.
Bitrate uint
// Force keyframe interval.
KeyframeInterval uint
// Speed/quality tradeoff (0=auto, 18 manual). Defaults to 0.
// Applies to both VP8 and VP9.
CpuUsed int
// Log2 of tile columns for VP9 frame-level parallelism (06). VP9 only.
TileColumns int
// Content tuning: "screen" for game/screen content. VP9 only.
Tune string
}
func NewEncoder(w, h int, th int, version int, opts *Options) (*Vpx, error) {
@ -114,7 +164,9 @@ func NewEncoder(w, h int, th int, version int, opts *Options) (*Vpx, error) {
if opts == nil {
opts = &Options{
Bitrate: 1200,
KeyframeInterval: 5,
KeyframeInterval: 120,
TileColumns: 2,
Tune: "screen",
}
}
@ -135,17 +187,56 @@ func NewEncoder(w, h int, th int, version int, opts *Options) (*Vpx, error) {
cfg.g_w = C.uint(w)
cfg.g_h = C.uint(h)
if th != 0 {
cfg.g_threads = C.uint(th)
}
cfg.g_threads = C.uint(autoThreads(th, runtime.NumCPU()))
cfg.g_lag_in_frames = 0
cfg.rc_target_bitrate = C.uint(opts.Bitrate)
cfg.g_error_resilient = C.VPX_ERROR_RESILIENT_DEFAULT
cfg.g_error_resilient = 0
if C.call_vpx_codec_enc_init(&vpx.codecCtx, encoder, &cfg) != 0 {
return nil, fmt.Errorf("failed to initialize encoder")
}
// Speed/quality tradeoff: higher = faster, lower = better quality.
if opts.CpuUsed == 0 {
thr := autoThreads(th, runtime.NumCPU())
switch {
case thr <= 2:
opts.CpuUsed = 8
case thr <= 4:
opts.CpuUsed = 7
default:
opts.CpuUsed = 6
}
}
C.set_vpx_cpu_used(&vpx.codecCtx, C.int(opts.CpuUsed))
// VP9-specific tuning.
if version == 9 {
if opts.TileColumns == 0 {
thr := autoThreads(th, runtime.NumCPU())
if thr >= 4 {
opts.TileColumns = 2
} else if thr >= 2 {
opts.TileColumns = 1
}
}
if opts.TileColumns > 0 {
C.set_vp9_tile_columns(&vpx.codecCtx, C.int(opts.TileColumns))
}
if opts.Tune == "screen" {
C.set_vp9_tune_content(&vpx.codecCtx, C.VP9E_TUNE_SCREEN)
}
C.set_vp9_row_mt(&vpx.codecCtx, 1)
}
// VP8 real-time tuning: disable features that add latency.
if version == 8 {
// No alt-ref frames for zero-latency.
C.set_vp8_auto_alt_ref(&vpx.codecCtx, 0)
// Reduce noise sensitivity — game content is low-noise.
C.set_vp8_noise_sensitivity(&vpx.codecCtx, 0)
}
return &vpx, nil
}