mirror of
https://github.com/Monibuca/plugin-webrtc.git
synced 2025-10-05 23:06:55 +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