Jitsi Videobridge is a WebRTC compatible video router or SFU that lets build highly scalable video conferencing infrastructure (i.e., up to hundreds of conferences per server).
We run a jitsi shard with two videobridges and one jicofo,prosody server together with a separat jigasi server. Before updating the videobridge to the new version, jigasi was able to call into a conference and the caller could talk and hear others.
After the update, after the caller joint the conference, jigasi stoped the stream and hang up after appr. 5 seconds, hence the caller is leving the meeting.
Jigasi is still running in an old version, however upgrading it to the latest release does not change anything.
The configuration of all services stayed the same. And when I downgrade back only the videobridge, jigasi can join the meeting and stays inside.
Steps to reproduce
Upgrade all services from Jitsi to the latest version.
Keep the old configuration and restart all services.
Server 2:
jigasi 1.1-231-gd792d0f-1
asterisk 1:18.10.0~dfsg+~cs6.10.40431411-2
Configuration
Config Jigasi
#Sample config with one XMPP and one SIP account configured
# Replace {sip-pass-hash} with SIP user password hash
# as well as other account properties
# Name of default JVB room that will be joined if no special header is included
# in SIP invite
# org.jitsi.jigasi.DEFAULT_JVB_ROOM_NAME=siptest@conference.xxxxxxxxxxxxxxx
org.jitsi.jigasi.MUC_SERVICE_ADDRESS=conference.xxxxxxxxxxxxxxx
net.java.sip.communicator.impl.protocol.SingleCallInProgressPolicy.enabled=false
org.jitsi.impl.neomedia.transform.csrc.CsrcTransformEngine.DISCARD_CONTRIBUTING_SOURCES=true
# Should be enabled when using translator mode
#net.java.sip.communicator.impl.neomedia.audioSystem.audiosilence.captureDevice_list=["AudioSilenceCaptureDevice:noTransferData"]
net.java.sip.communicator.plugin.reconnectplugin.ATLEAST_ONE_SUCCESSFUL_CONNECTION.acc1=true
net.java.sip.communicator.impl.protocol.sip.SKIP_REINVITE_ON_FOCUS_CHANGE_PROP=true
# Adjust opus encoder complexity
net.java.sip.communicator.impl.neomedia.codec.audio.opus.encoder.COMPLEXITY=10
# Disables packet logging
net.java.sip.communicator.packetlogging.PACKET_LOGGING_ENABLED=false
net.java.sip.communicator.impl.protocol.sip.acc1=acc1
net.java.sip.communicator.impl.protocol.sip.acc1.ACCOUNT_UID=xxxxxxxxxxxxxxx
net.java.sip.communicator.impl.protocol.sip.acc1.PASSWORD=xxxxxxxxxxxxxxx
net.java.sip.communicator.impl.protocol.sip.acc1.PROTOCOL_NAME=SIP
net.java.sip.communicator.impl.protocol.sip.acc1.SERVER_ADDRESS=xxxxxxxxxxxxxxx
net.java.sip.communicator.impl.protocol.sip.acc1.USER_ID=xxxxxxxxxxxxxxx
net.java.sip.communicator.impl.protocol.sip.acc1.KEEP_ALIVE_INTERVAL=25
net.java.sip.communicator.impl.protocol.sip.acc1.KEEP_ALIVE_METHOD=OPTIONS
net.java.sip.communicator.impl.protocol.sip.acc1.VOICEMAIL_ENABLED=false
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.AMR-WB/16000=750
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.G722/16000=710
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.G722/8000=700
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.ALAW/8000=690
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.ALAW/16000=680
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.ULAW/8000=670
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.ULAW/16000=660
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.GSM/8000=0
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.H263-1998/90000=0
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.H264/90000=0
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.PCMA/8000=600
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.PCMU/8000=650
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.SILK/12000=0
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.SILK/16000=0
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.SILK/24000=0
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.SILK/8000=0
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.VP8/90000=0
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.iLBC/8000=10
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.opus/48000=1000
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.red/90000=0
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.speex/16000=0
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.speex/32000=0
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.speex/8000=0
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.telephone-event/8000=1
net.java.sip.communicator.impl.protocol.sip.acc1.Encodings.ulpfec/90000=0
net.java.sip.communicator.impl.protocol.sip.acc1.OVERRIDE_ENCODINGS=true
net.java.sip.communicator.impl.protocol.sip.acc1.DEFAULT_ENCRYPTION=false
# If an authenticated (hidden) domain is used to connect to a conference,
# PREVENT_AUTH_LOGIN will prevent the SIP participant from being seen as a
# hidden participant in the conference
#net.java.sip.communicator.impl.protocol.sip.acc1.PREVENT_AUTH_LOGIN=FALSE
# Used when incoming calls are used in multidomain environment, used to detect subdomains
# used for constructing callResource and eventually contacting jicofo
net.java.sip.communicator.impl.protocol.sip.acc1.DOMAIN_BASE=xxxxxxxxxxxxxxx
net.java.sip.communicator.impl.protocol.sip.acc1.JITSI_AUTH_TOKEN_HEADER_NAME=Jitsi-Auth-Token
net.java.sip.communicator.impl.protocol.sip.acc1.JITSI_MEET_ROOM_HEADER_NAME=Jitsi-Conference-Room
net.java.sip.communicator.impl.protocol.sip.acc1.JITSI_MEET_DOMAIN_BASE_HEADER_NAME=Jitsi-Domain-Header
# the pattern to be used as bosh url when using bosh in multidomain environment
net.java.sip.communicator.impl.protocol.sip.acc1.BOSH_URL_PATTERN=xxxxxxxxxxxxxxx
# can be enabled to disable audio mixing and use translator, jigasi will act as jvb, just forward every ssrc stream it receives.
#net.java.sip.communicator.impl.protocol.sip.acc1.USE_TRANSLATOR_IN_CONFERENCE=true
# we can receive dial/hangup only from the control muc
org.jitsi.jigasi.ALLOWED_JID=JigasiBrewery@internal.auth.xxxxxxxxxxxxxxx
org.jitsi.jigasi.BREWERY_ENABLED=true
# We can use the prefix org.jitsi.jigasi.xmpp.acc to override any of the
# properties that will be used for creating xmpp account for communication.
# The following two props assume we are using jigasi on the same machine as
# the xmpp server.
org.jitsi.jigasi.xmpp.acc.IS_SERVER_OVERRIDDEN=true
org.jitsi.jigasi.xmpp.acc.SERVER_ADDRESS=xxxxxxxxxxxxxxx
org.jitsi.jigasi.xmpp.acc.VIDEO_CALLING_DISABLED=true
org.jitsi.jigasi.xmpp.acc.JINGLE_NODES_ENABLED=false
org.jitsi.jigasi.xmpp.acc.AUTO_DISCOVER_STUN=false
org.jitsi.jigasi.xmpp.acc.IM_DISABLED=true
org.jitsi.jigasi.xmpp.acc.SERVER_STORED_INFO_DISABLED=true
org.jitsi.jigasi.xmpp.acc.IS_FILE_TRANSFER_DISABLED=true
org.jitsi.jigasi.xmpp.acc.KEEP_ALIVE_METHOD=XEP-0199
org.jitsi.jigasi.xmpp.acc.KEEP_ALIVE_INTERVAL=30
org.jitsi.jigasi.xmpp.acc.USE_DEFAULT_STUN_SERVER=false
# Or you can use bosh for the connection establishment by specifing the URL to use.
# Used when outgoing calls are used in multidomain environment, used to detect subdomains
# org.jitsi.jigasi.xmpp.acc.DOMAIN_BASE=xxxxxxxxxxxxxxx
org.jitsi.jigasi.xmpp.acc.BOSH_URL_PATTERN=xxxxxxxxxxxxxxx
# can be enabled to disable audio mixing and use translator, jigasi will act as jvb, just forward every ssrc stream it receives.
# org.jitsi.jigasi.xmpp.acc.USE_TRANSLATOR_IN_CONFERENCE=true
# If you want jigasi to perform authenticated login instead of anonymous login
# to the XMPP server, you can set the following properties.
# org.jitsi.jigasi.xmpp.acc.USER_ID=jigasi@auth.xxxxxxxxxxxxxxx
# org.jitsi.jigasi.xmpp.acc.PASS=xxxxxxxxxxxxxxx
# org.jitsi.jigasi.xmpp.acc.ANONYMOUS_AUTH=false
# To fix SSL/TLS required by client but not supported by server
org.jitsi.jigasi.xmpp.acc.ALLOW_NON_SECURE=true
# If you want to disconnect jigasi calls automatically when all web users have
# left, you can set the following property to false.
# org.jitsi.jigasi.ALLOW_ONLY_JIGASIS_IN_ROOM=true
# If you want to use the SIP user part of the incoming/outgoing call SIP URI
# you can set the following property to true.
# org.jitsi.jigasi.USE_SIP_USER_AS_XMPP_RESOURCE=true
# Activate this property if you are using self-signed certificates or other
# type of non-trusted certicates. In this mode your service trust in the
# remote certificates always.
net.java.sip.communicator.service.gui.ALWAYS_TRUST_MODE_ENABLED=true
# Enable this property to be able to shutdown gracefully jigasi using
# a rest command
# org.jitsi.jigasi.ENABLE_REST_SHUTDOWN=true
# Options regarding Transcription. Read the README for a detailed description
# about each property
#org.jitsi.jigasi.ENABLE_TRANSCRIPTION=false
#org.jitsi.jigasi.ENABLE_SIP=true
# whether to use the more expensive, but better performing
# "video" model when doing transcription
# org.jitsi.jigasi.transcription.USE_VIDEO_MODEL = false
# delivering final transcript
# org.jitsi.jigasi.transcription.DIRECTORY=/var/lib/jigasi/transcripts
# org.jitsi.jigasi.transcription.BASE_URL=http://localhost/
# org.jitsi.jigasi.transcription.jetty.port=-1
# org.jitsi.jigasi.transcription.ADVERTISE_URL=false
# save formats
# org.jitsi.jigasi.transcription.SAVE_JSON=false
# org.jitsi.jigasi.transcription.SAVE_TXT=true
# send formats
# org.jitsi.jigasi.transcription.SEND_JSON=true
# org.jitsi.jigasi.transcription.SEND_TXT=false
# Vosk server
# org.jitsi.jigasi.transcription.customService=org.jitsi.jigasi.transcription.VoskTranscriptionService
# org.jitsi.jigasi.transcription.vosk.websocket_url=ws://localhost:2700
# translation
# org.jitsi.jigasi.transcription.ENABLE_TRANSLATION=false
# record audio. Currently only wav format is supported
# org.jitsi.jigasi.transcription.RECORD_AUDIO=false
# org.jitsi.jigasi.transcription.RECORD_AUDIO_FORMAT=wav
# execute one or more scripts when a transcript or recording is saved
# org.jitsi.jigasi.transcription.EXECUTE_SCRIPTS=true
# org.jitsi.jigasi.transcription.SCRIPTS_TO_EXECUTE_LIST_SEPARATOR=","
# org.jitsi.jigasi.transcription.SCRIPTS_TO_EXECUTE_LIST=script/example_handle_transcript_directory.sh
# filter out silent audio
#org.jitsi.jigasi.transcription.FILTER_SILENCE = false
# properties for optionally sending statistics to a DataDog server
#org.jitsi.ddclient.prefix=jitsi.jigasi
#org.jitsi.ddclient.host=localhost
#org.jitsi.ddclient.port=8125
# sip health checking
# Enables sip health checking by specifying a number/uri to call
# the target just needs to auto-connect the call play some audio,
# the call must be established for less than 10 seconds
# org.jitsi.jigasi.HEALTH_CHECK_SIP_URI=healthcheck
#
# The interval between healthcheck calls, by default is 5 minutes
# org.jitsi.jigasi.HEALTH_CHECK_INTERVAL=300000
#
# The timeout of healthcheck, if there was no successful health check for
# 10 minutes (default value) we consider jigasi unhealthy
# org.jitsi.jigasi.HEALTH_CHECK_TIMEOUT=600000
# Enabled or disable the notification when max occupants limit is reached
# org.jitsi.jigasi.NOTIFY_MAX_OCCUPANTS=false
org.jitsi.jigasi.rest.jetty.port=9001
Config Videobridge
videobridge {
entity-expiration {
# If an entity has no activity after this timeout, it is expired
timeout=1 minute
# The interval at which the videobridge will check for expired entities
check-interval=${videobridge.entity-expiration.timeout}
}
health {
# The interval between health checks
interval=1 minute
# The timeout for a health check. This needs to be higher than [interval], otherwise health checks timeout because
# none were scheduled.
timeout=90 seconds
# If performing a health check takes longer than this, it is considered unsuccessful.
max-check-duration=3 seconds
# Whether or not health check failures should be 'sticky'
# (i.e. once the bridge becomes unhealthy, it will never
# go back to a healthy state)
sticky-failures=false
}
ep-connection-status {
# How long we'll wait for an endpoint to *start* sending
# data before we consider it 'inactive'
first-transfer-timeout=15 seconds
# How long an endpoint can be 'inactive' before it will
# be considered disconnected
max-inactivity-limit=3 seconds
# How often we check endpoint's connectivity status
check-interval=500 milliseconds
}
cc {
bwe-change-threshold=0.15
thumbnail-max-height-px=180
onstage-ideal-height-px=1080
onstage-preferred-height-px=360
onstage-preferred-framerate=30
// Whether the bridge is allowed to oversend (send the lowest layer regardless of BWE) for on-stage endpoints. If
// allowed, it's only used when an endpoint is screensharing.
allow-oversend-onstage=true
// The maximum bitrate by which the estimation will be exceeded when oversending (if oversending is allowed).
max-oversend-bitrate=500 kbps
trust-bwe=true
# How often we check to send probing data
padding-period=15ms
# How often we'll force recalculations of forwarded
# streams
max-time-between-calculations = 15 seconds
# A JVB-wide last-n value, observed by all endpoints. Endpoints
# will take the minimum of their setting and this one (-1 implies
# no last-n limit)
jvb-last-n = -1
}
# The APIs by which the JVB can be controlled
apis {
xmpp-client {
# The interval at which presence is published in the configured MUCs.
presence-interval = ${videobridge.stats.interval}
# Controls which statistics are sent.
stats-filter {
# Whether to filter the statistics.
# If true, send whitelisted keys only. If false, send all statistics.
enabled = false
# Which statistics to send, when filter is enabled.
# Ignored if filter is disabled.
whitelist = ["average_participant_stress", "colibri2", "current_timestamp", "drain", "graceful_shutdown",
"healthy", "region", "relay_id", "release", "shutting_down", "stress_level", "version"]
}
# The size of the Smack JID cache
jid-cache-size = 1000
configs {
shard-local {
hostname = "localhost"
domain = "auth.xxxxxxxxxxxxxx"
username = "jvb"
password = "xxxxxxxxxxxxxx"
muc_jids = "JvbBrewery@internal.auth.xxxxxxxxxxxxxx"
muc_nickname = "xxxxxxxxxxxxxx"
disable_certificate_verification = true
}
}
}
# The COLIBRI REST API
rest {
enabled = true
}
jvb-api {
enabled = true
}
}
# Configuration of the different REST APIs.
# Note that the COLIBRI REST API is configured under videobridge.apis.rest instead.
rest {
debug {
enabled = true
}
health {
enabled = true
}
shutdown {
# Note that the shutdown API requires the COLIBRI API to also be enabled.
enabled = true
}
drain {
enabled = true
}
version {
enabled = true
}
}
http-servers {
# The HTTP server which hosts services intended for 'public' use
# (e.g. websockets for the bridge channel connection)
public {
# See JettyBundleActivatorConfig in Jicoco for values
port = xxxxxxxxxxxxxx
}
# The HTTP server which hosts services intended for 'private' use
# (e.g. health or debug stats)
private {
# See JettyBundleActivatorConfig in Jicoco for values
host = xxxxxxxxxxxxxx
port = xxxxxxxxxxxxxx
}
}
relay {
# Whether or not relays (octo) are enabled
enabled=true
# A string denoting the 'region' of this JVB. This region will be used by Jicofo in the selection of a bridge for
# a client by comparing it to the client's region.
# Must be set when 'enabled' is true.
region="xxxxxxxxxxxxxx"
# The unique identifier of the jitsi-videobridge instance as a relay.
# Must be set when 'enabled' is true.
relay-id="xxxxxxxxxxxxxx"
}
load-management {
# Whether or not the reducer will be enabled to take actions to mitigate load
reducer-enabled = false
load-measurements {
packet-rate {
# The packet rate at which we'll consider the bridge overloaded
load-threshold = 50000
# The packet rate at which we'll consider the bridge 'underloaded' enough
# to start recovery
recovery-threshold = 40000
}
}
load-reducers {
last-n {
# The factor by which we'll reduce the current last-n when trying to reduce load
reduction-scale = .75
# The factor by which we'll increase the current last-n when trying to recover
recover-scale = 1.25
# The minimum time in between runs of the last-n reducer to reduce or recover from
# load
impact-time = 1 minute
# The lowest value we'll set for last-n
minimum-last-n-value = 1
# The highest last-n value we'll enforce. Once the enforced last-n exceeds this value
# we'll remove the limit entirely
maximum-enforced-last-n-value = 40
}
}
// LastN limits based on conference size. Maps a conference size to the maximum number of streams that will be
// forwarded to endpoints in a conference of that size or larger (up until the next entry).
conference-last-n-limits {
// With these example values conferences with size<20 endpoints can have arbitrary lastN, conferences with
// 20 < size <= 29 can have lastN at most 20, conferences 30 < size <= 50 can have lastN at most 15.
#20 = 20,
#30 = 15,
#50 = 10,
#90 = 2
}
// An estimation of the stress an endpoint adds to the bridge when ramped up. This is communicated to jicofo
// together with the stress level, where it is used to calculate an augmented stress value for the bridge, which
// takes into account recently added endpoints:
// augmented_stress = jvb_reported_stress + number_recently_added_participants * average-participant-stress
average-participant-stress = 0.01
}
sctp {
# Whether SCTP data channels are enabled.
enabled=true
}
stats {
# The interval at which stats are gathered.
interval = 5 seconds
transports = [
{ type = "muc" }
]
}
websockets {
enabled=true
server-id="xxxxxxxxxxxxxx"
# Whether to negotiate WebSocket compression (permessage-deflate)
enable-compression = true
# Optional, even when 'enabled' is set to true
tls=true
# Must be set when enabled = true
domain="xxxxxxxxxxxxxx:443"
}
ice {
tcp {
# Whether ICE/TCP is enabled.
enabled = true
# The port to bind to for ICE/TCP.
# port = 443
# An optional additional port to advertise.
# mapped-port = 8443
# Whether to use "ssltcp" or plain "tcp".
# ssltcp = true
}
udp {
# The port for ICE/UDP.
port = 10000
}
# An optional prefix to include in STUN username fragments generated by the bridge.
# ufrag-prefix = "xxxxxxxxxxxxxx:"
# Which candidate pairs to keep alive. The accepted values are defined in ice4j's KeepAliveStrategy:
# "selected_and_tcp", "selected_only", or "all_succeeded".
keep-alive-strategy = "selected_and_tcp"
# Whether to use the "component socket" feature of ice4j.
use-component-socket = true
# Whether to attempt DNS resolution for remote candidates that contain a non-literal address. When set to 'false'
# such candidates will be ignored.
resolve-remote-candidates = false
# The nomination strategy to use for ICE. THe accepted values are defined in ice4j's NominationStrategy:
# "NominateFirstValid", "NominateHighestPriority", "NominateFirstHostOrReflexiveValid", or "NominateBestRTT".
nomination-strategy = "NominateFirstValid"
# Whether to advertise private ICE candidates, i.e. RFC 1918 IPv4 addresses and fec0::/10 and fc00::/7 IPv6 addresses.
advertise-private-candidates = true
}
transport {
send {
# The size of the dtls-transport outgoing queue. This is a per-participant
# queue. Packets from the egress end-up in this queue right before
# transmission by the outgoing srtp pipeline (which mainly consists of the
# packet sender).
#
# Its size needs to be of the same order of magnitude as the rtp sender
# queue. In a 100 participant call, assuming 300pps for the on-stage and
# 100pps for low-definition, last-n 20 and 2 participants talking, so
# 2*50pps for audio, this queue is fed 300+19*100+2*50 = 2300pps, so its
# size in terms of millis is 1024/2300*1000 ~= 445ms.
queue-size=1024
}
}
# The experimental multiple streams per endpoint support
multi-stream {
enabled = true
}
speech-activity {
# The number of speakers to include in the list of recent speakers sent with dominant speaker change
# notifications.
recent-speakers-count = 10
}
loudest {
# Whether to route only the loudest speakers. If false, all audio is forwarded.
route-loudest-only = false
# The number of current loudest speakers to route audio packets for.
# Ignored if route-loudest-only = false.
num-loudest = 3
# Whether to route dominant speaker when it is not among the current loudest speakers.
# Ignored if route-loudest-only = false.
always-route-dominant = true
# Time after which speaker is removed from loudest list if
# no new audio packets have been received from that speaker.
energy-expire-time = 150 milliseconds
# Alpha factor for exponential smoothing of energy values, multiplied by 100.
energy-alpha-pct = 50
}
version {
# Whether to announce the jitsi-videobridge version to clients in the ServerHello message.
announce = false
# A release identifier. When set, this will be appended to the version string
# that is associated with this bridge when selecting bridges for a conference.
# This allows finer-grained control of the selection process.
# Note that multiple bridges must have the same version and release identifier
# in order to share conferences between them.
#release = "123"
}
shutdown {
# The maximum amount of time to stay in GRACEFUL_SHUTDOWN before going into SHUTTING_DOWN. See ShutdownManager.
graceful-shutdown-max-duration = 24 hours
# The minimum number of participants required to stay in GRACEFUL_SHUTDOWN. If the number of participants falls
# at or below this threshold the bridge will transition to SHUTTING_DOWN. See ShutdownManager.
graceful-shutdown-min-participants = 0
# The amount of time to stay in SHUTTING_DOWN before acutally shutting down. Gives jicofo time to actively move
# participants off this bridge.
shutting-down-delay = 1 minutes
}
# Whether to start the videobridge in drain mode.
initial-drain-mode = false
# In small conferences we disable the stats filter and always forward stats. This sets the minimum conference
# size for which the filter is enabled.
stats-filter-threshold = 20
}
We run a jitsi shard with two videobridges and one jicofo,prosody server together with a separat jigasi server. Before updating the videobridge to the new version, jigasi was able to call into a conference and the caller could talk and hear others.
After the update, after the caller joint the conference, jigasi stoped the stream and hang up after appr. 5 seconds, hence the caller is leving the meeting.
Steps to reproduce
Upgrade all services from Jitsi to the latest version. Keep the old configuration and restart all services.
Environment details
Server 1: jitsi-meet-web 1.0.6776-1 jitsi-videobridge2_2.2-61-g98c9f868-1 / jitsi-videobridge2 2.2-45-ge8b20f06-1 prosody 0.11.9-2+deb11u2 jicofo 1.0-954-1
Server 2: jigasi 1.1-231-gd792d0f-1 asterisk 1:18.10.0~dfsg+~cs6.10.40431411-2
Configuration
Config Jigasi
Config Videobridge
Logs from the Videobridge and Jigasi
Link to Logs in a Gist