| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- const JSWebrtc = {
- Player: null,
- CreateVideoElements: function() {
- var elements = document.querySelectorAll('.jswebrtc')
- for (var i = 0; i < elements.length; i++) {
- new JSWebrtc.VideoElement(elements[i])
- }
- },
- FillQuery: function(query_string, obj) {
- obj.user_query = {}
- if (query_string.length === 0) return
- if (query_string.indexOf('?') >= 0) query_string = query_string.split('?')[1]
- var queries = query_string.split('&')
- for (var i = 0; i < queries.length; i++) {
- var query = queries[i].split('=')
- obj[query[0]] = query[1]
- obj.user_query[query[0]] = query[1]
- }
- if (obj.domain) obj.vhost = obj.domain
- },
- ParseUrl: function(rtmp_url) {
- var a = document.createElement('a')
- a.href = rtmp_url
- .replace('rtmp://', 'http://')
- .replace('webrtc://', 'http://')
- .replace('rtc://', 'http://')
- var vhost = a.hostname
- var app = a.pathname.substr(1, a.pathname.lastIndexOf('/') - 1)
- var stream = a.pathname.substr(a.pathname.lastIndexOf('/') + 1)
- app = app.replace('...vhost...', '?vhost=')
- if (app.indexOf('?') >= 0) {
- var params = app.substr(app.indexOf('?'))
- app = app.substr(0, app.indexOf('?'))
- if (params.indexOf('vhost=') > 0) {
- vhost = params.substr(params.indexOf('vhost=') + 'vhost='.length)
- if (vhost.indexOf('&') > 0) {
- vhost = vhost.substr(0, vhost.indexOf('&'))
- }
- }
- }
- if (a.hostname === vhost) {
- var re = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/
- if (re.test(a.hostname)) vhost = '__defaultVhost__'
- }
- var schema = 'rtmp'
- if (rtmp_url.indexOf('://') > 0) schema = rtmp_url.substr(0, rtmp_url.indexOf('://'))
- var port = a.port
- if (!port) {
- if (schema === 'http') {
- port = 80
- } else if (schema === 'https') {
- port = 443
- } else if (schema === 'rtmp') {
- port = 1935
- } else if (schema === 'webrtc' || schema === 'rtc') {
- port = 1985
- }
- }
- var ret = {
- url: rtmp_url,
- schema: schema,
- server: a.hostname,
- port: port,
- vhost: vhost,
- app: app,
- stream: stream
- }
- JSWebrtc.FillQuery(a.search, ret)
- return ret
- },
- HttpPost: function(url, data) {
- return new Promise(function(resolve, reject) {
- var xhr = new XMLHttpRequest()
- xhr.onreadystatechange = function() {
- if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status < 300) {
- var respone = JSON.parse(xhr.responseText)
- xhr.onreadystatechange = new Function()
- xhr = null
- resolve(respone)
- }
- }
- xhr.open('POST', url, true)
- xhr.timeout = 5e3
- xhr.responseType = 'text'
- xhr.setRequestHeader('Content-Type', 'application/json')
- xhr.send(data)
- })
- },
- httpGet: function(url) {
- return new Promise(function(resolve, reject) {
- var xhr = new XMLHttpRequest()
- xhr.onreadystatechange = function() {
- if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status < 300) {
- var respone = JSON.parse(xhr.responseText)
- xhr.onreadystatechange = new Function()
- xhr = null
- resolve(respone)
- }
- }
- xhr.open('GET', url, true)
- xhr.timeout = 1000
- xhr.setRequestHeader('Content-Type', 'application/json')
- xhr.send(null)
- })
- }
- }
- JSWebrtc.Player = (function() {
- 'use strict'
- class Player {
- constructor(url, options) {
- this.options = options || {}
- if (!url.match(/^webrtc?:\/\//)) {
- // eslint-disable-next-line no-throw-literal
- throw 'JSWebrtc just work with webrtc'
- }
- if (!this.options.video) {
- // eslint-disable-next-line no-throw-literal
- throw 'VideoElement is null'
- }
- this.urlParams = JSWebrtc.ParseUrl(url)
- this.pc = null
- this.autoplay = !!options.autoplay || false
- this.paused = true
- if (this.autoplay) this.options.video.muted = true
- this.startLoading()
- }
- startLoading() {
- var _self = this
- if (_self.pc) {
- _self.pc.close()
- }
- _self.pc = new RTCPeerConnection(null)
- _self.pc.ontrack = function(event) {
- _self.options.video['srcObject'] = event.streams[0]
- }
- _self.pc.addTransceiver('audio', {
- direction: 'recvonly'
- })
- _self.pc.addTransceiver('video', {
- direction: 'recvonly'
- })
- _self.pc
- .createOffer()
- .then(async function(offer) {
- await _self.pc.setLocalDescription(offer)
- return offer
- })
- .then(function(offer) {
- return new Promise(function(resolve, reject) {
- var port = _self.urlParams.port || 1985
- var api = _self.urlParams.user_query.play || '/rtc/v1/play/'
- if (api.lastIndexOf('/') !== api.length - 1) {
- api += '/'
- }
- var url = 'http://' + _self.urlParams.server + ':' + port + api
- for (var key in _self.urlParams.user_query) {
- if (key !== 'api' && key !== 'play') {
- url += '&' + key + '=' + _self.urlParams.user_query[key]
- }
- }
- var data = {
- api: url,
- streamurl: _self.urlParams.url,
- clientip: null,
- sdp: offer.sdp
- }
- JSWebrtc.HttpPost(url, JSON.stringify(data)).then(
- function(res) {
- resolve(res.sdp)
- },
- function(rej) {
- reject(rej)
- }
- )
- })
- })
- .then(function(answer) {
- return _self.pc.setRemoteDescription(
- new RTCSessionDescription({
- type: 'answer',
- sdp: answer
- })
- )
- })
- .catch(function(reason) {
- throw reason
- })
- if (this.autoplay) {
- this.play()
- }
- }
- play(ev) {
- if (this.animationId) {
- return
- }
- this.animationId = requestAnimationFrame(this.update.bind(this))
- this.paused = false
- }
- pause(ev) {
- if (this.paused) {
- return
- }
- cancelAnimationFrame(this.animationId)
- this.animationId = null
- this.isPlaying = false
- this.paused = true
- this.options.video.pause()
- if (this.options.onPause) {
- this.options.onPause(this)
- }
- }
- stop(ev) {
- this.pause()
- }
- destroy() {
- this.pause()
- this.pc && this.pc.close() && this.pc.destroy()
- this.audioOut && this.audioOut.destroy()
- }
- update() {
- this.animationId = requestAnimationFrame(this.update.bind(this))
- if (this.options.video.readyState < 4) {
- return
- }
- if (!this.isPlaying) {
- this.isPlaying = true
- this.options.video.play()
- if (this.options.onPlay) {
- this.options.onPlay(this)
- }
- }
- }
- }
- return Player
- })()
- export default JSWebrtc
|