ably webrtc group call 在 Javascript 和简单对等体中不工作
ably webrtc group call Not working in Javascript and simple peer
我们正在努力使用 Ably 和简单的对等点制作一个简单的群呼网络应用程序。按照分步教程,一对一通话有效(在 public ip 上使用时也有问题,但这是另一天的主题)
但是,当相同的代码被修改为适用于群组通话时,它似乎不起作用。列出了成员,用户可以加入群组(频道),控制台甚至显示信号已 sent/received。但音频视频流不工作。以下是一些 js 代码(根据 ably 示例修改)
var membersList = []
var connections = {}
var currentCall
var localStream
var CurrentGroup = ""
var constraints = { video: true, audio: true }
var apiKey = 'oZ_NdA.xyzabc' // a new app key for Group Call
//var clientId = GetUserName() +'_'+ Math.random().toString(36).substr(2, 6) || 'client-' + Math.random().toString(36).substr(2, 16)
var clientId = GetUserName() || 'client-' + Math.random().toString(36).substr(2, 16)
let GroupMembers = null
let RealtimeApi = new Ably.Realtime({ key: apiKey, clientId: clientId })
var RealtimeChannel;
function JoinGroup(groupName) {
if (CurrentGroup !== "") {
LeaveCurrentGroup()
}
if (CurrentGroup == groupName) {
// user is already in this group
return
}
CurrentGroup = groupName
InitializeRealtimeChannel()
RealtimeChannel.presence.enter()
StartLocalCamera()
//RegisterSignalReceivingEvent()
RealtimeChannel.presence.subscribe('enter', function(member) {
RealtimeChannel.presence.get((err, members) => {
GroupMembers = members
RenderGroupMemberList(groupName, GroupMembers)
GenerateGroupMembersVideoTags(GroupMembers)
})
if (member.clientId === clientId) {
document.querySelector("#GroupStatus").innerHTML = "You have Joined the Group"
InitiateConnectionsWithGroupMembers(groupName)
RealtimeChannel.subscribe(`rtc-signal/${clientId}`, msg => {
if (localStream === undefined) {
navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream) {
/* use the stream */
localStream = stream
var video = document.getElementById('local')
//video.src = window.URL.createObjectURL(stream)
video.srcObject = stream
video.play()
connect(msg.data, stream)
})
.catch(function(err) {
alert('error occurred while trying to get stream')
})
} else {
connect(msg.data, localStream)
}
})
} else {
document.querySelector("#GroupStatus").innerHTML = member.clientId + " has Joined"
}
})
RealtimeChannel.presence.subscribe('leave', member => {
if (member.clientId === clientId) {
document.querySelector("#GroupStatus").innerHTML = "You have Left the Group"
document.querySelector("#GroupMemberVideos").innerHTML = ""
connections = []
} else {
document.querySelector("#GroupStatus").innerHTML = member.clientId + " has Left"
ReleaseLeavingMemberResources(member.clientId)
}
RealtimeChannel.presence.get((err, members) => {
GroupMembers = members
RenderGroupMemberList(groupName, GroupMembers)
})
})
}
function LeaveCurrentGroup() {
if (CurrentGroup !== "") {
InitializeRealtimeChannel()
RealtimeChannel.presence.leave()
CurrentGroup = ""
}
}
function GetAvailableMembersInGroup(groupName) {
let Channel = RealtimeApi.channels.get(groupName)
let GroupMembers = new Array()
Channel.presence.get((err, members) => {
GroupMembers = members
RenderGroupMemberList(groupName, GroupMembers)
// if (CurrentGroup == groupName) {
// GenerateGroupMembersVideoTags(members)
// }
})
}
function RenderGroupMemberList(groupName, memberNames) {
let Element = document.querySelector("#" + groupName + " .people-list")
let html = "<ul class='MemberList'>";
if (!memberNames || memberNames.length < 1) {
html += "<li style='font-weight: bold;'>No Member Yet..</li>"
}
if (memberNames) {
for (var i = 0; i < memberNames.length; i++) {
if (memberNames[i].clientId !== clientId) {
html += "<li>" + memberNames[i].clientId + "</li>"
} else {
html += "<li style='font-weight: bold;'>" + memberNames[i].clientId + " (You)</li>"
}
}
}
html += "</ul>"
Element.innerHTML = html;
}
function GenerateGroupMembersVideoTags(memberNames) {
let VideoHtml = "";
if (memberNames) {
for (var i = 0; i < memberNames.length; i++) {
if (memberNames[i].clientId === clientId || document.querySelector("#VideoContainer_" + memberNames[i].clientId) != null) {
// do nothing
} else {
let VideoTag = '<div class = "col-lg-3 col-sm-6 col-xs-12" id="VideoContainer_' + memberNames[i].clientId + '" >\n';
VideoTag += '<video controls style = "width: 100%; height: 100%; min-height: 200px;" id="Video_' + memberNames[i].clientId + '" ></video> \n';
VideoTag += '</div >';
VideoHtml += VideoTag;
}
}
}
// document.querySelector("#GroupMemberVideos").innerHTML += VideoHtml;
document.querySelector("#GroupMemberVideos").insertAdjacentHTML("beforeend", VideoHtml)
}
function ReleaseLeavingMemberResources(client_Id) {
if (document.querySelector("#VideoContainer_" + client_Id)) {
document.querySelector("#VideoContainer_" + client_Id).remove();
}
if (connections[client_Id]) {
connections[client_Id] = null
delete connections[client_Id]
}
}
function InitiateConnectionsWithGroupMembers(groupName) {
if (GroupMembers) {
for (let index = 0; index < GroupMembers.length; index++) {
if (GroupMembers[index].clientId != clientId && connections[GroupMembers[index].clientId] == null)
initiateCall(GroupMembers[index].clientId)
}
}
}
function StartLocalCamera() {
navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream) {
/* use the stream */
localStream = stream
var video = document.getElementById('local')
if (video.srcObject == null) {
video.srcObject = stream
video.play()
}
//video.src = window.URL.createObjectURL(stream)
})
.catch(function(err) {
console.error(err)
alert('Could not get video stream from source')
})
}
function InitializeRealtimeChannel() {
if (!RealtimeChannel) {
RealtimeChannel = RealtimeApi.channels.get(CurrentGroup)
}
}
function initiateCall(client_id) {
console.info(`Initialting call with ${client_id}`)
// Create a new connection
currentCall = client_id
if (!connections[client_id]) {
connections[client_id] = new Connection(client_id, RealtimeChannel, true, localStream)
}
}
function connect(data, stream) {
if (!connections[data.user]) {
connections[data.user] = new Connection(data.user, RealtimeChannel, false, stream)
}
if (!connections[data.user].isConnected) {
connections[data.user].handleSignal(data.signal)
}
}
function receiveStream(client_id, stream) {
let video = document.getElementById('Video_' + client_id)
//video.src = window.URL.createObjectURL(stream)
video.srcObject = stream
video.play()
}
简单的同伴帮手如下:
class Connection {
constructor(remoteClient, AblyRealtime, initiator, stream) {
console.log(`Opening connection to ${remoteClient}`)
this._remoteClient = remoteClient
this.isConnected = false
this._p2pConnection = new SimplePeer({
initiator: initiator,
stream: stream
})
this._p2pConnection.on('signal', this._onSignal.bind(this))
this._p2pConnection.on('error', this._onError.bind(this))
this._p2pConnection.on('connect', this._onConnect.bind(this))
this._p2pConnection.on('close', this._onClose.bind(this))
this._p2pConnection.on('stream', this._onStream.bind(this))
}
handleSignal(signal) {
this._p2pConnection.signal(signal)
}
send(msg) {
this._p2pConnection.send(msg)
}
destroy() {
this._p2pConnection.destroy()
}
_onSignal(signal) {
InitializeRealtimeChannel()
try {
console.info("Sending Signal to :" + `${this._remoteClient}`)
RealtimeChannel.publish(`rtc-signal/${this._remoteClient}`, {
user: clientId,
signal: signal
})
} catch (error) {
console.error("Signal error: " + error)
}
}
_onConnect() {
this.isConnected = true
console.log('connected to ' + this._remoteClient)
}
_onClose() {
console.log(`connection to ${this._remoteClient} closed`)
}
_onStream(data) {
console.info("Attempting to receive stream from " + this._remoteClient)
receiveStream(this._remoteClient, data)
}
_onError(error) {
console.log(`an error occurred ${error.toString()}`)
}
}
HTML 如下
<!--https://www.ably.io/tutorials/web-rtc-video-calling#testing-our-app-->
<!DOCTYPE html>
<html>
<head>
<title>Group Calls</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
</head>
<body class="bodybg">
<script src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/6.2.1/adapter.min.js"></script>
<script src="https://cdn.ably.io/lib/ably.min-1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/simple-peer/9.1.2/simplepeer.min.js"></script>
<!-- <script src="js/simple-peer/simplepeer.min.js" type="javascript"></script> -->
<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<!-- <script src="js/simple-peer/index.js"></script> -->
<script src="js/helper.js"></script>
<script src="js/group-call.js"></script>
<script src="js/ably-groupcall.js"></script>
<!-- <script src="js/connection-helper.js"></script> -->
<script src="js/group-connectionhelper.js"></script>
<form action="groups.html" method="GET" id="DisplayNameForm">
<div class="row" style="background-color: rgba(136, 26, 32, 0.53);">
<div class="col-sm-4">
<div class="form-group">
<label style="color: #fff;">Display Name</label>
<input type="text" name="Name" class="form-control" />
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<label> </label>
<button type="submit" class="btn btn-primary btn-block">Update</button>
</div>
</div>
</div>
</form>
<div class="conatainer-fluid" style="margin-top: 3em;">
<div class="row">
<!-- Group-1 -->
<div class="col-sm-3 col-xs-6">
<div class="panel panel-primary" id="Group_1">
<div class="panel-heading" id="Group_1_Heading">
Group-1
</div>
<div class="panel-body">
<h4>Members:</h4>
<div class="people-list"></div>
</div>
<div class="panel-footer">
<button onclick="JoinGroup('Group_1')" class="btn btn-info btn-block">Join</button>
</div>
</div>
</div>
<!-- Group-2 -->
<div class="col-sm-3 col-xs-6">
<div class="panel panel-primary" id="Group_2">
<div class="panel-heading" id="Group_2_Heading">
Group-2
</div>
<div class="panel-body">
<h4>Members:</h4>
<div class="people-list"></div>
</div>
<div class="panel-footer">
<button onclick="JoinGroup('Group_2')" class="btn btn-info btn-block">Join</button>
</div>
</div>
</div>
<!-- Group-3 -->
<div class="col-sm-3 col-xs-6">
<div class="panel panel-primary" id="Group_3">
<div class="panel-heading" id="Group_3_Heading">
Group-3
</div>
<div class="panel-body">
<h4>Members:</h4>
<div class="people-list"></div>
</div>
<div class="panel-footer">
<button onclick="JoinGroup('Group_3')" class="btn btn-info btn-block">Join</button>
</div>
</div>
</div>
<!-- Group-4 -->
<div class="col-sm-3 col-xs-6">
<div class="panel panel-primary" id="Group_4">
<div class="panel-heading" id="Group_4_Heading">
Group-4
</div>
<div class="panel-body">
<h4>Members:</h4>
<div class="people-list"></div>
</div>
<div class="panel-footer">
<button onclick="JoinGroup('Group_4')" class="btn btn-info btn-block">Join</button>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-3 col-xs-12">
<div class="panel panel-default">
<div class="panel-body">
<video id="local" muted style="z-index: 2; width: 100%; min-height: 200px;"></video>
<div class="row">
<div class="col-sm-12">
<div class="col-xs-6">
<h3>Duration:</h3>
<label id="minutes"></label> : <label id="seconds"></label>
</div>
<div class="col-xs-6">
<button class="btn btn-default" onclick="LeaveCurrentGroup()" title="Leave Group">
<img src="asset/hang-up.svg" style="width: 50px; height: 50px; color: #fff;">
</button>
</div>
</div>
<div class="col-sm-12">
<h3 id="CallStatus"></h3>
</div>
<div class="col-sm-12">
<h3 id="GroupStatus"></h3>
</div>
</div>
</div>
</div>
Icons made by <a href="https://www.flaticon.com/authors/dmitri13" title="dmitri13">dmitri13</a> from <a href="https://www.flaticon.com/" title="Flaticon"> www.flaticon.com</a>
</div>
<div class="col-sm-9 col-xs-12" style="margin-bottom: 50px;">
<div id="call" style="position: relative;">
<div class="row" id="GroupMemberVideos">
</div>
</div>
</div>
</div>
</div>
</body>
<style>
.MemberList {
list-style: decimal;
}
</style>
</html>
<script type="text/javascript">
window.onload = function() {
var Name = GetUrlParameter('Name');
if (Name != null && Name != '') {
document.getElementById('DisplayNameForm').style.display = 'none'
}
setTimeout(() => {
UpdateGroupMemeberLists()
}, 5000);
}
function UpdateGroupMemeberLists() {
for (let index = 1; index <= 4; index++) {
GetAvailableMembersInGroup("Group_" + index)
}
}
</script>
通过一些基本的调试,显示连接已建立但没有流
感谢任何帮助,因为我完全不知道 webrtc 是如何工作的。
找到问题了。 :)
正在加入群组功能中初始化本地摄像机流。通过在文档加载时初始化本地视频流解决了该问题。
希望这对其他人有帮助。
我们正在努力使用 Ably 和简单的对等点制作一个简单的群呼网络应用程序。按照分步教程,一对一通话有效(在 public ip 上使用时也有问题,但这是另一天的主题)
但是,当相同的代码被修改为适用于群组通话时,它似乎不起作用。列出了成员,用户可以加入群组(频道),控制台甚至显示信号已 sent/received。但音频视频流不工作。以下是一些 js 代码(根据 ably 示例修改)
var membersList = []
var connections = {}
var currentCall
var localStream
var CurrentGroup = ""
var constraints = { video: true, audio: true }
var apiKey = 'oZ_NdA.xyzabc' // a new app key for Group Call
//var clientId = GetUserName() +'_'+ Math.random().toString(36).substr(2, 6) || 'client-' + Math.random().toString(36).substr(2, 16)
var clientId = GetUserName() || 'client-' + Math.random().toString(36).substr(2, 16)
let GroupMembers = null
let RealtimeApi = new Ably.Realtime({ key: apiKey, clientId: clientId })
var RealtimeChannel;
function JoinGroup(groupName) {
if (CurrentGroup !== "") {
LeaveCurrentGroup()
}
if (CurrentGroup == groupName) {
// user is already in this group
return
}
CurrentGroup = groupName
InitializeRealtimeChannel()
RealtimeChannel.presence.enter()
StartLocalCamera()
//RegisterSignalReceivingEvent()
RealtimeChannel.presence.subscribe('enter', function(member) {
RealtimeChannel.presence.get((err, members) => {
GroupMembers = members
RenderGroupMemberList(groupName, GroupMembers)
GenerateGroupMembersVideoTags(GroupMembers)
})
if (member.clientId === clientId) {
document.querySelector("#GroupStatus").innerHTML = "You have Joined the Group"
InitiateConnectionsWithGroupMembers(groupName)
RealtimeChannel.subscribe(`rtc-signal/${clientId}`, msg => {
if (localStream === undefined) {
navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream) {
/* use the stream */
localStream = stream
var video = document.getElementById('local')
//video.src = window.URL.createObjectURL(stream)
video.srcObject = stream
video.play()
connect(msg.data, stream)
})
.catch(function(err) {
alert('error occurred while trying to get stream')
})
} else {
connect(msg.data, localStream)
}
})
} else {
document.querySelector("#GroupStatus").innerHTML = member.clientId + " has Joined"
}
})
RealtimeChannel.presence.subscribe('leave', member => {
if (member.clientId === clientId) {
document.querySelector("#GroupStatus").innerHTML = "You have Left the Group"
document.querySelector("#GroupMemberVideos").innerHTML = ""
connections = []
} else {
document.querySelector("#GroupStatus").innerHTML = member.clientId + " has Left"
ReleaseLeavingMemberResources(member.clientId)
}
RealtimeChannel.presence.get((err, members) => {
GroupMembers = members
RenderGroupMemberList(groupName, GroupMembers)
})
})
}
function LeaveCurrentGroup() {
if (CurrentGroup !== "") {
InitializeRealtimeChannel()
RealtimeChannel.presence.leave()
CurrentGroup = ""
}
}
function GetAvailableMembersInGroup(groupName) {
let Channel = RealtimeApi.channels.get(groupName)
let GroupMembers = new Array()
Channel.presence.get((err, members) => {
GroupMembers = members
RenderGroupMemberList(groupName, GroupMembers)
// if (CurrentGroup == groupName) {
// GenerateGroupMembersVideoTags(members)
// }
})
}
function RenderGroupMemberList(groupName, memberNames) {
let Element = document.querySelector("#" + groupName + " .people-list")
let html = "<ul class='MemberList'>";
if (!memberNames || memberNames.length < 1) {
html += "<li style='font-weight: bold;'>No Member Yet..</li>"
}
if (memberNames) {
for (var i = 0; i < memberNames.length; i++) {
if (memberNames[i].clientId !== clientId) {
html += "<li>" + memberNames[i].clientId + "</li>"
} else {
html += "<li style='font-weight: bold;'>" + memberNames[i].clientId + " (You)</li>"
}
}
}
html += "</ul>"
Element.innerHTML = html;
}
function GenerateGroupMembersVideoTags(memberNames) {
let VideoHtml = "";
if (memberNames) {
for (var i = 0; i < memberNames.length; i++) {
if (memberNames[i].clientId === clientId || document.querySelector("#VideoContainer_" + memberNames[i].clientId) != null) {
// do nothing
} else {
let VideoTag = '<div class = "col-lg-3 col-sm-6 col-xs-12" id="VideoContainer_' + memberNames[i].clientId + '" >\n';
VideoTag += '<video controls style = "width: 100%; height: 100%; min-height: 200px;" id="Video_' + memberNames[i].clientId + '" ></video> \n';
VideoTag += '</div >';
VideoHtml += VideoTag;
}
}
}
// document.querySelector("#GroupMemberVideos").innerHTML += VideoHtml;
document.querySelector("#GroupMemberVideos").insertAdjacentHTML("beforeend", VideoHtml)
}
function ReleaseLeavingMemberResources(client_Id) {
if (document.querySelector("#VideoContainer_" + client_Id)) {
document.querySelector("#VideoContainer_" + client_Id).remove();
}
if (connections[client_Id]) {
connections[client_Id] = null
delete connections[client_Id]
}
}
function InitiateConnectionsWithGroupMembers(groupName) {
if (GroupMembers) {
for (let index = 0; index < GroupMembers.length; index++) {
if (GroupMembers[index].clientId != clientId && connections[GroupMembers[index].clientId] == null)
initiateCall(GroupMembers[index].clientId)
}
}
}
function StartLocalCamera() {
navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream) {
/* use the stream */
localStream = stream
var video = document.getElementById('local')
if (video.srcObject == null) {
video.srcObject = stream
video.play()
}
//video.src = window.URL.createObjectURL(stream)
})
.catch(function(err) {
console.error(err)
alert('Could not get video stream from source')
})
}
function InitializeRealtimeChannel() {
if (!RealtimeChannel) {
RealtimeChannel = RealtimeApi.channels.get(CurrentGroup)
}
}
function initiateCall(client_id) {
console.info(`Initialting call with ${client_id}`)
// Create a new connection
currentCall = client_id
if (!connections[client_id]) {
connections[client_id] = new Connection(client_id, RealtimeChannel, true, localStream)
}
}
function connect(data, stream) {
if (!connections[data.user]) {
connections[data.user] = new Connection(data.user, RealtimeChannel, false, stream)
}
if (!connections[data.user].isConnected) {
connections[data.user].handleSignal(data.signal)
}
}
function receiveStream(client_id, stream) {
let video = document.getElementById('Video_' + client_id)
//video.src = window.URL.createObjectURL(stream)
video.srcObject = stream
video.play()
}
简单的同伴帮手如下:
class Connection {
constructor(remoteClient, AblyRealtime, initiator, stream) {
console.log(`Opening connection to ${remoteClient}`)
this._remoteClient = remoteClient
this.isConnected = false
this._p2pConnection = new SimplePeer({
initiator: initiator,
stream: stream
})
this._p2pConnection.on('signal', this._onSignal.bind(this))
this._p2pConnection.on('error', this._onError.bind(this))
this._p2pConnection.on('connect', this._onConnect.bind(this))
this._p2pConnection.on('close', this._onClose.bind(this))
this._p2pConnection.on('stream', this._onStream.bind(this))
}
handleSignal(signal) {
this._p2pConnection.signal(signal)
}
send(msg) {
this._p2pConnection.send(msg)
}
destroy() {
this._p2pConnection.destroy()
}
_onSignal(signal) {
InitializeRealtimeChannel()
try {
console.info("Sending Signal to :" + `${this._remoteClient}`)
RealtimeChannel.publish(`rtc-signal/${this._remoteClient}`, {
user: clientId,
signal: signal
})
} catch (error) {
console.error("Signal error: " + error)
}
}
_onConnect() {
this.isConnected = true
console.log('connected to ' + this._remoteClient)
}
_onClose() {
console.log(`connection to ${this._remoteClient} closed`)
}
_onStream(data) {
console.info("Attempting to receive stream from " + this._remoteClient)
receiveStream(this._remoteClient, data)
}
_onError(error) {
console.log(`an error occurred ${error.toString()}`)
}
}
HTML 如下
<!--https://www.ably.io/tutorials/web-rtc-video-calling#testing-our-app-->
<!DOCTYPE html>
<html>
<head>
<title>Group Calls</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
</head>
<body class="bodybg">
<script src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/6.2.1/adapter.min.js"></script>
<script src="https://cdn.ably.io/lib/ably.min-1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/simple-peer/9.1.2/simplepeer.min.js"></script>
<!-- <script src="js/simple-peer/simplepeer.min.js" type="javascript"></script> -->
<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<!-- <script src="js/simple-peer/index.js"></script> -->
<script src="js/helper.js"></script>
<script src="js/group-call.js"></script>
<script src="js/ably-groupcall.js"></script>
<!-- <script src="js/connection-helper.js"></script> -->
<script src="js/group-connectionhelper.js"></script>
<form action="groups.html" method="GET" id="DisplayNameForm">
<div class="row" style="background-color: rgba(136, 26, 32, 0.53);">
<div class="col-sm-4">
<div class="form-group">
<label style="color: #fff;">Display Name</label>
<input type="text" name="Name" class="form-control" />
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<label> </label>
<button type="submit" class="btn btn-primary btn-block">Update</button>
</div>
</div>
</div>
</form>
<div class="conatainer-fluid" style="margin-top: 3em;">
<div class="row">
<!-- Group-1 -->
<div class="col-sm-3 col-xs-6">
<div class="panel panel-primary" id="Group_1">
<div class="panel-heading" id="Group_1_Heading">
Group-1
</div>
<div class="panel-body">
<h4>Members:</h4>
<div class="people-list"></div>
</div>
<div class="panel-footer">
<button onclick="JoinGroup('Group_1')" class="btn btn-info btn-block">Join</button>
</div>
</div>
</div>
<!-- Group-2 -->
<div class="col-sm-3 col-xs-6">
<div class="panel panel-primary" id="Group_2">
<div class="panel-heading" id="Group_2_Heading">
Group-2
</div>
<div class="panel-body">
<h4>Members:</h4>
<div class="people-list"></div>
</div>
<div class="panel-footer">
<button onclick="JoinGroup('Group_2')" class="btn btn-info btn-block">Join</button>
</div>
</div>
</div>
<!-- Group-3 -->
<div class="col-sm-3 col-xs-6">
<div class="panel panel-primary" id="Group_3">
<div class="panel-heading" id="Group_3_Heading">
Group-3
</div>
<div class="panel-body">
<h4>Members:</h4>
<div class="people-list"></div>
</div>
<div class="panel-footer">
<button onclick="JoinGroup('Group_3')" class="btn btn-info btn-block">Join</button>
</div>
</div>
</div>
<!-- Group-4 -->
<div class="col-sm-3 col-xs-6">
<div class="panel panel-primary" id="Group_4">
<div class="panel-heading" id="Group_4_Heading">
Group-4
</div>
<div class="panel-body">
<h4>Members:</h4>
<div class="people-list"></div>
</div>
<div class="panel-footer">
<button onclick="JoinGroup('Group_4')" class="btn btn-info btn-block">Join</button>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-3 col-xs-12">
<div class="panel panel-default">
<div class="panel-body">
<video id="local" muted style="z-index: 2; width: 100%; min-height: 200px;"></video>
<div class="row">
<div class="col-sm-12">
<div class="col-xs-6">
<h3>Duration:</h3>
<label id="minutes"></label> : <label id="seconds"></label>
</div>
<div class="col-xs-6">
<button class="btn btn-default" onclick="LeaveCurrentGroup()" title="Leave Group">
<img src="asset/hang-up.svg" style="width: 50px; height: 50px; color: #fff;">
</button>
</div>
</div>
<div class="col-sm-12">
<h3 id="CallStatus"></h3>
</div>
<div class="col-sm-12">
<h3 id="GroupStatus"></h3>
</div>
</div>
</div>
</div>
Icons made by <a href="https://www.flaticon.com/authors/dmitri13" title="dmitri13">dmitri13</a> from <a href="https://www.flaticon.com/" title="Flaticon"> www.flaticon.com</a>
</div>
<div class="col-sm-9 col-xs-12" style="margin-bottom: 50px;">
<div id="call" style="position: relative;">
<div class="row" id="GroupMemberVideos">
</div>
</div>
</div>
</div>
</div>
</body>
<style>
.MemberList {
list-style: decimal;
}
</style>
</html>
<script type="text/javascript">
window.onload = function() {
var Name = GetUrlParameter('Name');
if (Name != null && Name != '') {
document.getElementById('DisplayNameForm').style.display = 'none'
}
setTimeout(() => {
UpdateGroupMemeberLists()
}, 5000);
}
function UpdateGroupMemeberLists() {
for (let index = 1; index <= 4; index++) {
GetAvailableMembersInGroup("Group_" + index)
}
}
</script>
通过一些基本的调试,显示连接已建立但没有流
找到问题了。 :)
正在加入群组功能中初始化本地摄像机流。通过在文档加载时初始化本地视频流解决了该问题。
希望这对其他人有帮助。