首页 > 解决方案 > 直接修改url参数访问时收不到远程视频流

问题描述

所以我开始玩在这里找到的简单 mediasoup 演示:https ://github.com/Dirvann/mediasoup-sfu-webrtc-video-rooms

我设置了演示,一切正常。

我要做的第一件事是添加 url 参数以绕过登录屏幕,这应该很容易,对吧?但是由于某些原因,当您通过直接修改 url 参数导航到房间时,它不会显示房间中其他用户的远程流!当用户使用登录表单加入房间时,它会显示房间中其他用户的流。

这让我感到困惑,因为无论您单击登录表单上的“加入”按钮,还是您的 url 已经存在参数,都在执行完全相同的 js 方法!

这里我将演示执行流程:

最初,我们有 1 个用户在 123 房间共享网络摄像头。第二个用户导航到没有相关参数的 url,因此,他们会看到登录表单: 在此处输入图像描述

检查详细信息后,用户意识到默认设置很好,然后继续单击加入按钮。这会调用一个简单的函数,通过更新 window.location.href 将房间和用户值添加到 URL(它会导致页面刷新)

页面刷新完成后,会出现必要的参数,这会导致视频室加载并显示远程流,如下所示: 在此处输入图像描述

但是,当我们不通过表单登录时,就会出现问题,我们直接将那些必要的参数添加到 url 中。如图所示: 在此处输入图像描述 这里应该有一个远程流,因为它与上图中的房间相同。我不知道为什么会出现这个问题。

这是我的 index.js 文件,我的更改都在斜杠内,靠近文件底部:

if (location.href.substr(0, 5) !== 'https')
  location.href = 'https' + location.href.substr(4, location.href.length - 4)

const socket = io()


let producer = null;

nameInput.value = 'bob' + Math.round(Math.random() * 1000)

socket.request = function request(type, data = {}) {
  return new Promise((resolve, reject) => {
    socket.emit(type, data, (data) => {
      if (data.error) {
        reject(data.error)
      } else {
        resolve(data)
      }
    })
  })
}

let rc = null

function joinRoom(name, room_id) {
  if (rc && rc.isOpen()) {
    console.log('already connected to a room')
  } else {
    rc = new RoomClient(localMedia, remoteVideos, remoteAudios, window.mediasoupClient, socket, room_id, name, roomOpen)

    addListeners()
  }

}



function roomOpen() {
  login.className = 'hidden'
  reveal(startAudioButton)
  hide(stopAudioButton)
  reveal(startVideoButton)
  hide(stopVideoButton)
  reveal(startScreenButton)
  hide(stopScreenButton)
  reveal(exitButton)
  control.className = ''
  reveal(videoMedia)
}

function hide(elem) {
  elem.className = 'hidden'
}

function reveal(elem) {
  elem.className = ''
}


function addListeners() {
  rc.on(RoomClient.EVENTS.startScreen, () => {
    hide(startScreenButton)
    reveal(stopScreenButton)
  })

  rc.on(RoomClient.EVENTS.stopScreen, () => {
    hide(stopScreenButton)
    reveal(startScreenButton)

  })

  rc.on(RoomClient.EVENTS.stopAudio, () => {
    hide(stopAudioButton)
    reveal(startAudioButton)

  })
  rc.on(RoomClient.EVENTS.startAudio, () => {
    hide(startAudioButton)
    reveal(stopAudioButton)
  })

  rc.on(RoomClient.EVENTS.startVideo, () => {
    hide(startVideoButton)
    reveal(stopVideoButton)
  })
  rc.on(RoomClient.EVENTS.stopVideo, () => {
    hide(stopVideoButton)
    reveal(startVideoButton)
  })
  rc.on(RoomClient.EVENTS.exitRoom, () => {
    hide(control)
    reveal(login)
    hide(videoMedia)

    /////////////////////////
    let indexOfQuestionMark = location.href.indexOf("?")
    location.href = location.href.split('').slice(0, indexOfQuestionMark-1).join('')
    /////////////////////////

  })
}

