数据编码解码

This commit is contained in:
2023-09-30 00:13:30 +08:00
parent fbf11f113c
commit ef436f2e93
3 changed files with 79 additions and 81 deletions

View File

@ -47,7 +47,7 @@ export default class ClientList {
channel.onmessage = event => { channel.onmessage = event => {
//console.log('收到对方 datachannel message', event) //console.log('收到对方 datachannel message', event)
if (channels[event.target.label]) { if (channels[event.target.label]) {
channels[event.target.label].onmessage(event, channel) channels[event.target.label].onmessage(event, this.clientlist.find(x => x.id === data.id))
} }
} }
} }

View File

@ -36,86 +36,82 @@
const clientList = new ClientList({}) const clientList = new ClientList({})
clientList.setChannel('musicList', { clientList.setChannel('musicList', {
onopen: async event => { onopen: async event => {
const data = musicList.list.filter(item=>{ const data = musicList.list.filter(item => {
return !!item.arrayBuffer return !!item.arrayBuffer
}).map(({ arrayBuffer, ...item }) => item) }).map(({ arrayBuffer, ...item }) => item)
console.log('发送 musicList:', data) console.log('发送 musicList:', data)
event.target.send(JSON.stringify(data)) event.target.send(JSON.stringify(data))
}, },
onmessage: async event => { onmessage: async (event, client) => {
console.log('收到 musicList:', event) console.log('收到 musicList:', event)
const data = JSON.parse(event.data) const data = JSON.parse(event.data)
const ids = musicList.list.map(item => item.id) const ids = musicList.list.map(item => item.id)
data.filter(item=>!ids.includes(item.id)).forEach(item=>{ data.filter(item => !ids.includes(item.id)).forEach(item => {
musicList.add(item) musicList.add(item)
}) })
// 将数据设置到这个客户端
console.log('设置 musicList:', data)
console.log('设置 musicList:', event)
console.log('当前客户端', client)
client.musicList = data
}
})
clientList.setChannel('musicload', {
onopen: async event => {
// 连接打开时要求发送某一条音乐数据?
//console.log('发送 musicload')
//const buffer = new ArrayBuffer(8)
//const json = { name: 'John', age: 30 }
//const jsonString = JSON.stringify(json)
//const jsonBuffer = new TextEncoder().encode(jsonString).buffer
//const lengthBuffer = new ArrayBuffer(8)
//const lengthView = new DataView(lengthBuffer)
//lengthView.setUint32(0, jsonBuffer.byteLength)
//const mergedBuffer = new ArrayBuffer(lengthBuffer.byteLength + jsonBuffer.byteLength + buffer.byteLength)
//const mergedView = new Uint8Array(mergedBuffer)
//mergedView.set(new Uint8Array(lengthBuffer), 0)
//mergedView.set(new Uint8Array(jsonBuffer), lengthBuffer.byteLength)
//mergedView.set(new Uint8Array(buffer), lengthBuffer.byteLength + jsonBuffer.byteLength)
//event.target.send(mergedBuffer)
},
onmessage: async event => {
console.log('收到 musicload')
const view = new DataView(event.data)
const len = new ArrayBuffer(8)
// 解析出原始数据, 更简洁的方式
const lengthBuffer = event.data.slice(0, len.byteLength)
const lengthView = new DataView(lengthBuffer)
console.log('getUint32', lengthView.getUint32(0))
const jsonBuffer = event.data.slice(len.byteLength, len.byteLength + lengthView.getUint32(0))
const jsonView = new DataView(jsonBuffer)
console.log('json', JSON.parse(new TextDecoder().decode(jsonBuffer)))
const buffer = event.data.slice(len.byteLength + lengthView.getUint32(0))
console.log('buffer', buffer)
} }
}) })
//// 初始化客户端列表 musicList.on('load', item => {
//const clientList = new ClientList({ console.log('从来源加载音乐', item)
// channels: { // 选择一个含有此音乐的客户端
// 'musicList': { const client = clientList.clientlist.find(client => {
// onopen: async (event, channel) => { console.log('client:', client)
// const list = await musicList.list if (!client.musicList) client.musicList = []
// console.log('发送 musicList:', list) return client.musicList.some(music => music.id === item.id)
// channel.send(JSON.stringify(list.map(({ arrayBuffer, ...data }) => data))) })
// }, if (!client) return console.log('没有找到含有此音乐的客户端')
// onmessage: async (event, channel) => { console.log('找到含有此音乐的客户端', client)
// console.log('收到 musicList:', event)
// JSON.parse(event.data).forEach(item => {
// musicList.push(item)
// })
// }
// },
// 'musicload': {
// onopen: async (event, channel) => {
// console.log('发送 musicload:', event)
// },
// onmessage: async (event, channel) => {
// console.log('收到 musicload:', event)
// }
// }
// }
//})
// 通过指定通道发送消息
// 接收处理各种通道消息
// 延迟2秒执行
//await new Promise(resolve => setTimeout(resolve, 2000))
//// 设定被动传输
//clientList.clientlist.forEach(client => {
// console.log('client:', client)
// client.webrtc.addEventListener('datachannel', event => {
// console.log('收到 datachannel:', event)
// event.channel.addEventListener('message', event => {
// console.log('收到消息:', event)
// })
// })
//})
//musicList.on('load', item => { //clientList.send('musicList', JSON.stringify([item]))
// console.log('从来源加载音乐', item) })
// clientList.send('musicList', JSON.stringify([item]))
//})
// 在什么时机发送musicList?
// 通道准备好时即可发送
// 获取对方的音乐列表 // 获取对方的音乐列表
// like对方的条目时亮起(双方高亮)(本地缓存)(可由对比缓存实现) // like对方的条目时亮起(双方高亮)(本地缓存)(可由对比缓存实现)
// ban对方的条目时灰掉(也禁止对方播放)(并保持ban表)(由插件实现) // ban对方的条目时灰掉(也禁止对方播放)(并保持ban表)(由插件实现)
//clientList.on('channel')
// 只需要在注册时拉取列表, 播放时才需要拉取音乐数据 // 只需要在注册时拉取列表, 播放时才需要拉取音乐数据
</script>
// 先拉取所有对方的音乐列表, 对比去重, 拉取音乐数据 <!--script type="module">
// 主动发送自己的音乐列表, 对比去重, 发送音乐数据
//clientList.on('list', async client => {
// console.log('push:', client)
// const musicList = await clientList.send('music-list', '23333')
// console.log('musicList:', musicList)
//})
// webRTC 传递音乐(分别传输文件和操作事件能更流畅) // webRTC 传递音乐(分别传输文件和操作事件能更流畅)
const music = async function () { const music = async function () {
@ -234,7 +230,7 @@
} }
} }
//music() //music()
</script> </script-->
<!--script type="module"> <!--script type="module">
// 创建 RTCPeerConnection // 创建 RTCPeerConnection
const pc = new RTCPeerConnection() const pc = new RTCPeerConnection()
@ -253,7 +249,7 @@
pc.setRemoteDescription(new RTCSessionDescription(data.offer)) pc.setRemoteDescription(new RTCSessionDescription(data.offer))
// 创建SDP answer并将其设置为本地描述, 发送给远程端 // 创建SDP answer并将其设置为本地描述, 发送给远程端
pc.createAnswer().then(function (answer) { pc.createAnswer().then(function (answer) {
pc.setLocalDescription(answer); pc.setLocalDescription(answer)
ws.send(JSON.stringify({ answer })) ws.send(JSON.stringify({ answer }))
}) })
return return
@ -277,16 +273,16 @@
// 获取本地视频流 // 获取本地视频流
navigator.mediaDevices.getUserMedia({ audio: false, video: true }).then(stream => { navigator.mediaDevices.getUserMedia({ audio: false, video: true }).then(stream => {
// 创建本地视频元素 // 创建本地视频元素
const localVideo = document.createElement('video'); const localVideo = document.createElement('video')
localVideo.srcObject = stream; localVideo.srcObject = stream
localVideo.autoplay = true; localVideo.autoplay = true
localVideo.muted = true; localVideo.muted = true
document.body.appendChild(localVideo); document.body.appendChild(localVideo)
// 添加本地视频流到 RTCPeerConnection // 添加本地视频流到 RTCPeerConnection
stream.getTracks().forEach(function (track) { stream.getTracks().forEach(function (track) {
pc.addTrack(track, stream); pc.addTrack(track, stream)
}); })
// 监听 ICE candidate 事件 // 监听 ICE candidate 事件
pc.onicecandidate = function (event) { pc.onicecandidate = function (event) {
@ -294,20 +290,20 @@
// 发送 ICE candidate 到远程端 // 发送 ICE candidate 到远程端
ws.send(JSON.stringify({ candidate: event.candidate })) ws.send(JSON.stringify({ candidate: event.candidate }))
} }
}; }
// 监听远程视频流事件 // 监听远程视频流事件
pc.ontrack = function (event) { pc.ontrack = function (event) {
// 创建远程视频元素 // 创建远程视频元素
var remoteVideo = document.createElement('video'); var remoteVideo = document.createElement('video')
remoteVideo.srcObject = event.streams[0]; remoteVideo.srcObject = event.streams[0]
remoteVideo.autoplay = true; remoteVideo.autoplay = true
document.body.appendChild(remoteVideo); document.body.appendChild(remoteVideo)
} }
// 创建SDP offer并将其设置为本地描述, 发送给远程端 // 创建SDP offer并将其设置为本地描述, 发送给远程端
pc.createOffer().then(function (offer) { pc.createOffer().then(function (offer) {
pc.setLocalDescription(offer); pc.setLocalDescription(offer)
ws.send(JSON.stringify({ offer })) ws.send(JSON.stringify({ offer }))
}) })

View File

@ -1,4 +1,3 @@
import IndexedDB from './database.js'
import { Button, List, ListItem } from './weigets.js' import { Button, List, ListItem } from './weigets.js'
export default class MusicList { export default class MusicList {
@ -93,12 +92,15 @@ export default class MusicList {
this.EventListeners['remove'](item) this.EventListeners['remove'](item)
} }
} }
async load(item) {
// 执行回调函数(应当异步)
if (this.EventListeners['load']) {
await this.EventListeners['load'](item)
}
}
async play(item) { async play(item) {
// 如果没有arrayBuffer则从对方获取
console.log('play:', item)
if (!item.arrayBuffer) { if (!item.arrayBuffer) {
console.log('从对方获取:', item) await this.load(item)
return
} }
this.audio.src = URL.createObjectURL(new Blob([item.arrayBuffer], { type: item.type })) this.audio.src = URL.createObjectURL(new Blob([item.arrayBuffer], { type: item.type }))
this.audio.play() this.audio.play()