Why do two person Jitsi calls fail or have one-way audio?

Short answer

Two person calls can attempt P2P, which needs a usable ICE path between browsers; same-LAN success does not prove internet connectivity. Docker issue #2324 reports fixing missing candidates with STUN_HOST, STUN_PORT and GLOBAL_MODULES=external_services, while restricted networks may need TURN. A separate bridge bug sent media to a non-nominated pair and is fixed in stable-11248. Test with P2P disabled to separate these failures. [S1][S4][S5][S9][S12]

Symptoms

In Docker #2324, two browsers work on one LAN but fail across networks. Firefox about:webrtc shows host candidates without srflx candidates. Adding P2P_STUN_SERVERS did not help that reporter. The issue remains open on 2026-10-06. [S1]

Bridge #2427 looks different: other people hear the affected participant, but that participant hears nobody. ICE completes, yet JVB sends media to another pair. Reported log markers include Selected pair for stream stream.RTP: and Nomination confirmed for pair:. These markers alone do not prove media used that pair. [S5]

Cause

Jitsi can attempt browser-to-browser P2P when two eligible participants remain. It switches back to JVB when a third joins. Failed P2P ICE stops the P2P session; an established bridge session supplies the fallback. A broken bridge can therefore also break two person meetings. [S4]

host describes an interface candidate, srflx a STUN-discovered mapped address, and relay a TURN allocation. Host-only gathering can mean missing discovery or unreachable services. It does not identify the cause by itself. STUN provides addresses, while TURN relays traffic when a direct path cannot work. [S12][S15]

In stable-11248, STUN_HOST creates a Prosody service entry, but STUN alone does not automatically enable external_services. The workaround enables that discovery module explicitly. P2P_STUN_SERVERS still populates browser configuration; successful XMPP service discovery can replace that initial list. Why it failed in #2324 needs reproduction. [S1][S2][S3]

In #2427, ice4j cached a sending pair before nomination and kept using it afterward. PR #311 removes that cache; JVB PR #2441 adopts the fix. Separately, #2414’s reporter blamed a STUN harvester returning a private bridge address alongside static mapping, and reported success after disabling that harvester. This was a deployment report, not a maintainer-confirmed general incompatibility. [S5][S6][S7][S8]

Fix

  1. Docker stable-11146-2 and stable-11248: isolate P2P. In the existing .env, set the supported key below, then recreate web and reload both meeting tabs. Keep your usual Compose file arguments for a custom stack. If audio now works, investigate P2P discovery and connectivity; otherwise, check the bridge path and other audio causes. [S2][S4][S10][S11]

    dotenv
    ENABLE_P2P=0
    Terminal
    docker compose up -d --force-recreate web
  2. Docker: apply the reported STUN workaround. For those releases, edit the existing .env assignments and recreate both services. meet.example.com below must actually run a reachable UDP STUN service on port 443. The exact successful #2324 host was meet-jit-si-turnrelay.jitsi.net. Port 443 here means UDP STUN, not HTTPS. [S1][S2][S11]

    dotenv
    ENABLE_P2P=1
    STUN_HOST=meet.example.com
    STUN_PORT=443
    GLOBAL_MODULES=external_services
    Terminal
    docker compose up -d --force-recreate web prosody

    If GLOBAL_MODULES already contains modules, append external_services to its comma-separated value. P2P_STUN_SERVERS accepts comma-separated host:port entries and adds stun: itself; it cannot supply TURN credentials. Do not use the unsupported P2P_ENABLED spelling from the report. [S1][S2][S3]

  3. Docker with the bridge failure: upgrade the complete release. Use the stable-11248 Compose bundle with matching image tags, preserving configuration and secrets. It is the latest release checked on 2026-10-06 and contains the #2427 fix. Then run: [S7][S9][S10][S11]

    Terminal
    docker compose config --images
    docker compose pull
    docker compose up -d

    Every Jitsi image should resolve to :stable-11248. Updating only web does not update the faulty bridge. [S2][S7][S10]

  4. Debian/Ubuntu packages: make the equivalent diagnosis. For Jitsi Meet 2.0.11248-1, edit the existing p2p object in /etc/jitsi/meet/meet.example.com-config.js, then reload both tabs: [S13]

    JavaScript
    p2p: {
        enabled: false
    },

    This is an excerpt, not a replacement file. Preserve other entries. Docker .env variables do not configure packages. The package Prosody template already includes external_services; inspect /etc/prosody/conf.avail/meet.example.com.cfg.lua and its advertised STUN/TURN services, preserving generated credentials. [S13]

    For the confirmed old JVB package in #2427, upgrade from the configured official Jitsi stable repository: [S5][S16]

    Terminal
    sudo apt-get update
    sudo apt-get install --only-upgrade jitsi-meet jitsi-videobridge2
    dpkg-query -W -f='${Package} ${Version}\n' jitsi-videobridge2

    The verified fixed baseline prints jitsi-videobridge2 2.3-318-gbf271b11f-1. [S7][S16]

  5. Both install types: add TURN when direct ICE fails. Follow the TURN setup guide. Docker advertises an external server through settings including TURN_HOST or TURNS_HOST and TURN_CREDENTIALS; enabling these does not create a TURN server. Test an actual allocation and selected relay path, especially on networks blocking UDP. [S2][S12]