// Load mediaDevice options
navigator.mediaDevices.enumerateDevices().then(devices =>
  devices.forEach(device => {
    let el = null
    if ('audioinput' === device.kind) {
      el = audioSelect
    } else if ('videoinput' === device.kind) {
      el = videoSelect
    }
    if(!el) return

    let option = document.createElement('option')
    option.value = device.deviceId
    option.innerText = device.label
    el.appendChild(option)
  })
)
/////////////////////////
if (window.location.href.includes("?r=") && window.location.href.includes("n=")) {
  let indexOfRoomNumber = location.href.indexOf("?r=")+3
  let array = location.href.split('')
  let room = array.slice(indexOfRoomNumber,indexOfRoomNumber+3).join("")
  let username = array.slice(indexOfRoomNumber+6, array.length).join("")
  joinRoom(username,room)
  console.log(`Welcome to room: ${room}, ${username}`)

}

function addParams(name, room_id) {
  window.location.href = `${location.href}?r=${room_id}+n=${name}`
}
//////////////////////////

addParams 函数由 index.html 中的 Join 按钮直接调用,如下所示:

<html>

<head>
    <script src="socket.io/socket.io.js"></script>
    <script src="modules/mediasoupclient.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/EventEmitter/5.2.8/EventEmitter.min.js"></script>
    <script src="RoomClient.js"></script>
    <style>
        .containers {
            display: grid;
            grid-gap: 5px;
            grid-template-columns: repeat(auto-fit, 1fr);
            grid-template-rows: repeat(auto-fit, 300px);
        }

        .container {
            display: flex;
        }

        .vid {
            flex: 0 1 auto;
            height: 400px;
        }

        .settings {
            background-color: #4CAF50;
            border: none;
            color: white;
            padding: 5px 10px;
            text-align: center;
            text-decoration: none;
            display: inline-block;
            font-size: 14px;
            margin: 2px 2px;
            cursor: pointer;
        }

        .hidden {
            display: none
        }
    </style>
</head>

<body>
    <div id="login">
        Room:   <input id="roomidInput" value="123" type="text" />
        <!--<button id="createRoom" onclick="createRoom(roomid.value)" label="createRoom">Create Room</button>-->
        <br />
        User: <input id='nameInput' value="bob" type="text" />
        <button id='joinButton' onclick="addParams(nameInput.value, roomidInput.value)">Join</button>
    </div>
    <div id="control" class="hidden">
        <button id='exitButton' class='hidden' onclick="rc.exit()">Exit</button>
        <br/>
        audio: <select id="audioSelect">
        </select>
        <br/>
        video: <select id="videoSelect">
        </select>
        <br />
        <button id='startAudioButton' class='hidden' onclick="rc.produce(RoomClient.mediaType.audio, audioSelect.value)">audio</button>
        <button id='stopAudioButton' class='hidden' onclick="rc.closeProducer(RoomClient.mediaType.audio)">close
            audio</button>
        <button id='startVideoButton' class='hidden' onclick="rc.produce(RoomClient.mediaType.video, videoSelect.value)">video</button>
        <button id='stopVideoButton' class='hidden' onclick="rc.closeProducer(RoomClient.mediaType.video)">close
            video</button>
        <button id='startScreenButton' class='hidden' onclick="rc.produce(RoomClient.mediaType.screen)">screen</button>
        <button id='stopScreenButton' class='hidden' onclick="rc.closeProducer(RoomClient.mediaType.screen)">close
            screen</button>
        <br />
    </div>




    <div id='videoMedia' class='hidden'>
        <h2>------local------</h2>
        <div id="localMedia"></div>
        <!--<video id="localVideo" autoplay inline class="vid"></video>-->
        <!--<video id="localScreen" autoplay inline class="vid"></video>-->
        <h2>-----remote-----</h2>
        <div id="remoteVideos" class="container">
        </div>

        <div id="remoteAudios"></div>

    </div>
</body>
<footer>
    <script src="index.js"></script>
</footer>

</html>

请注意:我修改的唯一文件是上面提到的那些。所有其他文件与演示的 github 存储库中的相同(链接在本文顶部。)

如果有人能帮助我深入了解这个问题,我将不胜感激。如果有 url 参数是什么导致房间被加入,为什么将参数放在 URL 中的方法似乎产生了如此显着的差异?

感谢您的时间和您可能提供的任何帮助!:)

标签: javascriptsocket.iowebrtcmediasoup

解决方案


唯一的区别是您不使用用户交互来建立连接。浏览器中的某些操作需要用户交互,这可能是它不起作用的原因。 自动播放政策更改

当您在页面上时添加一个按钮来执行 joinRoom 可以解决这个问题。


推荐阅读