1

我需要在我的项目中将 jitsi-meet 与 reactjs web 集成。我浏览了以下文档

https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-iframe

https://dev.to/fifo/video-conferencing-app-using-react-and-jitsi-32oh

https://github.com/jitsi/lib-jitsi-meet/tree/master/doc/example

从第三个链接,我能够复制它并且工作正常。

但是我需要做同样的事情 reactjs 我已经从 npm 安装了两个包

  1. npm i lib-jitsi-react
  2. npm i strophejs-插件

仍然,它没有工作是抛出与 stophejs 相关的错误(缺少 strophe-plugins(需要迪斯科和 caps 插件)!)。

如果有人在 reactjs 中实现了 jitsi meet,请指导我如何实现这一点。

而且我使用了外部 API iframe 也可以正常工作,但我需要对 UI 进行更多控制。

下面是我的反应组件:

/* global $, JitsiMeetJS */
import react from "react";
import { JitsiMeetJS } from "lib-jitsi-meet";
import $ from "jquery";

export const options = {
  hosts: {
    domain: "beta.meet.jit.si",
    muc: "conference.beta.meet.jit.si", // FIXME: use XEP-0030
  },
  bosh: "https://beta.meet.jit.si/http-bind", // FIXME: use xep-0156 for that

  // The name of client node advertised in XEP-0115 'c' stanza
  clientNode: "http://jitsi.org/jitsimeet",
};

const confOptions = {
  openBridgeChannel: true,
};

let connection = null;
let isJoined = false;
let room = null;

let localTracks = [];
const remoteTracks = {};

/**
 * Handles local tracks.
 * @param tracks Array with JitsiTrack objects
 */
function onLocalTracks(tracks) {
  localTracks = tracks;
  for (let i = 0; i < localTracks.length; i++) {
    localTracks[i].addEventListener(
      JitsiMeetJS.events.track.TRACK_AUDIO_LEVEL_CHANGED,
      (audioLevel) => console.log(`Audio Level local: ${audioLevel}`)
    );
    localTracks[i].addEventListener(
      JitsiMeetJS.events.track.TRACK_MUTE_CHANGED,
      () => console.log("local track muted")
    );
    localTracks[i].addEventListener(
      JitsiMeetJS.events.track.LOCAL_TRACK_STOPPED,
      () => console.log("local track stoped")
    );
    localTracks[i].addEventListener(
      JitsiMeetJS.events.track.TRACK_AUDIO_OUTPUT_CHANGED,
      (deviceId) =>
        console.log(`track audio output device was changed to ${deviceId}`)
    );
    if (localTracks[i].getType() === "video") {
      $("body").append(`<video autoplay='1' id='localVideo${i}' />`);
      localTracks[i].attach($(`#localVideo${i}`)[0]);
    } else {
      $("body").append(
        `<audio autoplay='1' muted='true' id='localAudio${i}' />`
      );
      localTracks[i].attach($(`#localAudio${i}`)[0]);
    }
    if (isJoined) {
      room.addTrack(localTracks[i]);
    }
  }
}

/**
 * Handles remote tracks
 * @param track JitsiTrack object
 */
function onRemoteTrack(track) {
  if (track.isLocal()) {
    return;
  }
  const participant = track.getParticipantId();

  if (!remoteTracks[participant]) {
    remoteTracks[participant] = [];
  }
  const idx = remoteTracks[participant].push(track);

  track.addEventListener(
    JitsiMeetJS.events.track.TRACK_AUDIO_LEVEL_CHANGED,
    (audioLevel) => console.log(`Audio Level remote: ${audioLevel}`)
  );
  track.addEventListener(JitsiMeetJS.events.track.TRACK_MUTE_CHANGED, () =>
    console.log("remote track muted")
  );
  track.addEventListener(JitsiMeetJS.events.track.LOCAL_TRACK_STOPPED, () =>
    console.log("remote track stoped")
  );
  track.addEventListener(
    JitsiMeetJS.events.track.TRACK_AUDIO_OUTPUT_CHANGED,
    (deviceId) =>
      console.log(`track audio output device was changed to ${deviceId}`)
  );
  const id = participant + track.getType() + idx;

  if (track.getType() === "video") {
    $("body").append(`<video autoplay='1' id='${participant}video${idx}' />`);
  } else {
    $("body").append(`<audio autoplay='1' id='${participant}audio${idx}' />`);
  }
  track.attach($(`#${id}`)[0]);
}

/**
 * That function is executed when the conference is joined
 */
function onConferenceJoined() {
  console.log("conference joined!");
  isJoined = true;
  for (let i = 0; i < localTracks.length; i++) {
    room.addTrack(localTracks[i]);
  }
}

/**
 *
 * @param id
 */
function onUserLeft(id) {
  console.log("user left");
  if (!remoteTracks[id]) {
    return;
  }
  const tracks = remoteTracks[id];

  for (let i = 0; i < tracks.length; i++) {
    tracks[i].detach($(`#${id}${tracks[i].getType()}`));
  }
}

/**
 * That function is called when connection is established successfully
 */
