How can I change the default Codec used in WebRTC? - webrtc
I've been googling a way to change codec in Chrome's implementation of WebRTC, but there doesn't seem to be a way.
How can I change the default codec used(audio or video) in a WebRTCpeer connection in Chrome?
Yes, you can change the codec to be anything you want...as long as Chrome supports it. Right now, audio wise, the only supported codecs are PCMA, PCMU, ISAC, and OPUS(the default). For Video you have VP8(also H264 on some systems with FireFox).
To use any of these codecs as default, you must modify your SDP before setting it locally in your peerconnection and sending your offer/answer. I have tested successfully forcing Chrome to send PCMA instead of OPUS by default.
As an example:
Say you have your default audio SDP section that looks like the following(notes are in brackets are are not part of the sdp)
m=audio<media> 49353<port> RTP/SAVPF<proto> 111 103 104 0 8 106 105 13 126 <rtpformats>
c=IN<nettype> IP4<addrtype> 192.168.0.13<address>
a=rtcp:49353<port> IN<nettype> IP4<addresstype> privateIP<connection address>
a=candidate:1204296370 1 udp 2122260223 privateIP 49353 typ host generation 0 <audioIceCandidate>
a=candidate:1204296370 2 udp 2122260223 privateIP 49353 typ host generation 0
a=candidate:155969090 1 tcp 1518280447 privateIP 0 typ host generation 0
a=candidate:155969090 2 tcp 1518280447 privateIP 0 typ host generation 0
a=ice-ufrag:E7VFzFythTIOaQ6X <ice username>
a=ice-pwd:ZMHFqqXEA8JLjItZcRN4FZDJ <ice-password>
a=ice-options:google-ice <iceoptions>
a=fingerprint:sha-256<encryptType> 66:2D:43:3A:31:7B:46:56:50:D7:CC:75:80:79:5D:88:7D:5D:1B:0E:C7:E6:F9:C4:68:6D:51:7F:4B:32:97:A1<print>
a=setup:actpass <dtls setup mode>
a=mid:audio
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level <extention map>
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=sendrecv <mediamode>
a=rtcp-mux <says rtcp mux>
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:126 telephone-event/8000
a=maxptime:60
If you wanted to ONLY use PCMA, you would change the m=audio line to the following:
m=audio 49353 RTP/SAVPF 8 this way only the PCMA payload is considered. Then you need to remove all the rtpmap lines that do not correspond with that payload, i.e. any a=rtpmap: where the next character is NOT an 8. If you set that modified sdp locally and send it to your peer(and if they SUPPORT PCMA...does not have to be default for them as the negotiation will force PCMA if you only offer it), then PCMA will be your audio codec and not OPUS.
Couple of asides:
The SDP I am talking about is the one generated and passed through the success callback of the createOffer and createAnswer functions of the peerconnection
This type of idea will work for ADDING codecs that you know are supported by the underlaying systems(H264, SPEEX, etc.). Just make sure to add the payload and the appropriate mappings and options(fmtp is needed for h264 as profiles are important and possibly sprop-parameter-sets).
This will work with any appropriately coded WebRTC system, i.e. Firefox, Opera, etc. Not just chrome.
As browsers start to support setCodecPreferences, you can check for the mimetype of the codec you want to use by default to set the codec preference. For example if you want to prefer opus for audio you can check for the "audio/opus" mimetype and set your codec preferences to opus codecs:
let tcvr = pc.getTransceivers()[0];
let codecs = RTCRtpReceiver.getCapabilities('audio').codecs;
let opus_codecs = [];
// iterate over supported codecs and pull out the codecs we want
for(let i = 0; i < codecs.length; i++)
{
if(codecs[i].mimeType == "audio/opus")
{
opus_codecs .push(codecs[i]);
}
}
// currently not all browsers support setCodecPreferences
if(tcvr.setCodecPreferences != undefined)
{
tcvr.setCodecPreferences(opus_codecs);
}
Or for video you can fix the codec to vp9:
// note the following should be called before before calling either RTCPeerConnection.createOffer() or createAnswer()
let tcvr = pc.getTransceivers()[0];
let codecs = RTCRtpReceiver.getCapabilities('video').codecs;
let vp9_codecs = [];
// iterate over supported codecs and pull out the codecs we want
for(let i = 0; i < codecs.length; i++)
{
if(codecs[i].mimeType == "video/VP9")
{
vp9_codecs.push(codecs[i]);
}
}
// currently not all browsers support setCodecPreferences
if(tcvr.setCodecPreferences != undefined)
{
tcvr.setCodecPreferences(vp9_codecs);
}
Code adapted from this Pericror blog post to force audio/video codecs.
Related
Why setRemoteDescription on RTCPeerConnection instance is failing with message Session Description is NULL?
I am using react-native-webrtc to implement livestreaming React native version: 0.66.4, react native webrtc version:^1.94.2 I have 2 separate screens for the person who creates the livestream and people who join on the stream and on both sides I am creating an instance of RTCPeerConnection (outside the body of the screen component) as follows: const configuration = {iceServers: [{url: 'stun:stun.l.google.com:19302'}]}; const pc = new RTCPeerConnection(configuration); I have this other function for creating offer: const createOffer = async () => { const offer = await pc.createOffer(); offerRef.current = offer; // await pc.setLocalDescription(offer); } For the moment I commented out the pc.setLocalDescription because it's throwing an error:PeerConnection not found This is what the offer looks: {"sdp": "v=0 o=- 4201814093591570700 2 IN IP4 127.0.0.1 s=- t=0 0 a=extmap-allow-mixed a=msid-semantic: WMS", "type": "offer"} then through the signaling server I am sending this offer to the other peer who is trying to join the streaming and on his side I am trying to do : pc.setRemoteDescription(offer) but it is giving me error { "message": "SessionDescription is NULL.", "name": "SetRemoteDescriptionFailed", } Any idea why is this happening I checked the offer on both sides and they are identical and also I don't understand why I am getting that PeerConnection is NULL error could that be causing all this? Note: The pc instance on the person who creates the live stream and the person who is trying to join the stream is not the same they are both declared same way tho with the same configuration.
RTCPeerConnection is creating invalid SDP with createOffer function
Im using 1.87.3 react-native-webrtc and react-native 0.64.3 Android 11. Im using this function for createOffer but its produces an incomplete sdp. When i createOffer from web side client its success, rnative and web side can communicate. But when i try to createoffer from React native side its creating invalid sdp. Is there any idea? peer.createOffer().then(desc => { console.log(desc); peer.setLocalDescription(desc).then(() => { //do something }); }); This is created SDP by CreateOffer function = "v=0 ↵o=- 7968195522823789820 2 IN IP4 127.0.0.1 ↵s=- ↵t=0 0 ↵a=msid-semantic: WMS ↵"
Sorry i should have to call addStream function before creating an offer.
Safari does not send ice candidates
don't work example in safari https://github.com/Kurento/kurento-tutorial-node/tree/master/kurento-one2many-call In chrome, everything is fine. Safary does not send ice candidates in view mode. Presenter mode is ok ==================== update In the Front (index.js) The event onOfferViewer is always executed onIceCandidate – never executed Connection from Front to the node var ws = new WebSocket('wss://' + location.host + '/one2many'); On KMS a Turn doesn’t turn on, but a Stun is configured. I can broadcasting from Safari, but I cannot watching on it Look at kurento utils deeper 2 Sturm servers are chosen, before WebRtcPeer initialization iceServers: Array (2) 0 {username: undefined, credential: undefined, url: "stun:stun.l.google.com:19302", urls: ["stun:stun.l.google.com:19302"]} 1 {username: undefined, credential: undefined, url: "stun:stun.voipbuster.com", urls: ["stun:stun.voipbuster.com"]} After RTCPeerConnection is created After Process answer is executed I think the next step has to be in a function addEventListener pc.addEventListener('icecandidate', function (event) {…} In Chrome in the function addEventListener a callback is executed but for Safari never. I can assume that the candidates come before the subscription is taking place, but there is no evidence, and I don’t understand why the presenter works fine. detail I started broadcasting in the presenter mode in the Safari The Safari version - 13604.3.5 (MacOs - 11.0.1) The Safari options Old api - Enabled Ice restrictions - Disabled The Bower’s dependencies "dependencies": { "adapter.js": "v0.2.9", "bootstrap": "~3.3.0", "ekko-lightbox": "~3.3.0", "demo-console": "1.5.1", "kurento-utils": "master" } The package.json structure { "name": "kurento-one2many-call", "version": "6.7.3-dev", "private": true, "scripts": { "postinstall": "cd static && bower install" }, "dependencies": { "express": "~4.12.4", "minimist": "^1.1.1", "ws": "~1.0.1", "kurento-client": "Kurento/kurento-client-js" }, "devDependencies": { "bower": "^1.4.1" } } Output of Safari logs Output of Safari logs [Log] Browser does not appear to be WebRTC-capable (adapter.js, line 34) [Debug] constraints: {"offerToReceiveAudio":true,"offerToReceiveVideo":true} (kurento-utils.js, line 268) [Debug] Created SDP offer (kurento-utils.js, line 270) [Debug] Local description set – "v=0 ↵o=- 5811275597248577793 2 IN IP4 127.0.0.1 ↵s=- ↵t=0 0 ↵a=msid-semantic: WMS ↵" (kurento-utils.js, line 275) "v=0 o=- 5811275597248577793 2 IN IP4 127.0.0.1 s=- t=0 0 a=msid-semantic: WMS " [Log] Senging message: {"id":"viewer","sdpOffer":"v=0\r\no=- 5811275597248577793 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=msid-semantic: WMS\r\n"} (index.js, line 70) [Info] Received message: {"id":"viewerResponse","response":"accepted","sdpAnswer":"v=0\r\no=- 3748169328 3748169328 IN IP4 0.0.0.0\r\ns=Kurento Media Server\r\nc=IN IP4 0.0.0.0\r\nt=0 0\r\na=msid-semantic: WMS\r\n"} (index.js, line 70) [Debug] SDP answer received, setting remote description (kurento-utils.js, line 320) [Debug] Remote stream: – undefined (kurento-utils.js, line 294) How to a node connects to KMS var argv = minimist(process.argv.slice(2), { default: { as_uri: 'https://localhost:8443/', ws_uri: 'ws://37.228.89.170:8888/kurento' } });
Two options: Safari 12 only - Need to enable the experimental feature "Enable MDNS Ice Candidates" in Safari settings, advanced, experimental features Safari 11 - you have to call getUserMedia({video: true, audio: true}), and have the user accept the dialog box to allow video and audio on your page. Even though you don't want to use the video or audio, this then causes safari to send ice-candidates during the negotiation
This question is vague and does not provide a lot of detail. Please provide more details on the issue you are experiencing and what you have done to try to fix it/debug it. You might try to disable the ICE candidate restrictions option in the developer menu and restart Safari, as mentioned in this Google Group post. Without knowing more information, I can't help much more than this. For the future, please provide more thorough and detailed information on the problem and solutions you have attempted.
webrtc - In firefox beta version giving InvalidSessionDescriptionError: Local descriptions must have a=mid attributes error
WEBRTC - while setting answer into setLocalDescription getting below error in firefox beta version .63 this.soc.setLocalDescription(answer, function(){}, function(error){ co.handleAnswerLoacalDescError(error); } ); SWRTCAnswerPConn.prototype.handleAnswerLoacalDescError = function (error) { console.log("error SWRTCAnswerPConn.prototype.handleAnswerLoacalDescError "+error); } Below one is the local sdp "v=0\r\no=mozilla...THIS_IS_SDPARTA-63.0 6779639364423913043 0 IN IP4 0.0.0.0\r\ns=-\r\nt=0 0\r\n a=ice-options:trickle\r\n a=msid-semantic:WMS *\r\nm=audio 9 RTP/SAVPF 0\r\nc=IN IP4 0.0.0.0\r\n a=sendrecv\r\n a=ice-pwd:0c25b6011567fa002a87fw6d36d0c32e\r\n a=ice-ufrag:9cba9881\r\n a=msid:{342671bf-c92f-4d7e-add6-37228fcaffc4} {6876af26-691b-4beb-9fed-a18e27ea0fe0}\r\n a=rtcp-mux\r\n a=rtpmap:0 PCMU/8000\r\n a=setup:active\r\n a=ssrc:127692948 cname:{f7d3d74d-86e0-4a27-a143-79f4703d32cf}\r\n" * InvalidSessionDescriptionError: Local descriptions must have a=mid attributes * Please, anyone, help to resolve this issue.
How to use kurento-media-server for audio only stream?
I want to have only audio stream communication between peers , I changed the parts of kurento.utils.js to get only audio stream via getusermedia but it's not working I used this example node-hello-world example WebRtcPeer.prototype.userMediaConstraints = { audio : true, video : { mandatory : { maxWidth : 640, maxFrameRate : 15, minFrameRate : 15 } } }; to WebRtcPeer.prototype.userMediaConstraints = { audio : true, video : false }; is it possible use kurento service for only audio stream?
This is indeed possible with Kurento. There are two ways of doing this, depending on the desired scope of the modification: Per webrtc endpoint: when you process the SDP offer sent by the client, you get an SDP answer from KMS that you have to send back. After invoking the processOffer method call, you can tamper the SDP to remove all video parts. That way, your client will send back only audio. Globally: You can edit /etc/kurento/sdp_pattern.txt file removing all video related parts, this will force SdpEndpoints (parent class of WebrtcEndpoint) to only use audio. EDIT 1 The file sdp_pattern.txt is deprecated in KMS 6.1.0, so method 2 shouldn't be used. EDIT 2 There was an issue with the kurento-utils library, and the client was not correctly setting the OfferToReceiveAudio. It was fixed some time ago, and you shouldn't need tampering the SDPs now.
git origin: https://github.com/Kurento/kurento-tutorial-js.git git branch: 6.6.0 My solution is only changing var offerVideo = true; to var offerVideo = false; in generateOffer function of kurento-utils.js file.
My approach is to modify the options that you pass to the WebRtcPeer. var options = { onicecandidate: onIceCandidate, iceServers: iceServers, mediaConstraints: { audio:true, video:false } } Besides, in the kurento-utils.js, the mediaContraints is overidden by this line: constraints.unshift(MEDIA_CONSTRAINTS); So comment it.