{"_id":"@blueromans/sdp-translator","_rev":"1-3590edd8444f0e8289df0f18fce7c2f1","name":"@blueromans/sdp-translator","dist-tags":{"latest":"0.0.3"},"versions":{"0.0.2":{"name":"@blueromans/sdp-translator","description":"A simple SDP interoperability layer for Unified Plan/Plan B","author":{"name":"Yaşar Özyurt","email":"blueromans@hotmail.com"},"version":"0.0.2","stability":"stable","keywords":["sdp","webrtc","react-native-webrtc","interoperability","polyfill"],"main":"./lib/","scripts":{"lint":"jshint .","validate":"npm ls"},"dependencies":{"sdp-transform":"1.5.*"},"devDependencies":{"browserify":"^10.2.4","browserify-optional":"^1.0.0","coveralls":"^2.11.1","grunt":"^0.4.5","grunt-browserify":"~3.8.0","grunt-cli":"~0.1.13","grunt-contrib-clean":"~0.6.0","grunt-contrib-jshint":"^0.11.2","grunt-githooks":"^0.3.1","grunt-jscoverage":"^0.1.3","grunt-jsdoc":"^0.6.7","grunt-npm2bower-sync":"^0.9.1","grunt-shell":"^1.1.2","jscoverage":"^0.5.5","jshint":"2.8.0","minifyify":"~7.0.1","precommit-hook":"^3.0.0","qunit-cli":"^0.2.0"},"pre-commit":["lint"],"license":"Apache-2.0","gitHead":"a60b5c4fb33aee250a71d32def78b3a5f493d09d","_id":"@blueromans/sdp-translator@0.0.2","_nodeVersion":"16.17.0","_npmVersion":"8.19.1","dist":{"integrity":"sha512-9M03a5xPc9rWPzCsD9EnDmYXAldHOn6Cv8nAB30kmcxgKaCvWyUnfX3sjuq9A0dtCUdrDYtlbk6wbmIVLgxyMg==","shasum":"907f402cfffe51435564cab232ccaee9aaa4e508","tarball":"https://registry.npmjs.org/@blueromans/sdp-translator/-/sdp-translator-0.0.2.tgz","fileCount":14,"unpackedSize":55048,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFemwuZ86oNoUqWWFwQ3Nq2RivmDVziRSIS0OHB0wgHXAiEAzmOQ53C+js4llMDaHjQPT+AULJvvP71Q6oAcA1t2deA="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjSIW4ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpfYg/9EmKqWFtZAc/MTEnmbva2DgbLKC6eFim7QPBJ5LmhqdU443TU\r\nUhv80m6ziNexN549dJNxo6jvVjw7uehF6jPpJwFiNFRHHY4XUu4aMQ1Uqeoq\r\nryO1HLJd+y2ZPiz6neEJFu3EnIkgu4wgbrlvOvBQ2cIiMSvSbkxxUIVFQAke\r\nl3dU7cdtNTvWwARZFufiLEAC+zRlvrMNCwHEXzKADw/R2LgVoMRXyCWKnzDc\r\nwXiLTLNFQyobYRzPYWC4HEsZAhvvImeviU5oIipQYj9kViR5avwo+utVARUn\r\nuXswL5Nt0udvxhpNVlQOLqAD8C2vqi0hZso+4DOyKY9297/OxgxEhtc5khNz\r\n1euQNAHr3tDWoW+riOihwlC51PQQuGcEiR3x3sUb3IZeBUY6oBE+feldCBlp\r\nX9fV0exInE22BwyKTt7HR37V/1w266J9+5Wj0WUQgF4EdBNwVD7wKVsLmT/1\r\nA4Z1MJTHCxiqfaJHkuKAXgWnKTq6G2jt5oAiwQvF4tdcglk37KPl3zL1d5rW\r\nd0GrI3Zm310gLIckI0UeysJuIkWUzw8DjAAC4tvFWe7M6Swmhj31ahuwdYGg\r\npgz056IEP6dgDyeBsjPtcIqZiWkmdirilmaZ7htapZjfITIlvY/kYK7zlUjr\r\nJVm/pSlaY92w/MBRyzOsgHx1qWLWZwCWCxc=\r\n=W1Sr\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"blueromans","email":"blueromans@hotmail.com"},"directories":{},"maintainers":[{"name":"blueromans","email":"blueromans@hotmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/sdp-translator_0.0.2_1665697208527_0.04383360577991313"},"_hasShrinkwrap":false},"0.0.3":{"name":"@blueromans/sdp-translator","description":"A simple SDP interoperability layer for Unified Plan/Plan B","author":{"name":"Yaşar Özyurt","email":"blueromans@hotmail.com"},"version":"0.0.3","stability":"stable","keywords":["sdp","webrtc","react-native-webrtc","interoperability","polyfill"],"main":"./lib/","scripts":{"lint":"jshint .","validate":"npm ls"},"dependencies":{"sdp-transform":"1.5.*"},"devDependencies":{"browserify":"^10.2.4","browserify-optional":"^1.0.0","coveralls":"^2.11.1","grunt":"^0.4.5","grunt-browserify":"~3.8.0","grunt-cli":"~0.1.13","grunt-contrib-clean":"~0.6.0","grunt-contrib-jshint":"^0.11.2","grunt-githooks":"^0.3.1","grunt-jscoverage":"^0.1.3","grunt-jsdoc":"^0.6.7","grunt-npm2bower-sync":"^0.9.1","grunt-shell":"^1.1.2","jscoverage":"^0.5.5","jshint":"2.8.0","minifyify":"~7.0.1","precommit-hook":"^3.0.0","qunit-cli":"^0.2.0"},"pre-commit":["lint"],"license":"Apache-2.0","gitHead":"eee16a929dd33fe64140d02209f4f0f9327704a9","_id":"@blueromans/sdp-translator@0.0.3","_nodeVersion":"16.17.0","_npmVersion":"8.19.1","dist":{"integrity":"sha512-U4P2pgQZRSuMDVzX/uKNcPN1pJ4VvTsZRXtYFbi7FL9IIX3ngiy2qMkreSIGKtssHWgyJ7HWtLB4atkhRMya5Q==","shasum":"95766f498af07dbc228f4798ff306a74ffe93185","tarball":"https://registry.npmjs.org/@blueromans/sdp-translator/-/sdp-translator-0.0.3.tgz","fileCount":14,"unpackedSize":51886,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAfiuuWqcvVNmiL9CFqDdgyikOm4bhNu+ibJLbVnTSZDAiEA+teRCvKUYd+JX77lVHMYvtdURX4qnAgI8BAgXjbVjQw="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjSIaFACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqFshAAkMgm6J1gHLi1FNhsPJAW9mV5+Toi5Xwof8eBAwHFYXwwZKTt\r\nGhF2aAfQ+HorJb6pHIawtqrC61P/QflnItzd04TeURyeSGYbKBYzSnKcHVAU\r\nTjAV8v6SPix7ITPE5xTP+XyP0eVY+oQUDN6bSqC8QbrGtGI9KqxPQxuf5uyv\r\nLR87hQ6VC9aTHldYbSxt9Y1EKsULttA+oCOuhWRdr409430J0zWzTXUr0C8C\r\nc4F3gJAs7rwWquJ4JYXbFZJc5EFCo2z+eU+qYcNAVRIREGqJWMkMhIPTlbEo\r\nVHx7zIsGicz1hx3JjFMbg8zc0VZNetTgVuHA6ZsHHupxack2EL/N8IG2y9M+\r\nJ5aHIBpwQTox0SfcznXEWhDV5kjaftSx+MrdCY4n044wF7u78voDis3j3yvk\r\n0BfxodrAr2WSRaniO3cBCwTdLdSWrW09UPgw+Awz+0Jhzly0ZqeIpB8KMgt/\r\n813Ur09vgMry6RX2zEkSG4gosWIFBEBLDtVH1lIKZAvvgq1VaW05bE3OUYwz\r\nB4NXBiZw8pX9UB0BRgqWGkuLzXF+DpYTJYWgosTJohzNOIs/5vjNs0QEAwLY\r\nWvvQu9nY+PwdFECYBaNZmGTCqF7M5RGqa4jmfKWnYWyvRwB0jR6EdzKMs7WV\r\n18tNF3bgvdUNi6nqUlchlEBGg2WH3xwbgiA=\r\n=dDDf\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"blueromans","email":"blueromans@hotmail.com"},"directories":{},"maintainers":[{"name":"blueromans","email":"blueromans@hotmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/sdp-translator_0.0.3_1665697413678_0.23036989069036706"},"_hasShrinkwrap":false}},"time":{"created":"2022-10-13T21:40:08.474Z","0.0.2":"2022-10-13T21:40:08.801Z","modified":"2022-10-13T21:43:33.906Z","0.0.3":"2022-10-13T21:43:33.837Z"},"maintainers":[{"name":"blueromans","email":"blueromans@hotmail.com"}],"description":"A simple SDP interoperability layer for Unified Plan/Plan B","keywords":["sdp","webrtc","react-native-webrtc","interoperability","polyfill"],"author":{"name":"Yaşar Özyurt","email":"blueromans@hotmail.com"},"license":"Apache-2.0","readme":"## Introduction\n\n(or _Unified Plan, Plan B and the answer to life, the universe and eveything!_)\n\nIf somebody wants to talk about interoperability between Firefox and Chome when\ndoing multi-party video conferences, it is impossible to not talk a little bit\n(or a lot!) about [Unified\nPlan](https://tools.ietf.org/html/draft-roach-mmusic-unified-plan-00) and [Plan\nB](https://tools.ietf.org/html/draft-uberti-rtcweb-plan-00). Unified Plan and\nPlan B were two competing IETF drafts for the negotiation and exchange of\nmultiple media sources (AKA MediaStreamTracks, or MSTs) between two WebRTC\nendpoints. Unified Plan is being incorporated in the [JSEP\ndraft](https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-09) and is on its way\nto becoming an IETF standard while Plan B has expired in 2013 and nobody should\ncare about it anymore, right? Wrong!\n\nPlan B lives on in the Chrome and its derivatives, like Chromium and Opera.\nThere's actually an issue in the Chromium bug tracker to add support for\n[Unified Plan in\nChromium](https://code.google.com/p/chromium/issues/detail?id=465349), but\nthat'll take some time. Firefox, on the other hand, has, [as of\nrecently](https://hacks.mozilla.org/2015/03/webrtc-in-firefox-38-multistream-and-renegotiation/),\nimplemented Unified Plan.\n\nDevelopers that want to support both Firefox and Chrome have to deal with this\nsituation and implement some kind of _interoperability_ layer between Chrome and\nit derivatives and Firefox.\n\nThe most substantial difference between Unified Plan and Plan B is how they\nrepresent media stream tracks. Unified Plan extends the standard way of\nencoding this information in SDP which is to have each RTP flow (i.e., SSRC)\nappear on its own m-line. So, each media stream track is represented by its own\nunique m-line.  This is a strict one-to-one mapping; a single media stream\ntrack cannot be spread across several m-lines, nor may a single m-line\nrepresent multiple media stream tracks.\n\nPlan B takes a different approach, and creates a hierarchy within SDP; a m=\nline defines an \"envelope\", specifying codec and transport parameters, and\na=ssrc lines are used to describe individual media sources within that\nenvelope. So, typically, a Plan B SDP has three channels, one for audio, one\nfor video and one for the data.\n\n### Installation\n\nInstall locally from npm:\n\n```bash\n$ npm install @blueromans/sdp-translator\n```\nor yarn\n\n```bash\n$ yarn add @blueromans/sdp-translator\n```\n## Implementation\n\nThis module gives a general solution to the problem of SDP interoperability\ndescribed in the previous section and deals with it at the lowest level. The idea\nis to build a PeerConnection adapter that will feed the right SDP to the browser,\ni.e. Unified Plan to Firefox and Plan B to Chrome and that would give a Plan B SDP\nto the application.\n\n### The SDP interoperability layer\n\nsdp-interop is a reusable npm module that offers the two simple methods:\n\n* `toUnifiedPlan(sdp)` that takes an SDP string and transforms it into a\n  Unified Plan SDP.\n* `toPlanB(sdp)` that, not surprisingly, takes an SDP string and transforms it\n  to Plan B SDP.\n\nThe PeerConnection adapter wraps the `setLocalDescription()`,\n`setRemoteDescription()` methods and the success callbacks of the\n`createAnswer()` and `createOffer()` methods. If the browser is Chrome, the\nadapter does nothing. If, on the other hand, the browser is Firefox the\nPeerConnection adapter...\n\n* calls the `toUnifiedPlan()` method of the sdp-interop module prior to calling\n  the `setLocalDescription()` or the `setRemoteDescription()` methods, thus\n  converting the Plan B SDP from the application to a Unified Plan SDP that\n  Firefox can understand.\n* calls the `toPlanB()` method prior to calling the `createAnswer()` or the\n  `createOffer()` success callback, thus converting the Unified Plan SDP from\n  Firefox to a Plan B SDP that the application can understand.\n\nHere's a sample PeerConnection adapter:\n\n```javascript\nfunction PeerConnectionAdapter(ice_config, constraints) {\n    var RTCPeerConnection = navigator.mozGetUserMedia\n      ? mozRTCPeerConnection : webkitRTCPeerConnection;\n    this.peerconnection = new RTCPeerConnection(ice_config, constraints);\n    this.interop = new require('sdp-interop').Interop();\n}\n\nPeerConnectionAdapter.prototype.setLocalDescription\n  = function (description, successCallback, failureCallback) {\n    // if we're running on FF, transform to Unified Plan first.\n    if (navigator.mozGetUserMedia)\n        description = this.interop.toUnifiedPlan(description);\n\n    var self = this;\n    this.peerconnection.setLocalDescription(description,\n        function () { successCallback(); },\n        function (err) { failureCallback(err); }\n    );\n};\n\nPeerConnectionAdapter.prototype.setRemoteDescription\n  = function (description, successCallback, failureCallback) {\n    // if we're running on FF, transform to Unified Plan first.\n    if (navigator.mozGetUserMedia)\n        description = this.interop.toUnifiedPlan(description);\n\n    var self = this;\n    this.peerconnection.setRemoteDescription(description,\n        function () { successCallback(); },\n        function (err) { failureCallback(err); }\n    );\n};\n\nPeerConnectionAdapter.prototype.createAnswer\n  = function (successCallback, failureCallback, constraints) {\n    var self = this;\n    this.peerconnection.createAnswer(\n        function (answer) {\n            if (navigator.mozGetUserMedia)\n                answer = self.interop.toPlanB(answer);\n            successCallback(answer);\n        },\n        function(err) {\n            failureCallback(err);\n        },\n        constraints\n    );\n};\n\nPeerConnectionAdapter.prototype.createOffer\n  = function (successCallback, failureCallback, constraints) {\n    var self = this;\n    this.peerconnection.createOffer(\n        function (offer) {\n            if (navigator.mozGetUserMedia)\n                offer = self.interop.toPlanB(offer);\n            successCallback(offer);\n        },\n        function(err) {\n            failureCallback(err);\n        },\n        constraints\n    );\n};\n```","readmeFilename":"README.md"}