function onConnectionSuccess() {
  room = connection.initJitsiConference("s123", confOptions);
  room.on(JitsiMeetJS.events.conference.TRACK_ADDED, onRemoteTrack);
  room.on(JitsiMeetJS.events.conference.TRACK_REMOVED, (track) => {
    console.log(`track removed!!!${track}`);
  });
  room.on(JitsiMeetJS.events.conference.CONFERENCE_JOINED, onConferenceJoined);
  room.on(JitsiMeetJS.events.conference.USER_JOINED, (id) => {
    console.log("user join");
    remoteTracks[id] = [];
  });
  room.on(JitsiMeetJS.events.conference.USER_LEFT, onUserLeft);
  room.on(JitsiMeetJS.events.conference.TRACK_MUTE_CHANGED, (track) => {
    console.log(`${track.getType()} - ${track.isMuted()}`);
  });
  room.on(
    JitsiMeetJS.events.conference.DISPLAY_NAME_CHANGED,
    (userID, displayName) => console.log(`${userID} - ${displayName}`)
  );
  room.on(
    JitsiMeetJS.events.conference.TRACK_AUDIO_LEVEL_CHANGED,
    (userID, audioLevel) => console.log(`${userID} - ${audioLevel}`)
  );
  room.on(JitsiMeetJS.events.conference.PHONE_NUMBER_CHANGED, () =>
    console.log(`${room.getPhoneNumber()} - ${room.getPhonePin()}`)
  );
  room.join();
}

/**
 * This function is called when the connection fail.
 */
function onConnectionFailed() {
  console.error("Connection Failed!");
}

/**
 * This function is called when the connection fail.
 */
function onDeviceListChanged(devices) {
  console.info("current devices", devices);
}

/**
 * This function is called when we disconnect.
 */
function disconnect() {
  console.log("disconnect!");
  connection.removeEventListener(
    JitsiMeetJS.events.connection.CONNECTION_ESTABLISHED,
    onConnectionSuccess
  );
  connection.removeEventListener(
    JitsiMeetJS.events.connection.CONNECTION_FAILED,
    onConnectionFailed
  );
  connection.removeEventListener(
    JitsiMeetJS.events.connection.CONNECTION_DISCONNECTED,
    disconnect
  );
}

/**
 *
 */
function unload() {
  for (let i = 0; i < localTracks.length; i++) {
    localTracks[i].dispose();
  }
  room.leave();
  connection.disconnect();
}

let isVideo = true;

/**
 *
 */
export function switchVideo() {
  // eslint-disable-line no-unused-vars
  isVideo = !isVideo;
  if (localTracks[1]) {
    localTracks[1].dispose();
    localTracks.pop();
  }
  JitsiMeetJS.createLocalTracks({
    devices: [isVideo ? "video" : "desktop"],
  })
    .then((tracks) => {
      localTracks.push(tracks[0]);
      localTracks[1].addEventListener(
        JitsiMeetJS.events.track.TRACK_MUTE_CHANGED,
        () => console.log("local track muted")
      );
      localTracks[1].addEventListener(
        JitsiMeetJS.events.track.LOCAL_TRACK_STOPPED,
        () => console.log("local track stoped")
      );
      localTracks[1].attach($("#localVideo1")[0]);
      room.addTrack(localTracks[1]);
    })
    .catch((error) => console.log(error));
}

/**
 *
 * @param selected
 */
function changeAudioOutput(selected) {
  // eslint-disable-line no-unused-vars
  JitsiMeetJS.mediaDevices.setAudioOutputDevice(selected.value);
}

$(window).bind("beforeunload", unload);
$(window).bind("unload", unload);

// JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.ERROR);
const initOptions = {
  disableAudioLevels: true,
};

window.JitsiMeetJS.init(initOptions);

connection = new window.JitsiMeetJS.JitsiConnection(null, null, options);

connection.addEventListener(
  JitsiMeetJS.events.connection.CONNECTION_ESTABLISHED,
  onConnectionSuccess
);
connection.addEventListener(
  JitsiMeetJS.events.connection.CONNECTION_FAILED,
  onConnectionFailed
);
connection.addEventListener(
  JitsiMeetJS.events.connection.CONNECTION_DISCONNECTED,
  disconnect
);

JitsiMeetJS.mediaDevices.addEventListener(
  JitsiMeetJS.events.mediaDevices.DEVICE_LIST_CHANGED,
  onDeviceListChanged
);

connection.connect();

JitsiMeetJS.createLocalTracks({ devices: ["audio", "video"] })
  .then(onLocalTracks)
  .catch((error) => {
    throw error;
  });

if (JitsiMeetJS.mediaDevices.isDeviceChangeAvailable("output")) {
  JitsiMeetJS.mediaDevices.enumerateDevices((devices) => {
    const audioOutputDevices = devices.filter((d) => d.kind === "audiooutput");

    if (audioOutputDevices.length > 1) {
      $("#audioOutputSelect").html(
        audioOutputDevices
          .map((d) => `<option value="${d.deviceId}">${d.label}</option>`)
          .join("\n")
      );

      $("#audioOutputSelectWrapper").show();
    }
  });
}
<!DOCTYPE html>
<html>
  <head lang="en">
    <meta charset="UTF-8" />
    <title></title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/strophe.js/1.2.16/strophe.min.js"></script>
    <script src="strophe.disco.min.js?v=1"></script>
    <script src="lib-jitsi-meet.min.js"></script>
    <script src="jitsi.js"></script>
  </head>
  <body>
    <a href="#" onclick="unload()">Unload</a>
    <a href="#" onclick="switchVideo()">switchVideo</a>
    <div id="audioOutputSelectWrapper" style="display: none;">
      Change audio output device
      <select
        id="audioOutputSelect"
        onchange="changeAudioOutput(this)"
      ></select>
    </div>
    <!-- <video id="localVideo" autoplay="true"></video> -->
    <!--<audio id="localAudio" autoplay="true" muted="true"></audio>-->
  </body>
</html>
© 2020 GitHub, Inc.

提前致谢。

4

1 回答 1

3

如果你还在寻找什么。我使用以下示例在 React JS 中实现了 Jitsi:

https://github.com/this-fifo/jutsu

于 2020-10-08T10:02:09.000 回答