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

    # If enabled, health checks fail when there are no valid addresses available for ICE. Here "valid" means not
    # site local, link local or loopback.
    require-valid-address = true

    # If enabled, health checks will fail when a STUN mapping harvester is configured, but fails to get a mapping (even
    # if there is a valid address available through other mappings or locally).
    require-stun = 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 = 8 seconds

    # How often we check endpoint's connectivity status
    check-interval = 500 milliseconds
  }
  # Congestion Control
  cc {
    bwe-change-threshold = 0.15
    # The default constraint to use if the receiver signals ReceiverConstraints with missing defaultConstraints.
    default-max-height-px = 180
    # The constraint to use for the initial allocation, before the receiver has signaled ReceiverConstraints.
    initial-max-height-px = 180
    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 run bandwidth re-allocation. This is in addition to re-allocating when otherwise required (e.g.
    # a new endpoint joins or the available layers change).
    max-time-between-calculations = 5 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 initial value for the client-configured last-n setting. This applies before it is overriden by colibri or
    // data channel signaling (-1 implies no last-n limit).
    initial-last-n = -1

    # If set allows receivers to override bandwidth estimation (BWE) with a specific value signaled over the bridge
    # channel (limited to the configured value). If not set, receivers are not allowed to override BWE.
    // assumed-bandwidth-limit = 10 Mbps

    # Whether to use the target bitrate signaled in the VLA extension for allocation. When disabled we use the measured
    # bitrate instead (preserving previous behavior).
    use-vla-target-bitrate = false

    # How long after first media to ignore bandwidth estimation for the purposes of allocation.  Needed
    # for bwe algorithms that ramp up slowly; should be set to zero if this isn't a problem.

    # By default this value will depend on the BWE algorithm chosen based on values set under
    # jmt.bwe.estimator, but they can also be specified explicitly.

    # initial-ignore-bwe-period = 10 seconds
  }
  # Whether to indicate support for cryptex header extension encryption (RFC 9335)
  cryptex {
     # To endpoints
     endpoint = false
     # To other relays
     relay = false
  }
  # 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 {
        # example-connection-id {
        #   For the properties which should be
        #   filled out here, see MucClientConfiguration
        # }
      }
    }
    # The COLIBRI REST API
    rest {
      enabled = false
    }
  }
  # Configuration of the different REST APIs.
  # Note that the COLIBRI REST API is configured under videobridge.apis.rest instead.
  rest {
    debug {
      enabled = true
    }
    drain {
      enabled = true
    }
    health {
      enabled = true
    }
    prometheus {
      enabled = true
    }
    rtcstats {
      enabled = true
    }
    shutdown {
      # Note that the shutdown API requires the COLIBRI API to also be enabled.
      enabled = false
    }
    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 = -1
      tls-port = -1
    }
    # The HTTP server which hosts services intended for 'private' use
    # (e.g. health or debug stats)
    private {
      # See JettyBundleActivatorConfig in Jicoco for values
      host = 127.0.0.1
    }
  }
  relay {
    # Whether or not relays (octo) are enabled
    enabled = false

    # 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 = "us-west-1"

    # The unique identifier of the jitsi-videobridge instance as a relay.
    # Must be set when 'enabled' is true.
    #relay-id = "jvb-1234"
  }
  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
      }
      cpu-usage {
        load-threshold = 0.9
        recovery-threshold = 0.72
        # If enabled, CPU steal will be detected by reading /proc/stat (supported only on linux) and will be added to
        # the CPU usage metric before stress is calculated.
        detect-cpu-steal = true
      }

      # Which of the available measurements to use, either "packet-rate" or "cpu-usage". This determines how the stress
      # metric is calculated, which is just the measured load divided by the configured load-threshold.
      # The packet-rate metric load-threshold needs to be configured based on the machine that the bridge is running on,
      # while the cpu-usage metric should behave well with the default configuration on any machine.
      load-measurement = "cpu-usage"
    }
    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

    // Statistics about the transit time of RTP/RTCP packets. Note that the collection code for the JSON and Prometheus
    // outputs is different, and each has a slight performance impact, so the format(s) that are not needed should be
    // kept disabled.
    transit-time {
      // Enable collection of transit time stats in JSON format. Available through /debug/jvb/stats/transit-time
      enable-json = true
      // Enable collection of transit time stats in Prometheus. Available through /metrics.
      enable-prometheus = false
      // Enable collection of internal jitter (difference in processing time). Available through
      // /debug/jvb/stats/transit-time
      enable-jitter = false
    }
    jvm {
      // Whether to enable collection of JVM metrics (thread count, garbage collection)
      enabled = true
    }
  }
  websockets {
    enabled = false
    server-id = "default-id"
    // Whether to negotiate WebSocket compression (permessage-deflate)
    enable-compression = true
    // Whether to send keepalive pings on idle websockets
    send-keepalive-pings = true
    // The keepalive ping interval
    keepalive-ping-interval = 15 seconds
    // The websocket idle timeout
    idle-timeout = 60 seconds

    // Optional, even when 'enabled' is set to true
    #tls = true
    // The domains used when advertising a colibri-ws URL. Must be set when enabled = true
    domains = []
    // The domain used when advertising a colibri-relay-ws URL. If empty defaults to the value of `domains`.
    relay-domains = []
  }
  ice {
    udp {
        # The port for ICE/UDP.
        port = 10000
    }

    # An optional prefix to include in STUN username fragments generated by the bridge.
    #ufrag-prefix = "jvb-123:"

    # Which candidate pairs to keep alive. The accepted values are defined in ice4j's KeepAliveStrategy:
    # "selected_only", or "all_succeeded".
    keep-alive-strategy = "selected_only"

    # 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 = "NominateFirstHostOrReflexiveValid"

    # Whether to advertise private ICE candidates, i.e. RFC 1918 IPv4 addresses and fec0::/10 and fc00::/7 IPv6
    # addresses even for endpoints that have not signaled support for private addresses.
    # Note: Jicofo signals support for private addresses for jigasi and jibri.
    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
    }
  }

  speech-activity {
    # The number of speakers to include in the list of recent speakers sent with dominant speaker change
    # notifications.
    recent-speakers-count = 10

    # Whether to enable silence detection. When silence detection is enabled and there is no speech activity for a
    # certain time (see silence-detection-timeout below) we fire a "dominant speaker changed" event notifying endpoints
    # that we entered a period of silence.
    enable-silence-detection = false

    # How long to wait for lack of speech activity before a period of silence begins.
    silence-detection-timeout = 3 seconds
  }

  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

  # Whether to redact remote endpoint IP addresses from logs
  redact-remote-addresses = true


  connection-stats {
    # Whether to periodically send connection stats (currently, estimated downlink bandwidth) to endpoints
    enabled = true
    # How often to send these stats
    interval = 10 seconds
  }

  ssrc-limit {
    # maximum number of SSRCs to send to an endpoint for video
    video = 50

    # maximum number of SSRCs to send to an endpoint for audio
    audio = 50
  }
}