Verify

For both install types, open chrome://webrtc-internals/ before joining, or Firefox about:webrtc. Inspect the active media connection: Jitsi can have both P2P and JVB connections. Follow the RTP stream’s transportId, then the transport’s selectedCandidatePairId, then the pair’s localCandidateId and remoteCandidateId. [S4][S14][S15]

The selected pair should have state: "succeeded". Speak in both directions and compare successive outbound-rtp.bytesSent and inbound-rtp.bytesReceived samples for streams with kind: "audio". Increasing inbound media counters at both ends plus audible speech proves bidirectional audio. A gathered relay candidate alone only proves TURN allocation, not that the call uses TURN. [S15]

For stable-11248, the meeting page console check window.config.p2p.enabled should return false after step 1 or package step 4, and true after step 2. This proves the loaded setting, not successful media. [S2][S13]

If it still fails

On Docker, inspect current service logs: [S11]

Terminal
docker compose logs --tail=100 web prosody jvb

On packages, read /var/log/jitsi/jvb.log, /var/log/jitsi/jicofo.log and /var/log/prosody/prosody.log. Correlate ICE pair selection with the failing browser’s selected pair. For a persistent bridge failure, follow video fails with three participants to check advertised addresses and UDP reachability. [S5][S17][S18]

Use the Trickle ICE test with your TURN URI and valid temporary credentials. A relay candidate verifies allocation; also test a real meeting through that relay. [S12][S15]

FAQ

Does adding STUN guarantee working calls?

No. A discovered mapped address may still be unusable across the two NATs or firewalls. TURN supplies a relay when direct connectivity fails. [S12]

Can I leave P2P disabled?

Yes. ENABLE_P2P=0, or package p2p.enabled: false, keeps media on the bridge. The bridge must be reachable and healthy. [S2][S4][S13]

Is every one-way audio report fixed in stable-11248?

No. It contains the nominated-pair fix from #2427. #2414 describes a separate deployment workaround, without an identified affected version or upstream code fix. [S5][S7][S8]

Sources

All checked 2026-10-06. Dates below identify the source version or publication.

[S1] Docker #2324, 2026-09-11 to 12, community report and maintainer comments.

[S2] stable-11248 web template, Prosody template, Compose, 2026-09-14, source code.

[S3] Jingle service discovery and initial ICE servers, SDK pinned by stable-11248, source code.

[S4] JitsiConference P2P transitions, stable-11248 SDK, source code.

[S5] JVB #2427, closed 2026-09-02, community report and maintainer comments.

[S6] ice4j PR #311, merged 2026-09-02, source code.

[S7] JVB PR #2441, 2026-09-03; 11248 dependencies, 2026-09-14, source code.

[S8] JVB #2414, closed 2026-05-28, community report.

[S9] stable-11248 and latest release, 2026-09-14, release note.

[S10] Docker handbook, checked 2026-10-06, official doc.

[S11] Docker Compose up, config, logs, checked 2026-10-06, official docs.

[S12] Jitsi TURN setup, checked 2026-10-06, official doc.

[S13] 11248 browser config, web package installer, Prosody template, 2026-09-14, source code.

[S14] Chrome stats, 2023-06-30; Firefox WebRTC debugging, checked 2026-10-06, official docs.

[S15] W3C WebRTC statistics and candidate types, checked 2026-10-06, official docs.

[S16] Jitsi stable package index, apt-get, dpkg-query, checked 2026-10-06, official repository and docs.

[S17] Debian/Ubuntu quickstart, checked 2026-10-06, official doc.

[S18] Video fails with three participants, checked 2026-10-06, independent community guide.

Open questions

The exact reason P2P_STUN_SERVERS failed in #2324 and #2414’s affected version remain unconfirmed. These steps need testing on real browsers across restrictive networks; this guide does not claim a live call test. [S1][S8]

Collect debug info

These commands gather what an engineer needs to diagnose a Jitsi server. Copy them, run them, and keep the output.

Terminal
# Run on the server, from your docker-jitsi-meet folder

# 1. Every service should be "running" (or "healthy")
docker compose ps

# 2. Which images and release tags are running
docker compose images

# 3. Recent logs from the core services
docker compose logs --tail=200 web prosody jicofo jvb

# 4. The settings most fixes depend on
grep -E '^(PUBLIC_URL|JVB_ADVERTISE_IPS|ENABLE_LETSENCRYPT|ENABLE_AUTH|AUTH_TYPE)=' .env

# 5. Is anything listening for media on UDP 10000?
sudo ss -ulnp | grep 10000

Installed with the Debian packages instead of Docker? Read the service logs with:

Terminal
sudo journalctl -u prosody -u jicofo -u jitsi-videobridge2 --since "1 hour ago"

Remove passwords, secrets and tokens before you share any output.

Send the output to an engineer

Stuck, or would rather not do this by hand?

Deploy it in one click

A private Jitsi server in your own AWS account with SSL, your domain and optional recording, transcription and JWT. Free 15 minute trial.

Start free trial

Talk to a Jitsi engineer

Setup, fixes, branding, recording, scaling. Tell us what is happening and we reply with a plan and a quote.

Get expert help

Related

Recently updated