123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- import { defineStore } from "pinia";
- import { MSG_TYPE, MESSAGE_TYPE_USER, MESSAGE_TYPE_GROUP } from "@/common/constant/msgType";
- import { useWebSocketStore } from "@/stores/modules/webSocketStore";
- export const useWebRTCStore = defineStore("webrtc", {
- state: () => ({
- // WebRTC 连接实例
- peerConnection: null,
- // ICE 候选信息
- iceCandidates: [],
- // 连接状态
- connectionState: "disconnected",
- // 媒体流
- localStream: null,
- remoteStream: null,
- // 配置项
- config: {
- iceServers: [
- { urls: "stun:stun.l.google.com:19302" },
- // 可以添加更多 STUN/TURN 服务器
- ],
- },
- }),
- actions: {
- // 初始化 WebRTC 连接
- initConnection(MESSAGE_TYPE) {
- this.cleanup();
- const wsStore = useWebSocketStore();
- try {
- this.peerConnection = new RTCPeerConnection();
- // 设置事件监听: 对等方收到ice信息后,通过调用 addIceCandidate 将接收的候选者信息传递给浏览器的ICE代理
- this.peerConnection.onicecandidate = (event) => {
- if (event.candidate) {
- if (MESSAGE_TYPE === MESSAGE_TYPE_USER) {
- let candidate = {
- type: "offer_ice",
- iceCandidate: event.candidate,
- };
- wsStore.sendMessage({
- contentType: MSG_TYPE.AUDIO_ONLINE,
- type: "webrtc",
- messageType: MESSAGE_TYPE,
- content: JSON.stringify(candidate),
- });
- }
- if (MESSAGE_TYPE === MESSAGE_TYPE_GROUP) {
- this.iceCandidates.push(event.candidate);
- }
- }
- };
- // 监听 ICE 状态变化
- this.peerConnection.onconnectionstatechange = () => {
- this.connectionState = this.peerConnection.connectionState;
- };
- // 当连接成功后,从里面获取语音视频流: 监听 ICE candidate:包含语音视频流
- this.peerConnection.ontrack = (event) => {
- // 添加远程媒体流
- if (!this.remoteStream) {
- this.remoteStream = new MediaStream();
- }
- // 添加远程媒体流
- event.streams[0].getTracks().forEach((track) => {
- this.remoteStream.addTrack(track);
- });
- };
- console.log("WebRTC 连接初始化成功");
- } catch (error) {
- console.error("初始化 WebRTC 连接失败:", error);
- this.cleanup();
- throw error;
- }
- },
- // 添加本地媒体流
- async addLocalStream(stream) {
- if (!this.peerConnection) {
- throw new Error("WebRTC 连接未初始化");
- }
- this.localStream = stream;
- stream.getTracks().forEach((track) => {
- this.peerConnection.addTrack(track, stream);
- });
- },
- // 创建 Offer
- async createOffer() {
- if (!this.peerConnection) {
- throw new Error("WebRTC 连接未初始化");
- }
- try {
- const offer = await this.peerConnection.createOffer();
- await this.peerConnection.setLocalDescription(offer);
- return offer;
- } catch (error) {
- console.error("创建 Offer 失败:", error);
- throw error;
- }
- },
- // 创建 Answer
- async createAnswer() {
- if (!this.peerConnection) {
- throw new Error("WebRTC 连接未初始化");
- }
- try {
- const answer = await this.peerConnection.createAnswer();
- await this.peerConnection.setLocalDescription(answer);
- return answer;
- } catch (error) {
- console.error("创建 Answer 失败:", error);
- throw error;
- }
- },
- // 设置远程 Description
- async setRemoteDescription(desc) {
- if (!this.peerConnection) {
- throw new Error("WebRTC 连接未初始化");
- }
- try {
- await this.peerConnection.setRemoteDescription(desc);
- } catch (error) {
- console.error("设置远程 Description 失败:", error);
- throw error;
- }
- },
- // 添加 ICE 候选
- async addIceCandidate(candidate) {
- if (!this.peerConnection) {
- throw new Error("WebRTC 连接未初始化");
- }
- try {
- await this.peerConnection.addIceCandidate(candidate);
- } catch (error) {
- console.error("添加 ICE 候选失败:", error);
- throw error;
- }
- },
- // 清理资源
- cleanup() {
- if (this.peerConnection) {
- this.peerConnection.close();
- this.peerConnection = null;
- }
- if (this.localStream) {
- this.localStream.getTracks().forEach((track) => track.stop());
- this.localStream = null;
- }
- this.iceCandidates = [];
- this.connectionState = "disconnected";
- },
- },
- });
|