mirror of
https://github.com/Monibuca/plugin-webrtc.git
synced 2025-10-05 14:56:56 +08:00
first commit
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
node_modules
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2019-present, dexter
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
9
go.mod
Normal file
9
go.mod
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
module github.com/Monibuca/plugin-webrtc
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/Monibuca/engine/v2 v2.0.0
|
||||||
|
github.com/pion/rtcp v1.2.1
|
||||||
|
github.com/pion/webrtc/v2 v2.2.14
|
||||||
|
)
|
105
go.sum
Normal file
105
go.sum
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/Monibuca/engine v1.2.2 h1:hNjsrZpOmui8lYhgCJ5ltJU8g/k0Rrdysx2tHNGGnbI=
|
||||||
|
github.com/Monibuca/engine/v2 v2.0.0 h1:8FjaScrtN8QdbcxO9zZYABMC0Re3I1O1T4p94zAXYb0=
|
||||||
|
github.com/Monibuca/engine/v2 v2.0.0/go.mod h1:34EYjjV15G6myuHOKaJkO7y5tJ1Arq/NfC9Weacr2mc=
|
||||||
|
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
|
||||||
|
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||||
|
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/funny/slab v0.0.0-20180511031532-b1fad5e5d478 h1:Db9StoJ6RZN3YttC0Pm0I4Y5izITRYch3RMbT59BYN0=
|
||||||
|
github.com/funny/slab v0.0.0-20180511031532-b1fad5e5d478/go.mod h1:0j1+svBH8ABEIPdUP0AIg4qedsybnXGJBakCEw8cfoo=
|
||||||
|
github.com/funny/utest v0.0.0-20161029064919-43870a374500/go.mod h1:mUn39tBov9jKnTWV1RlOYoNzxdBFHiSzXWdY1FoNGGg=
|
||||||
|
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
|
||||||
|
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
||||||
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 h1:bqDmpDG49ZRnB5PcgP0RXtQvnMSgIF14M7CBd2shtXs=
|
||||||
|
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||||
|
github.com/lucas-clemente/quic-go v0.7.1-0.20190401152353-907071221cf9/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw=
|
||||||
|
github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk=
|
||||||
|
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
||||||
|
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
|
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||||
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
|
github.com/pion/datachannel v1.4.17 h1:8CChK5VrJoGrwKCysoTscoWvshCAFpUkgY11Tqgz5hE=
|
||||||
|
github.com/pion/datachannel v1.4.17/go.mod h1:+vPQfypU9vSsyPXogYj1hBThWQ6MNXEQoQAzxoPvjYM=
|
||||||
|
github.com/pion/dtls/v2 v2.0.0 h1:Fk+MBhLZ/U1bImzAhmzwbO/pP2rKhtTw8iA934H3ybE=
|
||||||
|
github.com/pion/dtls/v2 v2.0.0/go.mod h1:VkY5VL2wtsQQOG60xQ4lkV5pdn0wwBBTzCfRJqXhp3A=
|
||||||
|
github.com/pion/ice v0.7.15 h1:s1In+gnuyVq7WKWGVQL+1p+OcrMsbfL+VfSe2isH8Ag=
|
||||||
|
github.com/pion/ice v0.7.15/go.mod h1:Z6zybEQgky5mZkKcLfmvc266JukK2srz3VZBBD1iXBw=
|
||||||
|
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
|
||||||
|
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
|
||||||
|
github.com/pion/mdns v0.0.4 h1:O4vvVqr4DGX63vzmO6Fw9vpy3lfztVWHGCQfyw0ZLSY=
|
||||||
|
github.com/pion/mdns v0.0.4/go.mod h1:R1sL0p50l42S5lJs91oNdUL58nm0QHrhxnSegr++qC0=
|
||||||
|
github.com/pion/quic v0.1.1/go.mod h1:zEU51v7ru8Mp4AUBJvj6psrSth5eEFNnVQK5K48oV3k=
|
||||||
|
github.com/pion/rtcp v1.2.1 h1:S3yG4KpYAiSmBVqKAfgRa5JdwBNj4zK3RLUa8JYdhak=
|
||||||
|
github.com/pion/rtcp v1.2.1/go.mod h1:a5dj2d6BKIKHl43EnAOIrCczcjESrtPuMgfmL6/K6QM=
|
||||||
|
github.com/pion/rtp v1.5.4 h1:PuNg6xqV3brIUihatcKZj1YDUs+M45L0ZbrZWYtkDxY=
|
||||||
|
github.com/pion/rtp v1.5.4/go.mod h1:bg60AL5GotNOlYZsqycbhDtEV3TkfbpXG0KBiUq29Mg=
|
||||||
|
github.com/pion/sctp v1.7.6 h1:8qZTdJtbKfAns/Hv5L0PAj8FyXcsKhMH1pKUCGisQg4=
|
||||||
|
github.com/pion/sctp v1.7.6/go.mod h1:ichkYQ5tlgCQwEwvgfdcAolqx1nHbYCxo4D7zK/K0X8=
|
||||||
|
github.com/pion/sdp/v2 v2.3.7 h1:WUZHI3pfiYCaE8UGUYcabk863LCK+Bq3AklV5O0oInQ=
|
||||||
|
github.com/pion/sdp/v2 v2.3.7/go.mod h1:+ZZf35r1+zbaWYiZLfPutWfx58DAWcGb2QsS3D/s9M8=
|
||||||
|
github.com/pion/srtp v1.3.3 h1:8bjs9YaSNvSrbH0OfKxzPX+PTrCyAC2LoT9Qesugi+U=
|
||||||
|
github.com/pion/srtp v1.3.3/go.mod h1:jNe0jmIOqksuurR9S/7yoKDalfPeluUFrNPCBqI4FOI=
|
||||||
|
github.com/pion/stun v0.3.3 h1:brYuPl9bN9w/VM7OdNzRSLoqsnwlyNvD9MVeJrHjDQw=
|
||||||
|
github.com/pion/stun v0.3.3/go.mod h1:xrCld6XM+6GWDZdvjPlLMsTU21rNxnO6UO8XsAvHr/M=
|
||||||
|
github.com/pion/transport v0.6.0/go.mod h1:iWZ07doqOosSLMhZ+FXUTq+TamDoXSllxpbGcfkCmbE=
|
||||||
|
github.com/pion/transport v0.8.10/go.mod h1:tBmha/UCjpum5hqTWhfAEs3CO4/tHSg0MYRhSzR+CZ8=
|
||||||
|
github.com/pion/transport v0.10.0 h1:9M12BSneJm6ggGhJyWpDveFOstJsTiQjkLf4M44rm80=
|
||||||
|
github.com/pion/transport v0.10.0/go.mod h1:BnHnUipd0rZQyTVB2SBGojFHT9CBt5C5TcsJSQGkvSE=
|
||||||
|
github.com/pion/turn/v2 v2.0.3 h1:SJUUIbcPoehlyZgMyIUbBBDhI03sBx32x3JuSIBKBWA=
|
||||||
|
github.com/pion/turn/v2 v2.0.3/go.mod h1:kl1hmT3NxcLynpXVnwJgObL8C9NaCyPTeqI2DcCpSZs=
|
||||||
|
github.com/pion/webrtc v1.2.0 h1:3LGGPQEMacwG2hcDfhdvwQPz315gvjZXOfY4vaF4+I4=
|
||||||
|
github.com/pion/webrtc/v2 v2.2.14 h1:bRjnXTqMDJ3VERPF45z439Sv6QfDfjdYvdQk1QcIx8M=
|
||||||
|
github.com/pion/webrtc/v2 v2.2.14/go.mod h1:G+8lShCMbHhjpMF1ZJBkyuvrxXrvW4bxs3nOt+mJ2UI=
|
||||||
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
||||||
|
github.com/shirou/gopsutil v2.20.1+incompatible h1:oIq9Cq4i84Hk8uQAUOG3eNdI/29hBawGrD5YRl6JRDY=
|
||||||
|
github.com/shirou/gopsutil v2.20.1+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
|
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM=
|
||||||
|
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5 h1:WQ8q63x+f/zpC8Ac1s9wLElVoHhm32p6tudrU72n1QA=
|
||||||
|
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
199
main.go
Normal file
199
main.go
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
package webrtc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
. "github.com/Monibuca/engine/v2"
|
||||||
|
"github.com/pion/rtcp"
|
||||||
|
. "github.com/pion/webrtc/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var config = &struct {
|
||||||
|
ICEServers []string
|
||||||
|
}{[]string{
|
||||||
|
"stun.l.google.com:19302",
|
||||||
|
"stun1.l.google.com:19302",
|
||||||
|
"stun2.l.google.com:19302",
|
||||||
|
"stun3.l.google.com:19302",
|
||||||
|
"stun4.l.google.com:19302",
|
||||||
|
"stun.ekiga.net",
|
||||||
|
"stun.ideasip.com",
|
||||||
|
"stun.schlund.de",
|
||||||
|
"stun.stunprotocol.org:3478",
|
||||||
|
"stun.voiparound.com",
|
||||||
|
"stun.voipbuster.com",
|
||||||
|
"stun.voipstunt.com",
|
||||||
|
"stun.voxgratia.org",
|
||||||
|
"stun.services.mozilla.com",
|
||||||
|
"stun:stun.xten.com",
|
||||||
|
"stun:stun.softjoys.com",
|
||||||
|
"stun:stunserver.org",
|
||||||
|
"stun:stun.schlund.de",
|
||||||
|
"stun:stun.rixtelecom.se",
|
||||||
|
"stun:stun.iptel.org",
|
||||||
|
"stun:stun.ideasip.com",
|
||||||
|
"stun:stun.fwdnet.net",
|
||||||
|
"stun:stun.ekiga.net",
|
||||||
|
"stun:stun01.sipphone.com",
|
||||||
|
}}
|
||||||
|
|
||||||
|
type udpConn struct {
|
||||||
|
conn *net.UDPConn
|
||||||
|
port int
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
InstallPlugin(&PluginConfig{
|
||||||
|
Config: config,
|
||||||
|
Name: "WebRTC",
|
||||||
|
Type: PLUGIN_PUBLISHER | PLUGIN_SUBSCRIBER,
|
||||||
|
Run: run,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
func run() {
|
||||||
|
m := MediaEngine{}
|
||||||
|
m.RegisterCodec(NewRTPH264Codec(DefaultPayloadTypeH264, 90000))
|
||||||
|
api := NewAPI(WithMediaEngine(m))
|
||||||
|
peerConnection, err := api.NewPeerConnection(Configuration{
|
||||||
|
ICEServers: []ICEServer{
|
||||||
|
{
|
||||||
|
URLs: config.ICEServers,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Allow us to receive 1 audio track, and 1 video track
|
||||||
|
if _, err = peerConnection.AddTransceiverFromKind(RTPCodecTypeAudio); err != nil {
|
||||||
|
if err != nil {
|
||||||
|
Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else if _, err = peerConnection.AddTransceiverFromKind(RTPCodecTypeVideo); err != nil {
|
||||||
|
if err != nil {
|
||||||
|
Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var laddr *net.UDPAddr
|
||||||
|
if laddr, err = net.ResolveUDPAddr("udp", "127.0.0.1:"); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare udp conns
|
||||||
|
udpConns := map[string]*udpConn{
|
||||||
|
"audio": {port: 4000},
|
||||||
|
"video": {port: 4002},
|
||||||
|
}
|
||||||
|
for _, c := range udpConns {
|
||||||
|
// Create remote addr
|
||||||
|
var raddr *net.UDPAddr
|
||||||
|
if raddr, err = net.ResolveUDPAddr("udp", fmt.Sprintf("127.0.0.1:%d", c.port)); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dial udp
|
||||||
|
if c.conn, err = net.DialUDP("udp", laddr, raddr); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer func(conn net.PacketConn) {
|
||||||
|
if closeErr := conn.Close(); closeErr != nil {
|
||||||
|
panic(closeErr)
|
||||||
|
}
|
||||||
|
}(c.conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a handler for when a new remote track starts, this handler will forward data to
|
||||||
|
// our UDP listeners.
|
||||||
|
// In your application this is where you would handle/process audio/video
|
||||||
|
peerConnection.OnTrack(func(track *Track, receiver *RTPReceiver) {
|
||||||
|
// Retrieve udp connection
|
||||||
|
c, ok := udpConns[track.Kind().String()]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval
|
||||||
|
go func() {
|
||||||
|
ticker := time.NewTicker(time.Second * 2)
|
||||||
|
for range ticker.C {
|
||||||
|
if rtcpErr := peerConnection.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: track.SSRC()}}); rtcpErr != nil {
|
||||||
|
fmt.Println(rtcpErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
b := make([]byte, 1500)
|
||||||
|
for {
|
||||||
|
// Read
|
||||||
|
n, readErr := track.Read(b)
|
||||||
|
if readErr != nil {
|
||||||
|
panic(readErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write
|
||||||
|
if _, err = c.conn.Write(b[:n]); err != nil {
|
||||||
|
// For this particular example, third party applications usually timeout after a short
|
||||||
|
// amount of time during which the user doesn't have enough time to provide the answer
|
||||||
|
// to the browser.
|
||||||
|
// That's why, for this particular example, the user first needs to provide the answer
|
||||||
|
// to the browser then open the third party application. Therefore we must not kill
|
||||||
|
// the forward on "connection refused" errors
|
||||||
|
if opError, ok := err.(*net.OpError); ok && opError.Err.Error() == "write: connection refused" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Set the handler for ICE connection state
|
||||||
|
// This will notify you when the peer has connected/disconnected
|
||||||
|
peerConnection.OnICEConnectionStateChange(func(connectionState ICEConnectionState) {
|
||||||
|
fmt.Printf("Connection State has changed %s \n", connectionState.String())
|
||||||
|
|
||||||
|
if connectionState == ICEConnectionStateConnected {
|
||||||
|
fmt.Println("Ctrl+C the remote client to stop the demo")
|
||||||
|
} else if connectionState == ICEConnectionStateFailed ||
|
||||||
|
connectionState == ICEConnectionStateDisconnected {
|
||||||
|
fmt.Println("Done forwarding")
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
})
|
||||||
|
http.HandleFunc("/webrtc/answer", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// Wait for the offer to be pasted
|
||||||
|
offer := SessionDescription{}
|
||||||
|
bytes, err := ioutil.ReadAll(r.Body)
|
||||||
|
err = json.Unmarshal(bytes, &offer)
|
||||||
|
if err != nil {
|
||||||
|
Println(err)
|
||||||
|
}
|
||||||
|
// Set the remote SessionDescription
|
||||||
|
if err = peerConnection.SetRemoteDescription(offer); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create answer
|
||||||
|
answer, err := peerConnection.CreateAnswer(nil)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the LocalDescription, and starts our UDP listeners
|
||||||
|
if err = peerConnection.SetLocalDescription(answer); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
bytes, err = json.Marshal(answer)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
w.Write(bytes)
|
||||||
|
})
|
||||||
|
}
|
19
ui/dist/demo.html
vendored
Normal file
19
ui/dist/demo.html
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<meta charset="utf-8">
|
||||||
|
<title>plugin-webrtc demo</title>
|
||||||
|
<script src="https://unpkg.com/vue"></script>
|
||||||
|
<script src="./plugin-webrtc.umd.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="./plugin-webrtc.css">
|
||||||
|
|
||||||
|
|
||||||
|
<div id="app">
|
||||||
|
<demo></demo>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
new Vue({
|
||||||
|
components: {
|
||||||
|
demo: plugin-webrtc
|
||||||
|
}
|
||||||
|
}).$mount('#app')
|
||||||
|
</script>
|
408
ui/dist/plugin-webrtc.common.js
vendored
Normal file
408
ui/dist/plugin-webrtc.common.js
vendored
Normal file
@@ -0,0 +1,408 @@
|
|||||||
|
module.exports =
|
||||||
|
/******/ (function(modules) { // webpackBootstrap
|
||||||
|
/******/ // The module cache
|
||||||
|
/******/ var installedModules = {};
|
||||||
|
/******/
|
||||||
|
/******/ // The require function
|
||||||
|
/******/ function __webpack_require__(moduleId) {
|
||||||
|
/******/
|
||||||
|
/******/ // Check if module is in cache
|
||||||
|
/******/ if(installedModules[moduleId]) {
|
||||||
|
/******/ return installedModules[moduleId].exports;
|
||||||
|
/******/ }
|
||||||
|
/******/ // Create a new module (and put it into the cache)
|
||||||
|
/******/ var module = installedModules[moduleId] = {
|
||||||
|
/******/ i: moduleId,
|
||||||
|
/******/ l: false,
|
||||||
|
/******/ exports: {}
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // Execute the module function
|
||||||
|
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||||
|
/******/
|
||||||
|
/******/ // Flag the module as loaded
|
||||||
|
/******/ module.l = true;
|
||||||
|
/******/
|
||||||
|
/******/ // Return the exports of the module
|
||||||
|
/******/ return module.exports;
|
||||||
|
/******/ }
|
||||||
|
/******/
|
||||||
|
/******/
|
||||||
|
/******/ // expose the modules object (__webpack_modules__)
|
||||||
|
/******/ __webpack_require__.m = modules;
|
||||||
|
/******/
|
||||||
|
/******/ // expose the module cache
|
||||||
|
/******/ __webpack_require__.c = installedModules;
|
||||||
|
/******/
|
||||||
|
/******/ // define getter function for harmony exports
|
||||||
|
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||||
|
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||||
|
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
||||||
|
/******/ }
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // define __esModule on exports
|
||||||
|
/******/ __webpack_require__.r = function(exports) {
|
||||||
|
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
||||||
|
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
||||||
|
/******/ }
|
||||||
|
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // create a fake namespace object
|
||||||
|
/******/ // mode & 1: value is a module id, require it
|
||||||
|
/******/ // mode & 2: merge all properties of value into the ns
|
||||||
|
/******/ // mode & 4: return value when already ns object
|
||||||
|
/******/ // mode & 8|1: behave like require
|
||||||
|
/******/ __webpack_require__.t = function(value, mode) {
|
||||||
|
/******/ if(mode & 1) value = __webpack_require__(value);
|
||||||
|
/******/ if(mode & 8) return value;
|
||||||
|
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
||||||
|
/******/ var ns = Object.create(null);
|
||||||
|
/******/ __webpack_require__.r(ns);
|
||||||
|
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
||||||
|
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
||||||
|
/******/ return ns;
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||||
|
/******/ __webpack_require__.n = function(module) {
|
||||||
|
/******/ var getter = module && module.__esModule ?
|
||||||
|
/******/ function getDefault() { return module['default']; } :
|
||||||
|
/******/ function getModuleExports() { return module; };
|
||||||
|
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||||
|
/******/ return getter;
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // Object.prototype.hasOwnProperty.call
|
||||||
|
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||||
|
/******/
|
||||||
|
/******/ // __webpack_public_path__
|
||||||
|
/******/ __webpack_require__.p = "";
|
||||||
|
/******/
|
||||||
|
/******/
|
||||||
|
/******/ // Load entry module and return exports
|
||||||
|
/******/ return __webpack_require__(__webpack_require__.s = "fb15");
|
||||||
|
/******/ })
|
||||||
|
/************************************************************************/
|
||||||
|
/******/ ({
|
||||||
|
|
||||||
|
/***/ "8875":
|
||||||
|
/***/ (function(module, exports, __webpack_require__) {
|
||||||
|
|
||||||
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;// addapted from the document.currentScript polyfill by Adam Miller
|
||||||
|
// MIT license
|
||||||
|
// source: https://github.com/amiller-gh/currentScript-polyfill
|
||||||
|
|
||||||
|
// added support for Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1620505
|
||||||
|
|
||||||
|
(function (root, factory) {
|
||||||
|
if (true) {
|
||||||
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
||||||
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
||||||
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
||||||
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
||||||
|
} else {}
|
||||||
|
}(typeof self !== 'undefined' ? self : this, function () {
|
||||||
|
function getCurrentScript () {
|
||||||
|
if (document.currentScript) {
|
||||||
|
return document.currentScript
|
||||||
|
}
|
||||||
|
|
||||||
|
// IE 8-10 support script readyState
|
||||||
|
// IE 11+ & Firefox support stack trace
|
||||||
|
try {
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
// Find the second match for the "at" string to get file src url from stack.
|
||||||
|
var ieStackRegExp = /.*at [^(]*\((.*):(.+):(.+)\)$/ig,
|
||||||
|
ffStackRegExp = /@([^@]*):(\d+):(\d+)\s*$/ig,
|
||||||
|
stackDetails = ieStackRegExp.exec(err.stack) || ffStackRegExp.exec(err.stack),
|
||||||
|
scriptLocation = (stackDetails && stackDetails[1]) || false,
|
||||||
|
line = (stackDetails && stackDetails[2]) || false,
|
||||||
|
currentLocation = document.location.href.replace(document.location.hash, ''),
|
||||||
|
pageSource,
|
||||||
|
inlineScriptSourceRegExp,
|
||||||
|
inlineScriptSource,
|
||||||
|
scripts = document.getElementsByTagName('script'); // Live NodeList collection
|
||||||
|
|
||||||
|
if (scriptLocation === currentLocation) {
|
||||||
|
pageSource = document.documentElement.outerHTML;
|
||||||
|
inlineScriptSourceRegExp = new RegExp('(?:[^\\n]+?\\n){0,' + (line - 2) + '}[^<]*<script>([\\d\\D]*?)<\\/script>[\\d\\D]*', 'i');
|
||||||
|
inlineScriptSource = pageSource.replace(inlineScriptSourceRegExp, '$1').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < scripts.length; i++) {
|
||||||
|
// If ready state is interactive, return the script tag
|
||||||
|
if (scripts[i].readyState === 'interactive') {
|
||||||
|
return scripts[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// If src matches, return the script tag
|
||||||
|
if (scripts[i].src === scriptLocation) {
|
||||||
|
return scripts[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// If inline source matches, return the script tag
|
||||||
|
if (
|
||||||
|
scriptLocation === currentLocation &&
|
||||||
|
scripts[i].innerHTML &&
|
||||||
|
scripts[i].innerHTML.trim() === inlineScriptSource
|
||||||
|
) {
|
||||||
|
return scripts[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no match, return null
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return getCurrentScript
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ "fb15":
|
||||||
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
// ESM COMPAT FLAG
|
||||||
|
__webpack_require__.r(__webpack_exports__);
|
||||||
|
|
||||||
|
// CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js
|
||||||
|
// This file is imported into lib/wc client bundles.
|
||||||
|
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
var currentScript = window.document.currentScript
|
||||||
|
if (true) {
|
||||||
|
var getCurrentScript = __webpack_require__("8875")
|
||||||
|
currentScript = getCurrentScript()
|
||||||
|
|
||||||
|
// for backward compatibility, because previously we directly included the polyfill
|
||||||
|
if (!('currentScript' in document)) {
|
||||||
|
Object.defineProperty(document, 'currentScript', { get: getCurrentScript })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var src = currentScript && currentScript.src.match(/(.+\/)[^/]+\.js(\?.*)?$/)
|
||||||
|
if (src) {
|
||||||
|
__webpack_require__.p = src[1] // eslint-disable-line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicate to webpack that this file can be concatenated
|
||||||
|
/* harmony default export */ var setPublicPath = (null);
|
||||||
|
|
||||||
|
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"46d6b4f7-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=template&id=69b8f189&
|
||||||
|
var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_vm._v(" Browser base64 Session Description "),_c('br'),_c('textarea',{attrs:{"readonly":"true"},domProps:{"value":_vm.localDescription}}),_c('br'),_vm._v("Golang base64 Session Description "),_c('br'),_c('textarea',{domProps:{"value":_vm.remoteSessionDescription}}),_c('br'),_c('button',{on:{"click":_vm.startSession}},[_vm._v("Start Session")]),_c('br'),_c('br'),_vm._v("Video "),_c('br'),_c('video',{attrs:{"id":"video1","width":"160","height":"120","autoplay":"","muted":""},domProps:{"muted":true}}),_c('br'),_vm._v("Logs "),_c('br'),_c('div',{attrs:{"id":"logs"}})])}
|
||||||
|
var staticRenderFns = []
|
||||||
|
|
||||||
|
|
||||||
|
// CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=69b8f189&
|
||||||
|
|
||||||
|
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=script&lang=js&
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
let pc = new RTCPeerConnection({
|
||||||
|
iceServers: [
|
||||||
|
{
|
||||||
|
urls: "stun:stun.l.google.com:19302"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
/* harmony default export */ var Appvue_type_script_lang_js_ = ({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
localDescription: "",
|
||||||
|
remoteSessionDescription: ""
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
startSession() {
|
||||||
|
this.ajax.post("/webrtc/answer", this.localDescription).then(result => {
|
||||||
|
this.remoteSessionDescription = result;
|
||||||
|
pc.setRemoteDescription(new RTCSessionDescription(result));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
/* eslint-env browser */
|
||||||
|
var log = msg => {
|
||||||
|
document.getElementById("logs").innerHTML += msg + "<br>";
|
||||||
|
};
|
||||||
|
|
||||||
|
navigator.mediaDevices
|
||||||
|
.getUserMedia({ video: true, audio: true })
|
||||||
|
.then(stream => {
|
||||||
|
pc.addStream((document.getElementById("video1").srcObject = stream));
|
||||||
|
pc.createOffer()
|
||||||
|
.then(d => pc.setLocalDescription(d))
|
||||||
|
.catch(log);
|
||||||
|
})
|
||||||
|
.catch(log);
|
||||||
|
|
||||||
|
pc.oniceconnectionstatechange = e => log(pc.iceConnectionState);
|
||||||
|
pc.onicecandidate = event => {
|
||||||
|
if (event.candidate === null) {
|
||||||
|
this.localDescription = JSON.stringify(pc.localDescription);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// CONCATENATED MODULE: ./src/App.vue?vue&type=script&lang=js&
|
||||||
|
/* harmony default export */ var src_Appvue_type_script_lang_js_ = (Appvue_type_script_lang_js_);
|
||||||
|
// CONCATENATED MODULE: ./node_modules/vue-loader/lib/runtime/componentNormalizer.js
|
||||||
|
/* globals __VUE_SSR_CONTEXT__ */
|
||||||
|
|
||||||
|
// IMPORTANT: Do NOT use ES2015 features in this file (except for modules).
|
||||||
|
// This module is a runtime utility for cleaner component module output and will
|
||||||
|
// be included in the final webpack user bundle.
|
||||||
|
|
||||||
|
function normalizeComponent (
|
||||||
|
scriptExports,
|
||||||
|
render,
|
||||||
|
staticRenderFns,
|
||||||
|
functionalTemplate,
|
||||||
|
injectStyles,
|
||||||
|
scopeId,
|
||||||
|
moduleIdentifier, /* server only */
|
||||||
|
shadowMode /* vue-cli only */
|
||||||
|
) {
|
||||||
|
// Vue.extend constructor export interop
|
||||||
|
var options = typeof scriptExports === 'function'
|
||||||
|
? scriptExports.options
|
||||||
|
: scriptExports
|
||||||
|
|
||||||
|
// render functions
|
||||||
|
if (render) {
|
||||||
|
options.render = render
|
||||||
|
options.staticRenderFns = staticRenderFns
|
||||||
|
options._compiled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// functional template
|
||||||
|
if (functionalTemplate) {
|
||||||
|
options.functional = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// scopedId
|
||||||
|
if (scopeId) {
|
||||||
|
options._scopeId = 'data-v-' + scopeId
|
||||||
|
}
|
||||||
|
|
||||||
|
var hook
|
||||||
|
if (moduleIdentifier) { // server build
|
||||||
|
hook = function (context) {
|
||||||
|
// 2.3 injection
|
||||||
|
context =
|
||||||
|
context || // cached call
|
||||||
|
(this.$vnode && this.$vnode.ssrContext) || // stateful
|
||||||
|
(this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional
|
||||||
|
// 2.2 with runInNewContext: true
|
||||||
|
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
|
||||||
|
context = __VUE_SSR_CONTEXT__
|
||||||
|
}
|
||||||
|
// inject component styles
|
||||||
|
if (injectStyles) {
|
||||||
|
injectStyles.call(this, context)
|
||||||
|
}
|
||||||
|
// register component module identifier for async chunk inferrence
|
||||||
|
if (context && context._registeredComponents) {
|
||||||
|
context._registeredComponents.add(moduleIdentifier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// used by ssr in case component is cached and beforeCreate
|
||||||
|
// never gets called
|
||||||
|
options._ssrRegister = hook
|
||||||
|
} else if (injectStyles) {
|
||||||
|
hook = shadowMode
|
||||||
|
? function () {
|
||||||
|
injectStyles.call(
|
||||||
|
this,
|
||||||
|
(options.functional ? this.parent : this).$root.$options.shadowRoot
|
||||||
|
)
|
||||||
|
}
|
||||||
|
: injectStyles
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hook) {
|
||||||
|
if (options.functional) {
|
||||||
|
// for template-only hot-reload because in that case the render fn doesn't
|
||||||
|
// go through the normalizer
|
||||||
|
options._injectStyles = hook
|
||||||
|
// register for functional component in vue file
|
||||||
|
var originalRender = options.render
|
||||||
|
options.render = function renderWithStyleInjection (h, context) {
|
||||||
|
hook.call(context)
|
||||||
|
return originalRender(h, context)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// inject component registration as beforeCreate hook
|
||||||
|
var existing = options.beforeCreate
|
||||||
|
options.beforeCreate = existing
|
||||||
|
? [].concat(existing, hook)
|
||||||
|
: [hook]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
exports: scriptExports,
|
||||||
|
options: options
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CONCATENATED MODULE: ./src/App.vue
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* normalize component */
|
||||||
|
|
||||||
|
var component = normalizeComponent(
|
||||||
|
src_Appvue_type_script_lang_js_,
|
||||||
|
render,
|
||||||
|
staticRenderFns,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
/* harmony default export */ var App = (component.exports);
|
||||||
|
// CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/entry-lib.js
|
||||||
|
|
||||||
|
|
||||||
|
/* harmony default export */ var entry_lib = __webpack_exports__["default"] = (App);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***/ })
|
||||||
|
|
||||||
|
/******/ })["default"];
|
||||||
|
//# sourceMappingURL=plugin-webrtc.common.js.map
|
1
ui/dist/plugin-webrtc.common.js.map
vendored
Normal file
1
ui/dist/plugin-webrtc.common.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
418
ui/dist/plugin-webrtc.umd.js
vendored
Normal file
418
ui/dist/plugin-webrtc.umd.js
vendored
Normal file
@@ -0,0 +1,418 @@
|
|||||||
|
(function webpackUniversalModuleDefinition(root, factory) {
|
||||||
|
if(typeof exports === 'object' && typeof module === 'object')
|
||||||
|
module.exports = factory();
|
||||||
|
else if(typeof define === 'function' && define.amd)
|
||||||
|
define([], factory);
|
||||||
|
else if(typeof exports === 'object')
|
||||||
|
exports["plugin-webrtc"] = factory();
|
||||||
|
else
|
||||||
|
root["plugin-webrtc"] = factory();
|
||||||
|
})((typeof self !== 'undefined' ? self : this), function() {
|
||||||
|
return /******/ (function(modules) { // webpackBootstrap
|
||||||
|
/******/ // The module cache
|
||||||
|
/******/ var installedModules = {};
|
||||||
|
/******/
|
||||||
|
/******/ // The require function
|
||||||
|
/******/ function __webpack_require__(moduleId) {
|
||||||
|
/******/
|
||||||
|
/******/ // Check if module is in cache
|
||||||
|
/******/ if(installedModules[moduleId]) {
|
||||||
|
/******/ return installedModules[moduleId].exports;
|
||||||
|
/******/ }
|
||||||
|
/******/ // Create a new module (and put it into the cache)
|
||||||
|
/******/ var module = installedModules[moduleId] = {
|
||||||
|
/******/ i: moduleId,
|
||||||
|
/******/ l: false,
|
||||||
|
/******/ exports: {}
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // Execute the module function
|
||||||
|
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||||
|
/******/
|
||||||
|
/******/ // Flag the module as loaded
|
||||||
|
/******/ module.l = true;
|
||||||
|
/******/
|
||||||
|
/******/ // Return the exports of the module
|
||||||
|
/******/ return module.exports;
|
||||||
|
/******/ }
|
||||||
|
/******/
|
||||||
|
/******/
|
||||||
|
/******/ // expose the modules object (__webpack_modules__)
|
||||||
|
/******/ __webpack_require__.m = modules;
|
||||||
|
/******/
|
||||||
|
/******/ // expose the module cache
|
||||||
|
/******/ __webpack_require__.c = installedModules;
|
||||||
|
/******/
|
||||||
|
/******/ // define getter function for harmony exports
|
||||||
|
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||||
|
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||||
|
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
||||||
|
/******/ }
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // define __esModule on exports
|
||||||
|
/******/ __webpack_require__.r = function(exports) {
|
||||||
|
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
||||||
|
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
||||||
|
/******/ }
|
||||||
|
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // create a fake namespace object
|
||||||
|
/******/ // mode & 1: value is a module id, require it
|
||||||
|
/******/ // mode & 2: merge all properties of value into the ns
|
||||||
|
/******/ // mode & 4: return value when already ns object
|
||||||
|
/******/ // mode & 8|1: behave like require
|
||||||
|
/******/ __webpack_require__.t = function(value, mode) {
|
||||||
|
/******/ if(mode & 1) value = __webpack_require__(value);
|
||||||
|
/******/ if(mode & 8) return value;
|
||||||
|
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
||||||
|
/******/ var ns = Object.create(null);
|
||||||
|
/******/ __webpack_require__.r(ns);
|
||||||
|
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
||||||
|
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
||||||
|
/******/ return ns;
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||||
|
/******/ __webpack_require__.n = function(module) {
|
||||||
|
/******/ var getter = module && module.__esModule ?
|
||||||
|
/******/ function getDefault() { return module['default']; } :
|
||||||
|
/******/ function getModuleExports() { return module; };
|
||||||
|
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||||
|
/******/ return getter;
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // Object.prototype.hasOwnProperty.call
|
||||||
|
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||||
|
/******/
|
||||||
|
/******/ // __webpack_public_path__
|
||||||
|
/******/ __webpack_require__.p = "";
|
||||||
|
/******/
|
||||||
|
/******/
|
||||||
|
/******/ // Load entry module and return exports
|
||||||
|
/******/ return __webpack_require__(__webpack_require__.s = "fb15");
|
||||||
|
/******/ })
|
||||||
|
/************************************************************************/
|
||||||
|
/******/ ({
|
||||||
|
|
||||||
|
/***/ "8875":
|
||||||
|
/***/ (function(module, exports, __webpack_require__) {
|
||||||
|
|
||||||
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;// addapted from the document.currentScript polyfill by Adam Miller
|
||||||
|
// MIT license
|
||||||
|
// source: https://github.com/amiller-gh/currentScript-polyfill
|
||||||
|
|
||||||
|
// added support for Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1620505
|
||||||
|
|
||||||
|
(function (root, factory) {
|
||||||
|
if (true) {
|
||||||
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
||||||
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
||||||
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
||||||
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
||||||
|
} else {}
|
||||||
|
}(typeof self !== 'undefined' ? self : this, function () {
|
||||||
|
function getCurrentScript () {
|
||||||
|
if (document.currentScript) {
|
||||||
|
return document.currentScript
|
||||||
|
}
|
||||||
|
|
||||||
|
// IE 8-10 support script readyState
|
||||||
|
// IE 11+ & Firefox support stack trace
|
||||||
|
try {
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
// Find the second match for the "at" string to get file src url from stack.
|
||||||
|
var ieStackRegExp = /.*at [^(]*\((.*):(.+):(.+)\)$/ig,
|
||||||
|
ffStackRegExp = /@([^@]*):(\d+):(\d+)\s*$/ig,
|
||||||
|
stackDetails = ieStackRegExp.exec(err.stack) || ffStackRegExp.exec(err.stack),
|
||||||
|
scriptLocation = (stackDetails && stackDetails[1]) || false,
|
||||||
|
line = (stackDetails && stackDetails[2]) || false,
|
||||||
|
currentLocation = document.location.href.replace(document.location.hash, ''),
|
||||||
|
pageSource,
|
||||||
|
inlineScriptSourceRegExp,
|
||||||
|
inlineScriptSource,
|
||||||
|
scripts = document.getElementsByTagName('script'); // Live NodeList collection
|
||||||
|
|
||||||
|
if (scriptLocation === currentLocation) {
|
||||||
|
pageSource = document.documentElement.outerHTML;
|
||||||
|
inlineScriptSourceRegExp = new RegExp('(?:[^\\n]+?\\n){0,' + (line - 2) + '}[^<]*<script>([\\d\\D]*?)<\\/script>[\\d\\D]*', 'i');
|
||||||
|
inlineScriptSource = pageSource.replace(inlineScriptSourceRegExp, '$1').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < scripts.length; i++) {
|
||||||
|
// If ready state is interactive, return the script tag
|
||||||
|
if (scripts[i].readyState === 'interactive') {
|
||||||
|
return scripts[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// If src matches, return the script tag
|
||||||
|
if (scripts[i].src === scriptLocation) {
|
||||||
|
return scripts[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// If inline source matches, return the script tag
|
||||||
|
if (
|
||||||
|
scriptLocation === currentLocation &&
|
||||||
|
scripts[i].innerHTML &&
|
||||||
|
scripts[i].innerHTML.trim() === inlineScriptSource
|
||||||
|
) {
|
||||||
|
return scripts[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no match, return null
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return getCurrentScript
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ "fb15":
|
||||||
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
// ESM COMPAT FLAG
|
||||||
|
__webpack_require__.r(__webpack_exports__);
|
||||||
|
|
||||||
|
// CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js
|
||||||
|
// This file is imported into lib/wc client bundles.
|
||||||
|
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
var currentScript = window.document.currentScript
|
||||||
|
if (true) {
|
||||||
|
var getCurrentScript = __webpack_require__("8875")
|
||||||
|
currentScript = getCurrentScript()
|
||||||
|
|
||||||
|
// for backward compatibility, because previously we directly included the polyfill
|
||||||
|
if (!('currentScript' in document)) {
|
||||||
|
Object.defineProperty(document, 'currentScript', { get: getCurrentScript })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var src = currentScript && currentScript.src.match(/(.+\/)[^/]+\.js(\?.*)?$/)
|
||||||
|
if (src) {
|
||||||
|
__webpack_require__.p = src[1] // eslint-disable-line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicate to webpack that this file can be concatenated
|
||||||
|
/* harmony default export */ var setPublicPath = (null);
|
||||||
|
|
||||||
|
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"46d6b4f7-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=template&id=69b8f189&
|
||||||
|
var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_vm._v(" Browser base64 Session Description "),_c('br'),_c('textarea',{attrs:{"readonly":"true"},domProps:{"value":_vm.localDescription}}),_c('br'),_vm._v("Golang base64 Session Description "),_c('br'),_c('textarea',{domProps:{"value":_vm.remoteSessionDescription}}),_c('br'),_c('button',{on:{"click":_vm.startSession}},[_vm._v("Start Session")]),_c('br'),_c('br'),_vm._v("Video "),_c('br'),_c('video',{attrs:{"id":"video1","width":"160","height":"120","autoplay":"","muted":""},domProps:{"muted":true}}),_c('br'),_vm._v("Logs "),_c('br'),_c('div',{attrs:{"id":"logs"}})])}
|
||||||
|
var staticRenderFns = []
|
||||||
|
|
||||||
|
|
||||||
|
// CONCATENATED MODULE: ./src/App.vue?vue&type=template&id=69b8f189&
|
||||||
|
|
||||||
|
// CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/App.vue?vue&type=script&lang=js&
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
let pc = new RTCPeerConnection({
|
||||||
|
iceServers: [
|
||||||
|
{
|
||||||
|
urls: "stun:stun.l.google.com:19302"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
/* harmony default export */ var Appvue_type_script_lang_js_ = ({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
localDescription: "",
|
||||||
|
remoteSessionDescription: ""
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
startSession() {
|
||||||
|
this.ajax.post("/webrtc/answer", this.localDescription).then(result => {
|
||||||
|
this.remoteSessionDescription = result;
|
||||||
|
pc.setRemoteDescription(new RTCSessionDescription(result));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
/* eslint-env browser */
|
||||||
|
var log = msg => {
|
||||||
|
document.getElementById("logs").innerHTML += msg + "<br>";
|
||||||
|
};
|
||||||
|
|
||||||
|
navigator.mediaDevices
|
||||||
|
.getUserMedia({ video: true, audio: true })
|
||||||
|
.then(stream => {
|
||||||
|
pc.addStream((document.getElementById("video1").srcObject = stream));
|
||||||
|
pc.createOffer()
|
||||||
|
.then(d => pc.setLocalDescription(d))
|
||||||
|
.catch(log);
|
||||||
|
})
|
||||||
|
.catch(log);
|
||||||
|
|
||||||
|
pc.oniceconnectionstatechange = e => log(pc.iceConnectionState);
|
||||||
|
pc.onicecandidate = event => {
|
||||||
|
if (event.candidate === null) {
|
||||||
|
this.localDescription = JSON.stringify(pc.localDescription);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// CONCATENATED MODULE: ./src/App.vue?vue&type=script&lang=js&
|
||||||
|
/* harmony default export */ var src_Appvue_type_script_lang_js_ = (Appvue_type_script_lang_js_);
|
||||||
|
// CONCATENATED MODULE: ./node_modules/vue-loader/lib/runtime/componentNormalizer.js
|
||||||
|
/* globals __VUE_SSR_CONTEXT__ */
|
||||||
|
|
||||||
|
// IMPORTANT: Do NOT use ES2015 features in this file (except for modules).
|
||||||
|
// This module is a runtime utility for cleaner component module output and will
|
||||||
|
// be included in the final webpack user bundle.
|
||||||
|
|
||||||
|
function normalizeComponent (
|
||||||
|
scriptExports,
|
||||||
|
render,
|
||||||
|
staticRenderFns,
|
||||||
|
functionalTemplate,
|
||||||
|
injectStyles,
|
||||||
|
scopeId,
|
||||||
|
moduleIdentifier, /* server only */
|
||||||
|
shadowMode /* vue-cli only */
|
||||||
|
) {
|
||||||
|
// Vue.extend constructor export interop
|
||||||
|
var options = typeof scriptExports === 'function'
|
||||||
|
? scriptExports.options
|
||||||
|
: scriptExports
|
||||||
|
|
||||||
|
// render functions
|
||||||
|
if (render) {
|
||||||
|
options.render = render
|
||||||
|
options.staticRenderFns = staticRenderFns
|
||||||
|
options._compiled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// functional template
|
||||||
|
if (functionalTemplate) {
|
||||||
|
options.functional = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// scopedId
|
||||||
|
if (scopeId) {
|
||||||
|
options._scopeId = 'data-v-' + scopeId
|
||||||
|
}
|
||||||
|
|
||||||
|
var hook
|
||||||
|
if (moduleIdentifier) { // server build
|
||||||
|
hook = function (context) {
|
||||||
|
// 2.3 injection
|
||||||
|
context =
|
||||||
|
context || // cached call
|
||||||
|
(this.$vnode && this.$vnode.ssrContext) || // stateful
|
||||||
|
(this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional
|
||||||
|
// 2.2 with runInNewContext: true
|
||||||
|
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
|
||||||
|
context = __VUE_SSR_CONTEXT__
|
||||||
|
}
|
||||||
|
// inject component styles
|
||||||
|
if (injectStyles) {
|
||||||
|
injectStyles.call(this, context)
|
||||||
|
}
|
||||||
|
// register component module identifier for async chunk inferrence
|
||||||
|
if (context && context._registeredComponents) {
|
||||||
|
context._registeredComponents.add(moduleIdentifier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// used by ssr in case component is cached and beforeCreate
|
||||||
|
// never gets called
|
||||||
|
options._ssrRegister = hook
|
||||||
|
} else if (injectStyles) {
|
||||||
|
hook = shadowMode
|
||||||
|
? function () {
|
||||||
|
injectStyles.call(
|
||||||
|
this,
|
||||||
|
(options.functional ? this.parent : this).$root.$options.shadowRoot
|
||||||
|
)
|
||||||
|
}
|
||||||
|
: injectStyles
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hook) {
|
||||||
|
if (options.functional) {
|
||||||
|
// for template-only hot-reload because in that case the render fn doesn't
|
||||||
|
// go through the normalizer
|
||||||
|
options._injectStyles = hook
|
||||||
|
// register for functional component in vue file
|
||||||
|
var originalRender = options.render
|
||||||
|
options.render = function renderWithStyleInjection (h, context) {
|
||||||
|
hook.call(context)
|
||||||
|
return originalRender(h, context)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// inject component registration as beforeCreate hook
|
||||||
|
var existing = options.beforeCreate
|
||||||
|
options.beforeCreate = existing
|
||||||
|
? [].concat(existing, hook)
|
||||||
|
: [hook]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
exports: scriptExports,
|
||||||
|
options: options
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CONCATENATED MODULE: ./src/App.vue
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* normalize component */
|
||||||
|
|
||||||
|
var component = normalizeComponent(
|
||||||
|
src_Appvue_type_script_lang_js_,
|
||||||
|
render,
|
||||||
|
staticRenderFns,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
/* harmony default export */ var App = (component.exports);
|
||||||
|
// CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/entry-lib.js
|
||||||
|
|
||||||
|
|
||||||
|
/* harmony default export */ var entry_lib = __webpack_exports__["default"] = (App);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***/ })
|
||||||
|
|
||||||
|
/******/ })["default"];
|
||||||
|
});
|
||||||
|
//# sourceMappingURL=plugin-webrtc.umd.js.map
|
1
ui/dist/plugin-webrtc.umd.js.map
vendored
Normal file
1
ui/dist/plugin-webrtc.umd.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
ui/dist/plugin-webrtc.umd.min.js
vendored
Normal file
2
ui/dist/plugin-webrtc.umd.min.js
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
(function(e,t){"object"===typeof exports&&"object"===typeof module?module.exports=t():"function"===typeof define&&define.amd?define([],t):"object"===typeof exports?exports["plugin-webrtc"]=t():e["plugin-webrtc"]=t()})("undefined"!==typeof self?self:this,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s="fb15")}({8875:function(e,t,n){var r,o,i;(function(n,c){o=[],r=c,i="function"===typeof r?r.apply(t,o):r,void 0===i||(e.exports=i)})("undefined"!==typeof self&&self,(function(){function e(){if(document.currentScript)return document.currentScript;try{throw new Error}catch(l){var e,t,n,r=/.*at [^(]*\((.*):(.+):(.+)\)$/gi,o=/@([^@]*):(\d+):(\d+)\s*$/gi,i=r.exec(l.stack)||o.exec(l.stack),c=i&&i[1]||!1,s=i&&i[2]||!1,a=document.location.href.replace(document.location.hash,""),u=document.getElementsByTagName("script");c===a&&(e=document.documentElement.outerHTML,t=new RegExp("(?:[^\\n]+?\\n){0,"+(s-2)+"}[^<]*<script>([\\d\\D]*?)<\\/script>[\\d\\D]*","i"),n=e.replace(t,"$1").trim());for(var d=0;d<u.length;d++){if("interactive"===u[d].readyState)return u[d];if(u[d].src===c)return u[d];if(c===a&&u[d].innerHTML&&u[d].innerHTML.trim()===n)return u[d]}return null}}return e}))},fb15:function(e,t,n){"use strict";if(n.r(t),"undefined"!==typeof window){var r=window.document.currentScript,o=n("8875");r=o(),"currentScript"in document||Object.defineProperty(document,"currentScript",{get:o});var i=r&&r.src.match(/(.+\/)[^/]+\.js(\?.*)?$/);i&&(n.p=i[1])}var c=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",[e._v(" Browser base64 Session Description "),n("br"),n("textarea",{attrs:{readonly:"true"},domProps:{value:e.localDescription}}),n("br"),e._v("Golang base64 Session Description "),n("br"),n("textarea",{domProps:{value:e.remoteSessionDescription}}),n("br"),n("button",{on:{click:e.startSession}},[e._v("Start Session")]),n("br"),n("br"),e._v("Video "),n("br"),n("video",{attrs:{id:"video1",width:"160",height:"120",autoplay:"",muted:""},domProps:{muted:!0}}),n("br"),e._v("Logs "),n("br"),n("div",{attrs:{id:"logs"}})])},s=[];let a=new RTCPeerConnection({iceServers:[{urls:"stun:stun.l.google.com:19302"}]});var u={data(){return{localDescription:"",remoteSessionDescription:""}},methods:{startSession(){this.ajax.post("/webrtc/answer",this.localDescription).then(e=>{this.remoteSessionDescription=e,a.setRemoteDescription(new RTCSessionDescription(e))})}},mounted(){var e=e=>{document.getElementById("logs").innerHTML+=e+"<br>"};navigator.mediaDevices.getUserMedia({video:!0,audio:!0}).then(t=>{a.addStream(document.getElementById("video1").srcObject=t),a.createOffer().then(e=>a.setLocalDescription(e)).catch(e)}).catch(e),a.oniceconnectionstatechange=t=>e(a.iceConnectionState),a.onicecandidate=e=>{null===e.candidate&&(this.localDescription=JSON.stringify(a.localDescription))}}},d=u;function l(e,t,n,r,o,i,c,s){var a,u="function"===typeof e?e.options:e;if(t&&(u.render=t,u.staticRenderFns=n,u._compiled=!0),r&&(u.functional=!0),i&&(u._scopeId="data-v-"+i),c?(a=function(e){e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,e||"undefined"===typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),o&&o.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(c)},u._ssrRegister=a):o&&(a=s?function(){o.call(this,(u.functional?this.parent:this).$root.$options.shadowRoot)}:o),a)if(u.functional){u._injectStyles=a;var d=u.render;u.render=function(e,t){return a.call(t),d(e,t)}}else{var l=u.beforeCreate;u.beforeCreate=l?[].concat(l,a):[a]}return{exports:e,options:u}}var f=l(d,c,s,!1,null,null,null),p=f.exports;t["default"]=p}})["default"]}));
|
||||||
|
//# sourceMappingURL=plugin-webrtc.umd.min.js.map
|
1
ui/dist/plugin-webrtc.umd.min.js.map
vendored
Normal file
1
ui/dist/plugin-webrtc.umd.min.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
9392
ui/package-lock.json
generated
Normal file
9392
ui/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
15
ui/package.json
Normal file
15
ui/package.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "dashboard",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "dashboard of webrtc plugin for monibuca",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"build": "vue-cli-service build --target lib --name plugin-webrtc"
|
||||||
|
},
|
||||||
|
"author": "dexter",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"@vue/cli-service": "^4.2.3",
|
||||||
|
"vue-template-compiler": "^2.6.11"
|
||||||
|
}
|
||||||
|
}
|
72
ui/src/App.vue
Normal file
72
ui/src/App.vue
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
Browser base64 Session Description
|
||||||
|
<br />
|
||||||
|
<textarea readonly="true" :value="localDescription"></textarea>
|
||||||
|
<br />Golang base64 Session Description
|
||||||
|
<br />
|
||||||
|
<textarea :value="remoteSessionDescription"></textarea>
|
||||||
|
<br />
|
||||||
|
<button @click="startSession">Start Session</button>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<br />Video
|
||||||
|
<br />
|
||||||
|
<video id="video1" width="160" height="120" autoplay muted></video>
|
||||||
|
<br />Logs
|
||||||
|
<br />
|
||||||
|
<div id="logs"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let pc = new RTCPeerConnection({
|
||||||
|
iceServers: [
|
||||||
|
{
|
||||||
|
urls: "stun:stun.l.google.com:19302"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
localDescription: "",
|
||||||
|
remoteSessionDescription: ""
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
startSession() {
|
||||||
|
this.ajax.post("/webrtc/answer", this.localDescription).then(result => {
|
||||||
|
this.remoteSessionDescription = result;
|
||||||
|
pc.setRemoteDescription(new RTCSessionDescription(result));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
/* eslint-env browser */
|
||||||
|
var log = msg => {
|
||||||
|
document.getElementById("logs").innerHTML += msg + "<br>";
|
||||||
|
};
|
||||||
|
|
||||||
|
navigator.mediaDevices
|
||||||
|
.getUserMedia({ video: true, audio: true })
|
||||||
|
.then(stream => {
|
||||||
|
pc.addStream((document.getElementById("video1").srcObject = stream));
|
||||||
|
pc.createOffer()
|
||||||
|
.then(d => pc.setLocalDescription(d))
|
||||||
|
.catch(log);
|
||||||
|
})
|
||||||
|
.catch(log);
|
||||||
|
|
||||||
|
pc.oniceconnectionstatechange = e => log(pc.iceConnectionState);
|
||||||
|
pc.onicecandidate = event => {
|
||||||
|
if (event.candidate === null) {
|
||||||
|
this.localDescription = JSON.stringify(pc.localDescription);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
Reference in New Issue
Block a user