浏览代码

Annoyed

master
Roderic Day 5 年前
父节点
当前提交
efda1bf323
共有 2 个文件被更改,包括 82 次插入12 次删除
  1. +80
    -8
      apps/streams.js
  2. +2
    -4
      pico.js

+ 80
- 8
apps/streams.js 查看文件

videoOn: true, videoOn: true,
audioOn: true, audioOn: true,
get video() { get video() {
return VideoConfig.videoOn && {width: {ideal: 320}, facingMode: 'user', frameRate: 26}
return VideoConfig.videoOn
&& {width: {ideal: 320}, facingMode: 'user', frameRate: 26}
}, },
get audio() { get audio() {
return VideoConfig.audioOn return VideoConfig.audioOn
} }
}) })
const VideoSelf = { const VideoSelf = {
update() {
const stream = document.querySelector('video.self').srcObject
stream.getTracks().forEach(track => {
async update() {
const video = document.querySelector('video.self')
video.srcObject.getTracks().forEach(track => {
track.stop() track.stop()
stream.removeTrack(track)
video.srcObject.removeTrack(track)
delete track delete track
}) })
stream = new MediaStream()
if(VideoConfig.videoOn || VideoConfig.audioOn) { if(VideoConfig.videoOn || VideoConfig.audioOn) {
navigator.mediaDevices
await navigator.mediaDevices
.getUserMedia(VideoConfig) .getUserMedia(VideoConfig)
.then(s => s.getTracks().forEach(t => stream.addTrack(t))) .then(s => s.getTracks().forEach(t => stream.addTrack(t)))
.catch(e => console.error(e)) .catch(e => console.error(e))
} }
video.srcObject = stream
wire({kind: 'peerInfo', value: {type: 'request'}})
}, },
setUp: ({dom}) => { setUp: ({dom}) => {
dom.playsinline = true dom.playsinline = true
}, },
} }
const VideoOther = { const VideoOther = {
setUp: ({dom}) => {
setUp: (username) => ({dom}) => {
dom.playsinline = true dom.playsinline = true
dom.autoplay = true dom.autoplay = true
dom.srcObject = new MediaStream() dom.srcObject = new MediaStream()
let rpc = null

const rpcConfig = {iceServers: [{urls: 'stun:stun.sipgate.net:3478'}]}

const stopRpc = () => {
rpc && rpc.close()
dom.srcObject.getTracks().forEach(track => {
track.stop()
dom.srcObject.removeTrack(track)
delete track
})
}

const resetRpc = () => {
stopRpc()
rpc = new RTCPeerConnection(rpcConfig)
dom.srcObject = new MediaStream()
document.querySelector('video.self').srcObject.getTracks()
.forEach(t => rpc.addTrack(t))

rpc.onicecandidate = ({candidate}) => {
if(candidate && candidate.candidate) {
wire({kind: 'peerInfo', value: {type: 'candidate', candidate}, target: username})
}
}
rpc.ontrack = ({track}) => {
dom.srcObject.addTrack(track)
}
}

const onPeerInfo = async ({detail: {source, value}}) => {
if(source !== username) {
return
}
console.log(source, value.type)
if(value.type === 'request') {
resetRpc()
const localOffer = await rpc.createOffer()
await rpc.setLocalDescription(localOffer)
wire({kind: 'peerInfo', value: localOffer, target: username})
}
else if(value.type === 'offer') {
resetRpc()
const remoteOffer = new RTCSessionDescription(value)
await rpc.setRemoteDescription(remoteOffer)
const localAnswer = await rpc.createAnswer()
await rpc.setLocalDescription(localAnswer)
wire({kind: 'peerInfo', value: localAnswer, target: username})
}
else if(value.type === 'answer') {
const remoteAnswer = new RTCSessionDescription(value)
await rpc.setRemoteDescription(remoteAnswer)
}
else if(value.type === 'candidate') {
const candidate = new RTCIceCandidate(value.candidate)
await rpc.addIceCandidate(candidate)
}
else if(value.type === 'stop') {
stopRpc()
}
}

addEventListener('peerInfo', onPeerInfo)
}, },
view({attrs: {username}}) { view({attrs: {username}}) {
const styleOuter = { const styleOuter = {
m('.video-info', {style: {position: 'absolute', zIndex: 999}}, m('.video-info', {style: {position: 'absolute', zIndex: 999}},
m('span', {style: {padding: '5px'}}, username), m('span', {style: {padding: '5px'}}, username),
), ),
m('video.self', {style: styleInner, oncreate: this.setUp}),
m('video', {style: styleInner, oncreate: this.setUp(username)}),
) )
}, },
} }
const StreamContainer = { const StreamContainer = {
// screen.width, screen.height
getColumns() { getColumns() {
const n = State.online.length const n = State.online.length
if(n > 4) return '1fr 1fr 1fr' if(n > 4) return '1fr 1fr 1fr'
) )
}, },
} }

const signalPeerStop = (username) => signal({kind: 'peerInfo', value: {type: 'stop'}, source: username})
addEventListener('pagehide', () => State.online.forEach(signalPeerStop))
addEventListener('logout', () => State.online.forEach(signalPeerStop))

+ 2
- 4
pico.js 查看文件

*/ */
const wire = (message) => State.websocket.send(JSON.stringify(message)) const wire = (message) => State.websocket.send(JSON.stringify(message))
const signal = (message) => dispatchEvent(new CustomEvent(message.kind, {detail: message})) const signal = (message) => dispatchEvent(new CustomEvent(message.kind, {detail: message}))
const signalPeerRequest = () => wire({kind: 'peerInfo', value: {type: 'request'}})
const signalPeerStop = (username) => signal({kind: 'peerInfo', value: {type: 'stop'}, source: username})
const listen = (kind, handler) => { const listen = (kind, handler) => {
addEventListener(kind, handler) addEventListener(kind, handler)
} }
), ),
m('.error', State.info), m('.error', State.info),
), ),
m(StreamContainer),
State.isConnected ? m(StreamContainer) : null,
) )
}, },
} }
} }


if(!doNotLog.has(message.kind)) { if(!doNotLog.has(message.kind)) {
console.log(message)
console.log('@', message)
} }
signal(message) signal(message)



正在加载...
取消
保存