From 4f7741b34168e7dd34ea2fa61ffe4a58b60c64ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A7=89?= Date: Thu, 28 Sep 2023 23:49:26 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=B9=E7=AB=AF=E9=80=9A=E4=BF=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.js | 8 +-- public/client.js | 110 ++++++++++++++++++++++++++++++++++++++++++ public/database.js | 1 - public/index.html | 118 +++++++++++++++++++++------------------------ public/music.js | 13 +++-- 5 files changed, 177 insertions(+), 73 deletions(-) create mode 100644 public/client.js diff --git a/index.js b/index.js index e061d8c..4bc4ab3 100644 --- a/index.js +++ b/index.js @@ -31,10 +31,10 @@ app.ws('/webrtc/:channel', (ws, req) => { // 设备发送信令时转发给指定在线设备 ws.on('message', message => { console.log(ws.id, '设备发送信令:', ws.channel, wsInstance.getWss().clients.size) - const { id } = JSON.parse(message) + const data = JSON.parse(message) wsInstance.getWss().clients.forEach(client => { - if (client !== ws && client.readyState === 1 && client.channel === ws.channel && client.id === id) { - client.send(message) + if (client !== ws && client.readyState === 1 && client.channel === ws.channel && client.id === data.id) { + client.send(JSON.stringify({ ...data, id: ws.id })) } }) }) @@ -43,7 +43,7 @@ app.ws('/webrtc/:channel', (ws, req) => { wsInstance.getWss().clients.forEach(client => { if (client !== ws && client.readyState === 1 && client.channel === ws.channel) { client.send(JSON.stringify({ type: 'push', id: ws.id, channel: ws.channel })) - ws.send(JSON.stringify({ type: 'push', id: client.id, channel: client.channel })) + ws.send(JSON.stringify({ type: 'list', id: client.id, channel: client.channel })) } }) }) diff --git a/public/client.js b/public/client.js new file mode 100644 index 0000000..f49727f --- /dev/null +++ b/public/client.js @@ -0,0 +1,110 @@ +import { List, ListItem } from './weigets.js' + +export default class ClientList { + constructor() { + const protocol = window.location.protocol === 'https:' ? 'wss' : 'ws' + const host = window.location.host + this.websocket = new WebSocket(`${protocol}://${host}/webrtc/music`) + this.clientlist = [] + this.ul = List({}) + document.body.appendChild(this.ul) + //this.websocket.onopen = event => { + // console.log('clientlist websocket: onopen') + // console.log('当连接建立时,服务器将逐一发送所有客户端信息') + //} + this.websocket.onmessage = async event => { + const data = JSON.parse(event.data) + if (data.type === 'list') { + console.log('取得在线对端列表:', data) + const webrtc = new RTCPeerConnection() + webrtc.createDataChannel('music') + //webrtc.onicecandidate = event => { + // console.log('clientlist onicecandidate E', event) + // if (event.candidate) { + // this.websocket.send(JSON.stringify({ type: 'candidate', id: data.id, candidate: event.candidate })) + // } + //} + console.log('发送给对方 offer') + const offer = await webrtc.createOffer() + await webrtc.setLocalDescription(offer) + this.clientlist.push({ id: data.id, name: data.name, webrtc }) + this.websocket.send(JSON.stringify({ type: 'offer', id: data.id, offer })) + return this.add(data) + } + if (data.type === 'push') { + console.log('新上线客户端:', data) + return this.add(data) + } + if (data.type === 'pull') { + console.log('移除客户端:', data) + return this.remove(data) + } + if (data.type === 'offer') { + console.log('收到对方 offer', data) + const webrtc = new RTCPeerConnection() + webrtc.createDataChannel('music') + //webrtc.onicecandidate = event => { + // console.log('clientlist onicecandidate X', event) + // if (event.candidate) { + // this.websocket.send(JSON.stringify({ type: 'candidate', id: data.id, candidate: event.candidate })) + // } + //} + this.clientlist.push({ id: data.id, name: data.name, webrtc }) + console.log('发送给对方 answer') + await webrtc.setRemoteDescription(data.offer) + const answer = await webrtc.createAnswer() + await webrtc.setLocalDescription(answer) + this.websocket.send(JSON.stringify({ type: 'answer', id: data.id, answer })) + return + } + if (data.type === 'answer') { + console.log('收到对方 answer', data) + const pc = this.clientlist.find(client => client.id === data.id).webrtc + await pc.setRemoteDescription(data.answer) + return + } + if (data.type === 'candidate') { + const pc = this.clientlist.find(client => client.id === data.id).webrtc + await pc.addIceCandidate(data.candidate) + return console.log('收到 candidate 并将其添加到远程端', data.candidate) + } + console.log('收到未知数据:', data) + } + } + add(item) { + //this.clientlist.push(item) + this.ul.appendChild(ListItem({ + id: item.id, + innerText: item.name ?? item.id, + onclick: event => { + }, + chidren: [] + })) + //// 与对方建立连接(即使不传输数据) + //const webrtc = new RTCPeerConnection() + //const channel = webrtc.createDataChannel('music') + //channel.onopen = event => { + // console.log('clientlist music: channel.onopen') + // channel.send('hello') + //} + //channel.onmessage = event => { + // console.log('clientlist music: channel.onmessage', event.data) + //} + //// 监听 ICE 候选事件 + //webrtc.onicecandidate = event => { + // if (event.candidate) { + // console.log('clientlist onicecandidate', event.candidate) + // // 发送给对方(通过服务器) + // } + //} + } + remove(item) { + this.clientlist = this.clientlist.filter(client => client.id !== item.id) + this.ul.removeChild(document.getElementById(item.id)) + } + update(item) { } + get(id) { } + getAll() { } + clear() { } + on(event, callback) { } +} diff --git a/public/database.js b/public/database.js index a835daa..aae99f4 100644 --- a/public/database.js +++ b/public/database.js @@ -15,7 +15,6 @@ export default class IndexedDB { } open() { - console.log('open') return new Promise((resolve, reject) => { const request = indexedDB.open(this.databaseName, this.databaseVersion) request.onerror = (event) => { diff --git a/public/index.html b/public/index.html index e2feb84..9a5a70b 100644 --- a/public/index.html +++ b/public/index.html @@ -9,24 +9,64 @@

webRTC

-

message

+

选择音乐使频道内所有设备同步播放