<add>实现转发弹幕功能

This commit is contained in:
skmcj committed 2025-04-28 16:26:43 +08:00
1 parent bdea9bf1b6
commit 7cf2a9f8ad
3 files changed
+166 -2

No files matched your search

+11
View File
@@ -60,6 +60,7 @@ export interface LiveRoom {
/** 直播间信息-连接信息 */
export interface DyLiveInfo {
roomNum?: string;
roomId: string;
uniqueId: string;
avatar: string;
@@ -1121,4 +1122,14 @@ export class DyCast {
msg
};
}
/**
* 获取直播间信息
*/
public getLiveInfo(): DyLiveInfo {
return {
...this.info,
roomNum: this.roomNum
};
}
}
+105
View File
@@ -0,0 +1,105 @@
import { Emitter, type EventMap } from './emitter';
interface RelayCastEvent extends EventMap {
open: (ev: Event) => void;
close: (code?: number, msg?: string) => void;
error: (ev: Error) => void;
message: (data: any) => void;
}
/**
* 弹幕转发器
* - 简单封装一下,有问题再优化
*/
export class RelayCast {
private url: string;
private ws: WebSocket | undefined;
private emitter: Emitter<RelayCastEvent>;
constructor(url: string) {
this.url = url;
this.emitter = new Emitter();
}
/**
* 监听
* @param event
* @param listener
*/
public on<K extends keyof RelayCastEvent>(event: K, listener: RelayCastEvent[K]) {
this.emitter.on(event, listener);
}
/**
* 取消监听
* @param event
* @param listener
*/
public off<K extends keyof RelayCastEvent>(event: K, listener: RelayCastEvent[K]) {
this.emitter.off(event, listener);
}
/**
* 一次性监听
* - 如监听打开关闭
* @param event
* @param listener
*/
public once<K extends keyof RelayCastEvent>(event: K, listener: RelayCastEvent[K]) {
this.emitter.once(event, listener);
}
/**
* 连接
*/
connect() {
try {
this.ws = new WebSocket(this.url);
this.ws.addEventListener('open', ev => {
this.emitter.emit('open', ev);
});
this.ws.addEventListener('close', ev => {
this.emitter.emit('close', ev.code, ev.type);
});
this.ws.addEventListener('error', ev => {
this.emitter.emit('error', Error(ev.type));
});
this.ws.addEventListener('message', ev => {
this.emitter.emit('message', ev.data);
});
} catch (err) {
this.emitter.emit('error', Error('转发服务器连接出错'));
this.emitter.emit('close', 4002);
}
}
/**
* 是否连接
*/
isConnected() {
if (this.ws) return this.ws.readyState === WebSocket.OPEN;
else return false;
}
/**
* 发送消息
* @param data
*/
send(data: string | ArrayBuffer) {
if (this.ws && this.ws.readyState === WebSocket.OPEN) this.ws.send(data);
}
/**
* 关闭转发
* @param code
* @param msg
*/
close(code: number = 1000, msg: string = 'close replay') {
if (this.ws) {
this.ws.close(code, msg);
this.ws = void 0;
}
}
}
+50 -2
View File
@@ -67,6 +67,7 @@ import { verifyRoomNum, verifyWsUrl } from '@/utils/verifyUtil';
import { ref, useTemplateRef } from 'vue';
import { CLog } from '@/utils/logUtil';
import { getId } from '@/utils/idUtil';
import { RelayCast } from '@/core/relay';
// 连接状态
const connectStatus = ref<ConnectStatus>(0);
// 转发状态
@@ -101,6 +102,8 @@ const allCasts: DyMessage[] = [];
const castSet = new Set<string>();
// 弹幕客户端
let castWs: DyCast | undefined;
// 转发客户端
let relayWs: RelayCast | undefined;
/**
* 验证房间号
@@ -215,6 +218,9 @@ const handleMessages = function (msgs: DyMessage[]) {
allCasts.push(...newCasts);
if (castRef.value) castRef.value.appendCasts(mainCasts);
if (otherRef.value) otherRef.value.appendCasts(otherCasts);
if (relayWs && relayWs.isConnected()) {
relayWs.send(JSON.stringify(msgs));
}
};
/**
@@ -251,6 +257,7 @@ const connectLive = function () {
// 清空上一次连接的消息
clearMessageList();
CLog.debug('正在连接:', roomNum.value);
SkMessage.info(`正在连接:${roomNum.value}`);
const cast = new DyCast(roomNum.value);
cast.on('open', (ev, info) => {
CLog.info('DyCast 房间连接成功');
@@ -323,9 +330,50 @@ const disconnectLive = function () {
};
/** 连接转发房间 */
const relayCast = function () {};
const relayCast = function () {
try {
CLog.info('正在连接转发中 =>', relayUrl.value);
SkMessage.info(`转发连接中: ${relayUrl.value}`);
const cast = new RelayCast(relayUrl.value);
cast.on('open', () => {
CLog.info(`DyCast 转发连接成功`);
SkMessage.success(`已开始转发`);
relayInputStatus.value = true;
relayStatus.value = 1;
addConsoleMessage('转发客户端已连接');
if (castWs) {
// 发送直播间信息给转发地址
cast.send(JSON.stringify(castWs.getLiveInfo()));
}
});
cast.on('close', (code, msg) => {
CLog.info(`(${code})dycast 转发已关闭: ${msg || '未知原因'}`);
if (code === 1000) SkMessage.info(`已停止转发`);
else SkMessage.warning(`转发已停止: ${msg || '未知原因'}`);
relayInputStatus.value = false;
relayStatus.value = 0;
addConsoleMessage('转发已关闭');
});
cast.on('error', ev => {
CLog.warn(`dycast 转发出错: ${ev.message}`);
SkMessage.error(`转发出错了: ${ev.message}`);
relayInputStatus.value = false;
relayStatus.value = 2;
});
cast.connect();
relayWs = cast;
} catch (err) {
CLog.error('弹幕转发出错:', err);
SkMessage.error('转发出错: ${err.message}');
relayInputStatus.value = false;
relayStatus.value = 2;
relayWs = void 0;
}
};
/** 暂停转发 */
const stopRelayCast = function () {};
const stopRelayCast = function () {
if (relayWs) relayWs.close(1000);
};
</script>
<style lang="scss" scoped>