[Spreed video calls] Black screen / How to set STUN/TURN

Hey there,

as I so far did not manage to successfully establish video connection with the spreed app, both users just see their own camera and black screen of the other one, I guess I made something wrong in how to set STUN/TURN url.

Browser console shows the following error:

Uncaught DOMException: Failed to construct 'RTCPeerConnection': Failed to initialize native PeerConnection.
    at window.RTCPeerConnection (https://my.domain/nextcloud/apps/spreed/js/simplewebrtc.js?v=9c7a58b380c30c8827deb39147df7249:11372:14)
    at new TraceablePeerConnection (https://my.domain/nextcloud/apps/spreed/js/simplewebrtc.js?v=9c7a58b380c30c8827deb39147df7249:10138:25)
    at new PeerConnection (https://my.domain/nextcloud/apps/spreed/js/simplewebrtc.js?v=9c7a58b380c30c8827deb39147df7249:6121:13)
    at new Peer (https://my.domain/nextcloud/apps/spreed/js/simplewebrtc.js?v=9c7a58b380c30c8827deb39147df7249:13560:13)
    at WebRTC.createPeer (https://my.domain/nextcloud/apps/spreed/js/simplewebrtc.js?v=9c7a58b380c30c8827deb39147df7249:14427:10)
    at https://my.domain/nextcloud/apps/spreed/js/webrtc.js?v=9c7a58b380c30c8827deb39147df7249:65:25
    at EventSource.<anonymous> (https://my.domain/nextcloud/core/js/eventsource.js?v=9c7a58b380c30c8827deb39147df7249:144:8)

Spreed.ME with TURN server works, so generally Spreed video calls should also. I am wondering in how to exactly give the correct STUN/TURN url:

  • STUN server shows “stunserver:port” as example and does not allow “stun:domain.url:port”, as it is given in the Spreed.ME server config. I can just give “domain.url:port” without “https” or any other protocol.
  • TURN server shows “https://turn.example.org” as example, but allows any input, even “test”. As my TURN server listens to a specific port, I guess I need to give that also. Also I wonder if “https://” is really needed, and why not “turn:”, as it is used in the Spreed.ME server config.
  • As the coturn is on the same server than nextcloud, would it be possible to just give “localhost:port”, or does not local nextcloud but the “remote” user initiate the connection and therefore need external url?
  • So after all the examples and blocks of the input fields are everything else than consistent and whatever I tried (all combinations I was able to think of), both user just see black screens of each other but their own camera picture.

Anyone able to help me with this? :slight_smile:

Not sure I’ll be of much help but here’s some suggestions from my own working setup.

In my Nextcloud admin page for both stun and turn server fields I put:
cloud.mydomain.com:8443
cloud.mydomain.com:8443
and in the turnserver.conf I have listening port 8443.

You need to make sure:

  • you have correct firewall settings.
  • you have proper browser such as Chrome or Firefox which you have fixed some settings for in about:config.
  • that services are properly running “lsof -i :8080” and “lsof -i :8443”
  • That shared secret values are correctly set.

Best of luck.

Thanks for your reply!

As I said, Spreed.ME works very well inside local network and outside via TURN server. So the related browsers, port forwarding/listening, firewall, shared secrets, TURN settings etc. are working.

I tried now to apply TURN field as you suggested. After trying several times im both directions to call each other (I tried with two nextcloud users on two browser sessions), it did work ~1 of 5 times to have proper video/audio connection via TURN server, which could be seen in my turn.log. However so far it does only work, if I give only TURN server address. With also given STUN address (just the same) it did not work so far, even that STUN is enabled in turnserver.conf etc. But this might be just by chance, because also without STUN address I work just 1/5 times, as I said. I also tried it by phone via mobile internet (which works well with Spreed.ME again), but that did absolutely not work a single time. Watching the turn.log it just get stuck somewhere, sometimes after the (normal) unauthorized connection attempts, sometimes the mobile peer just get deleted for no reason, even that the mobile connection is pretty stable and fast enough for pretty stable Spreed.ME, Skype, WhatsApp video call etc.

Also what I watched is that the spreed app is absolutely slow in recognizing call attempts and showing the video/audio (if it works). I am wondering, if maybe the solution with internal webrtc/spreed server inside nextcloud API or what is just way slower in performance than with dedicated spreed server and therefore does in most cases not work with slow hardware like my Raspberry Pi 2?

Also for me it is little confusing what I have to do/wait for, after call attempt. When A does a call invitation to B via “choose person” drop down menu, person B first sees (after quite some seconds) the user transparent in the users list of the app. Just clicking the user there often results in a failure where both users see “waiting for to take the call” and nothing happens. After again some seconds user B sees the call invitation notification in top bar. Using this to take the call does generally work (just sometimes in my case). What I am missing is a clear not misunderstandable big button in the middle of the screen (while app is opnened of course) that clearly should be pressed to take the call.

Yeah, so far the app is sadly absolutely unusable for me, while I stay with Spreed.ME and dedicated server.

At least I know now, that “cloud.mydomain.com:8443” is principally the right way to give STUN/TURN server address in admin settings ;).

Ah the app seems more verbose now in browser console. I just opened some parts of the log, if someone could help by getting more parts of the log, I could provide that.

video added 
Peer {id: "rw2pKVmBSw8XQpXeKSy0c1mKjG6Jsj3fV2AVvVioEL9Kg7QBD7…ZVsi8MxtlLFd8w5SJoCjwuGpT/Rb2RJ4Bk9WL9ieTNT3GdIBJ", parent: WebRTC, type: "type", oneway: false, sharemyscreen: false…}
browserPrefix
:
"webkit"
callbacks
:
Object
channels
:
Object
enableDataChannels
:
true
id
:
"rw2pKVmBSw8XQpXeKSy0c1mKjG6Jsj3fV2AVvVioEL9Kg7QBD76Ly3DgzG/13lvtF98cm9wVmbshgBD+7dZJOStpEQI7B3S9iyjPTG8RxfLw91T30MvcGEsMQy30Y9p3+G8WoqtLT4Y1qvn6a3V/vrN2Q+6yLpBvoPUjWCwJVZhLaBw/jHNKxVPLmFSgYfw4GAjZL9deGUTA8XZVsi8MxtlLFd8w5SJoCjwuGpT/Rb2RJ4Bk9WL9ieTNT3GdIBJ"
logger
:
Object
nick
:
"Micha"
oneway
:
false
parent
:
WebRTC
pc
:
PeerConnection
addStream
:
function ()
assumeSetLocalSuccess
:
false
batchIceCandidates
:
0
batchedIceCandidates
:
Array(0)
callbacks
:
Object
config
:
Object
enableChromeNativeSimulcast
:
false
enableMultiStreamHacks
:
false
getLocalStreams
:
function ()
getRemoteStreams
:
function ()
hadLocalIPv6Candidate
:
false
hadLocalRelayCandidate
:
false
hadLocalStunCandidate
:
false
hadRemoteIPv6Candidate
:
true
hadRemoteRelayCandidate
:
true
hadRemoteStunCandidate
:
false
iceCredentials
:
Object
localDescription
:
Object
pc
:
TraceablePeerConnection
remoteDescription
:
Object
removeStream
:
function ()
restrictBandwidth
:
0
_candidateBuffer
:
Array(0)
_localDataChannels
:
Array(4)
_remoteDataChannels
:
Array(0)
iceConnectionState
:
(...)
signalingState
:
(...)
__proto__
:
WildEmitter
receiveMedia
:
Object
sharemyscreen
:
false
sid
:
"1490021422907"
stream
:
MediaStream
type
:
"type"
videoEl
:
video#rw2pKVmBSw8XQpXeKSy0c1mKjG6Jsj3fV2AVvVioEL9Kg7QBD76Ly3DgzG/13lvtF98cm9wVmbshgBD+7dZJOStpEQI7B3S9iyjPTG8RxfLw91T30MvcGEsMQy30Y9p3+G8WoqtLT4Y1qvn6a3V/vrN2Q+6yLpBvoPUjWCwJVZhLaBw/jHNKxVPLmFSgYfw4GAjZL9deGUTA8XZVsi8MxtlLFd8w5SJoCjwuGpT/Rb2RJ4Bk9WL9ieTNT3GdIBJ_type_incoming
accessKey
:
""
assignedSlot
:
null
attributes
:
NamedNodeMap
autoplay
:
true
baseURI
:
"https://path/to/nextcloud/apps/spreed/?roomId=37"
buffered
:
TimeRanges
childElementCount
:
0
childNodes
:
NodeList(0)
children
:
HTMLCollection(0)
classList
:
DOMTokenList(0)
className
:
""
clientHeight
:
1045
clientLeft
:
0
clientTop
:
0
clientWidth
:
2090
contentEditable
:
"inherit"
controls
:
false
crossOrigin
:
null
currentSrc
:
""
currentTime
:
0
dataset
:
DOMStringMap
defaultMuted
:
false
defaultPlaybackRate
:
1
dir
:
""
disableRemotePlayback
:
false
draggable
:
false
duration
:
NaN
ended
:
false
error
:
null
firstChild
:
null
firstElementChild
:
null
height
:
0
hidden
:
false
id
:
"rw2pKVmBSw8XQpXeKSy0c1mKjG6Jsj3fV2AVvVioEL9Kg7QBD76Ly3DgzG/13lvtF98cm9wVmbshgBD+7dZJOStpEQI7B3S9iyjPTG8RxfLw91T30MvcGEsMQy30Y9p3+G8WoqtLT4Y1qvn6a3V/vrN2Q+6yLpBvoPUjWCwJVZhLaBw/jHNKxVPLmFSgYfw4GAjZL9deGUTA8XZVsi8MxtlLFd8w5SJoCjwuGpT/Rb2RJ4Bk9WL9ieTNT3GdIBJ_type_incoming"
innerHTML
:
""
innerText
:
""
isConnected
:
true
isContentEditable
:
false
lang
:
""
lastChild
:
null
lastElementChild
:
null
localName
:
"video"
loop
:
false
mediaKeys
:
null
muted
:
false
namespaceURI
:
"http://www.w3.org/1999/xhtml"
networkState
:
2
nextElementSibling
:
div.avatar-container.hidden
nextSibling
:
div.avatar-container.hidden
nodeName
:
"VIDEO"
nodeType
:
1
nodeValue
:
null
offsetHeight
:
1045
offsetLeft
:
376
offsetParent
:
div#container_rw2pKVmBSw8XQpXeKSy0c1mKjG6Jsj3fV2AVvVioEL9Kg7QBD76Ly3DgzG/13lvtF98cm9wVmbshgBD+7dZJOStpEQI7B3S9iyjPTG8RxfLw91T30MvcGEsMQy30Y9p3+G8WoqtLT4Y1qvn6a3V/vrN2Q+6yLpBvoPUjWCwJVZhLaBw/jHNKxVPLmFSgYfw4GAjZL9deGUTA8XZVsi8MxtlLFd8w5SJoCjwuGpT/Rb2RJ4Bk9WL9ieTNT3GdIBJ_type_incoming.videoContainer.speaking.promoted
offsetTop
:
523
offsetWidth
:
2090
onabort
:
null
onauxclick
:
null
onbeforecopy
:
null
onbeforecut
:
null
onbeforepaste
:
null
onblur
:
null
oncancel
:
null
oncanplay
:
null
oncanplaythrough
:
null
onchange
:
null
onclick
:
null
onclose
:
null
oncontextmenu
:
function ()
oncopy
:
null
oncuechange
:
null
oncut
:
null
ondblclick
:
null
ondrag
:
null
ondragend
:
null
ondragenter
:
null
ondragleave
:
null
ondragover
:
null
ondragstart
:
null
ondrop
:
null
ondurationchange
:
null
onemptied
:
null
onencrypted
:
null
onended
:
null
onerror
:
null
onfocus
:
null
ongotpointercapture
:
null
oninput
:
null
oninvalid
:
null
onkeydown
:
null
onkeypress
:
null
onkeyup
:
null
onload
:
null
onloadeddata
:
null
onloadedmetadata
:
null
onloadstart
:
null
onlostpointercapture
:
null
onmousedown
:
null
onmouseenter
:
null
onmouseleave
:
null
onmousemove
:
null
onmouseout
:
null
onmouseover
:
null
onmouseup
:
null
onmousewheel
:
null
onoperadetachedviewchange
:
null
onoperadetachedviewcontrol
:
null
onpaste
:
null
onpause
:
null
onplay
:
null
onplaying
:
null
onpointercancel
:
null
onpointerdown
:
null
onpointerenter
:
null
onpointerleave
:
null
onpointermove
:
null
onpointerout
:
null
onpointerover
:
null
onpointerup
:
null
onprogress
:
null
onratechange
:
null
onreset
:
null
onresize
:
null
onscroll
:
null
onsearch
:
null
onseeked
:
null
onseeking
:
null
onselect
:
null
onselectstart
:
null
onshow
:
null
onstalled
:
null
onsubmit
:
null
onsuspend
:
null
ontimeupdate
:
null
ontoggle
:
null
onvolumechange
:
null
onwaiting
:
null
onwaitingforkey
:
null
onwebkitfullscreenchange
:
null
onwebkitfullscreenerror
:
null
onwheel
:
null
outerHTML
:
"<video autoplay="" id="rw2pKVmBSw8XQpXeKSy0c1mKjG6Jsj3fV2AVvVioEL9Kg7QBD76Ly3DgzG/13lvtF98cm9wVmbshgBD+7dZJOStpEQI7B3S9iyjPTG8RxfLw91T30MvcGEsMQy30Y9p3+G8WoqtLT4Y1qvn6a3V/vrN2Q+6yLpBvoPUjWCwJVZhLaBw/jHNKxVPLmFSgYfw4GAjZL9deGUTA8XZVsi8MxtlLFd8w5SJoCjwuGpT/Rb2RJ4Bk9WL9ieTNT3GdIBJ_type_incoming"></video>"
outerText
:
""
ownerDocument
:
document
parentElement
:
div#container_rw2pKVmBSw8XQpXeKSy0c1mKjG6Jsj3fV2AVvVioEL9Kg7QBD76Ly3DgzG/13lvtF98cm9wVmbshgBD+7dZJOStpEQI7B3S9iyjPTG8RxfLw91T30MvcGEsMQy30Y9p3+G8WoqtLT4Y1qvn6a3V/vrN2Q+6yLpBvoPUjWCwJVZhLaBw/jHNKxVPLmFSgYfw4GAjZL9deGUTA8XZVsi8MxtlLFd8w5SJoCjwuGpT/Rb2RJ4Bk9WL9ieTNT3GdIBJ_type_incoming.videoContainer.speaking.promoted
parentNode
:
div#container_rw2pKVmBSw8XQpXeKSy0c1mKjG6Jsj3fV2AVvVioEL9Kg7QBD76Ly3DgzG/13lvtF98cm9wVmbshgBD+7dZJOStpEQI7B3S9iyjPTG8RxfLw91T30MvcGEsMQy30Y9p3+G8WoqtLT4Y1qvn6a3V/vrN2Q+6yLpBvoPUjWCwJVZhLaBw/jHNKxVPLmFSgYfw4GAjZL9deGUTA8XZVsi8MxtlLFd8w5SJoCjwuGpT/Rb2RJ4Bk9WL9ieTNT3GdIBJ_type_incoming.videoContainer.speaking.promoted
paused
:
true
playbackRate
:
1
played
:
TimeRanges
poster
:
""
prefix
:
null
preload
:
"auto"
previousElementSibling
:
null
previousSibling
:
null
readyState
:
0
remote
:
RemotePlayback
scrollHeight
:
1045
scrollLeft
:
0
scrollTop
:
0
scrollWidth
:
2090
seekable
:
TimeRanges
seeking
:
false
shadowRoot
:
null
sinkId
:
""
slot
:
""
spellcheck
:
true
src
:
""
srcObject
:
MediaStream
style
:
CSSStyleDeclaration
tabIndex
:
-1
tagName
:
"VIDEO"
textContent
:
""
textTracks
:
TextTrackList
title
:
""
translate
:
true
videoHeight
:
0
videoWidth
:
0
volume
:
1
webkitAudioDecodedByteCount
:
0
webkitDecodedFrameCount
:
0
webkitDisplayingFullscreen
:
false
webkitDroppedFrameCount
:
0
webkitSupportsFullscreen
:
true
webkitVideoDecodedByteCount
:
0
webkitdropzone
:
""
width
:
0
__proto__
:
HTMLVideoElement
__proto__
:
WildEmitter

I have actually had some of the same issues too with the call notification not functioning properly and black screen on some occasion. I think the regular Video app might just not be as mature of software as SpreedME yet, or that hardware or link performance has a significant impact (which SpreedME software handles better than Video app). However, it works most of the time for me but Im using a little better hardware than raspbian.

It really sounds like too slow hardware or link problem to me. Some speculation: Udp protocol doesn’t have reliable delivery of data, so maybe SpreedME does something on the application level during the call setup phase that ensures a properly established connection wheras the Video app just goes udp all the way and you get the consequences of some failed to deliver packets.

Hah, at least for internal between two browser sessions/users it worked quite stable now, no matter if taking the call from user list or notification, but still a bit slow in building up connection. I just stopped spreed.me server service, which might lead to some problems, if both servers (dedicated and internal) listen to the same ports or something?

But that did not change anything about calls from phone via mobile internet. Still the same problems there.

Yeah, I just get a black screen for all calls. Haven’t had the time to troubleshoot why yet (not even sure where to start)…

This is usually calling from Firefox on Android to Desktop Linux Firefox.

I’m just getting started and have a special circumstance in my instance. I have a couple servers, one for my webpages, and a test server where I have installed NextCloud etc. This allows me to do things that may have otherwise disrupted service. Trying to keep my customers service level at 99.99% uptime.

Anyway… I have Testserver set up with ssl and it’s working great, I also installed the proxy server and it I swtich it over to the Internet, the RTC server starts and looks right. But it’s not running from inside Nextcloud, and I have created the config, and loaded it. So don’t quite understand why.

Next my question is if I am only interested in a tightly controlled group having access for video conferencing, do I need the proxy server to be on port 80?

What purpose does the STUN server serve ?

What purpose does the TURN server serve ?

If I have static IP and domain name access, do I need both of these ? I gathered that some people are using DDNS and figured that one of these servers may be just to get the addressing straight ? Is that right ?

I’m new to all this, smart, but uninformed. Reading everything I can get, but the architecture of the system isn’t explained.

HELP - dhenzler@sonic.net

You can use video call app.
It is working fine in my case.
only there are some issues with screen share when multiple OSs are involved.

The STUN server is for serving the correct local network IP and thus has nothing to do with dynamic or static IP, if I did not get something wrong.

Just try out, if this works already, otherwise TURN server is necessary and then no STUN anymore.

check this: Spreedme / webrtc and nextcloud on split host

I needed to forward the ports for coturn…

1 Like