首页 > 解决方案 > Peerjs 流重复(发送两次或更多次),有时不显示任何流

问题描述

我正在尝试使用 Express、Socket.IO、PeerJS、Vue3 和 Ionic 制作视频聊天应用程序。我在将流发送到对等方时遇到问题,因为它被发送了两次,有时更多有时它在没有发送任何流的情况下滞后,但在 peerjs cli 上显示连接。

Vue(客户端代码):

<template>
  <ion-page>
    <ion-header :translucent="true">
      <ion-toolbar>
        <ion-title>Chat</ion-title>
      </ion-toolbar>
    </ion-header>

    <ion-content :fullscreen="true">
      <ion-header collapse="condense">
        <ion-toolbar>
          <ion-title size="large">Chat</ion-title>
        </ion-toolbar>
      </ion-header>
      <ion-grid>
        <ion-row class="ion-justify-content-center">
          <ion-col>
            <VideoStream
              v-if="webCamVideoReady && webCamStream"
              :stream="webCamStream"
            />
          </ion-col>
        </ion-row>
        <ion-row>
          <ion-col v-for="(stream, i) in usersVideoStreams" :key="i">
            <VideoStream :stream="stream" />
          </ion-col>
        </ion-row>
      </ion-grid>
    </ion-content>
  </ion-page>
</template>

<script>
import {
  IonContent,
  IonHeader,
  IonList,
  IonPage,
  IonRefresher,
  IonRefresherContent,
  IonTitle,
  IonToolbar,
  IonGrid,
  IonRow,
  IonCol
} from "@ionic/vue";
import VideoStream from "@/components/VideoStream";
import io from "socket.io-client";
import Peer from "peerjs";
import { baseURL } from "../main";
import { ref, onMounted } from "vue";

export default {
  name: "Chat",
  components: {
    IonContent,
    IonHeader,
    IonList,
    IonPage,
    IonRefresher,
    IonRefresherContent,
    IonTitle,
    IonToolbar,
    IonGrid,
    IonRow,
    IonCol,
    VideoStream
  },
  props: ["roomId"],
  setup({ roomId }) {
    const socket = io(baseURL);
    const peer = new Peer(undefined, {
      host: "/",
      port: 4000
    });

    const webCamStream = ref(null);
    const webCamVideoReady = ref(false);
    const usersVideoStreams = ref([]);

    onMounted(() => {
      navigator.mediaDevices
        .getUserMedia({
          video: true,
          audio: true
        })
        .then(stream => {
          webCamStream.value = stream;
          webCamVideoReady.value = true;

          peer.on("call", call => {
            call.answer(stream);

            call.on("stream", userVideoStream => {
              usersVideoStreams.value.push(userVideoStream);
            });
          });

          socket.on("user-connected", userId => {
            const call = peer.call(userId, stream);

            call.on("stream", userVideoStream => {
              usersVideoStreams.value.push(userVideoStream);
            });

            // call.on("close", () => {});
          });
        });
    });

    peer.on("open", id => {
      socket.emit("join-room", roomId, id);
    });

    return { webCamVideoReady, webCamStream, usersVideoStreams };
  }
};
</script>

视频流 Vue 组件:

<template>
  <video
    ref="webCamVideo"
    @loadedmetadata="webCamVideo.play()"
    muted
    oncontextmenu="return false;"
  ></video>
</template>

<script>
import { onMounted, ref, watch, watchEffect } from "vue";
export default {
  name: "VideoStream",
  props: ["stream"],
  setup(props) {
    const webCamVideo = ref(null);

    onMounted(() => {
      webCamVideo.value.srcObject = props.stream;
    });

    return { webCamVideo };
  }
};
</script>

对等点和套接字连接:

const socket = io(baseURL);

const peer = new Peer(undefined, {
  host: "/",
  port: 4000
});

使用命令运行 Peerjs

peerjs --port 4000

Node.js 服务器端 Socket.IO 代码

const io = require("socket.io")();

io.on("connection", socket => {
  socket.on("join-room", (roomId, userId) => {
    console.log(roomId, userId);
    socket.join(roomId);
    socket.broadcast.to(roomId).emit("user-connected", userId);
  });
});

module.exports = { io };

标签: javascriptnode.jsvue.jssocket.iowebrtc

解决方案


推荐阅读