问题描述
我正在使用Twilio可编程视频JS SDK并遇到一些问题。我已经采用了他们的示例代码,我可以创建一个房间并连接到它,它会触发我的相机/麦克风,但没有任何事件正在触发,处理诸如将视频绑定到DOM,显示事件等事情。
这是基于Angular 1和Ionic Framework构建的Cordova应用程序的一部分。这是我的控制器中的代码:
angular.module('smartlab.controllers')。controller('SupportVideoCtrl',[' $ scope','$ http',函数($ scope,$ http){
//包括Twilio视频库
const Video = Twilio.Video;
//调用我们的cross origin friendlysmartlab云服务器来获取Twilio令牌(它们只能在服务器端生成)
$ http.get('TOKEN_URL',function(data){
})。then(function(data){
console.log(data);
console.log(Token =+ data.data.token);
Video.connect(data.data.token,{name:'Support'})。then(room => {
console.log('Connected to Room%s', room.name);
//以下所有事件都不会触发
room.participants.forEach(participantConnected);
room.on('participantConnected',participantConnected);
room.on('参与antDisconnected',participantDisconnected);
room.once('disconnected',error => room.participants.forEach(participantDisconnected));
});
});
function participantConnected(参与者){
console.log('Participant'%sconnected',participant.identity);
const div = document.createElement('div');
div.id = participant.sid;
div.innerText = participant.identity;
participant.on('trackAdded',track => trackAdded(div,track));
participant.tracks.forEach(track => trackAdded(div,track));
participant.on('trackRemoved',trackRemoved);
console.log(参与者已连接);
console.dir(div);
document.body.appendChild(div);
}
function participantDisconnected(参与者){
console.log('Participant'%sdisconnected',participant.identity);
participant.tracks.forEach(trackRemoved);
document.getElementById(participant.sid).remove();
}
函数trackAdded(div,track){
console.log(Track added);
console.dir(div);
console.dir(track);
div.appendChild(track.attach());
}
function trackRemoved(track){
track.detach()。forEach(element => element.remove());
}
}]);
是否有人使用过这个库,并有一些示例代码可以从代码中抽取或查看错误代码以上?我已经检查了他们的示例NodeJS应用程序,但它与我在这里的实现完全不同,所以它不是非常有用。谢谢!
经过大量的试验和错误+一些来回与伟大的我有一个很好的解决方案。现在,这是我们使用构建的Cordova移动应用程序的一部分。
HTML:
< ion-view class =app-tabhide-nav-bar =true view-title =支持>
< ion-content class =padding>
< h3 class =tab-header-text>实时视频支持< / h3>
< div id =call-connected>已连接到Live Tech Support< / div>
< div id =controls>
< div id =previewstyle =float:left;>
< div id =local-media>< / div>
< button id =button-previewstyle =margin-left:40px;>预览我的相机< / button>
< / div>
< div id =call-controlsclass =call-button-div>
< i id =button-callclass =icon ion-ios-telephone-outline call-buttonsstyle =color:green;>< / i>
< i id =button-call-endclass =icon ion-ios-telephone-outline call-buttonsstyle =color:red; display:none;>< / i>
< / div>
< / div>
< div id =spin-wrapper>< ion-spinner name =circles>< / ion-spinner>< / div>
< div id =remote-media>
< div id =video-overlay> Nicholas Kreidberg< / div>
< / div>
< / ion-content>
< / ion-view>
JS:
angular.module('PROJECT_NAME.controllers')。controller('SupportVideoCtrl',['$ rootScope','$ scope','$ http',函数($ rootScope,$ scope,$ http){
//实例化Twilio可编程视频库
const视频= Twilio.Video;
//设置一些变量
var activeRoom;
var previewTracks;
var identity;
var roomName;
//将曲目附加到DOM。
函数attachTracks(曲目,容器){
tracks.forEach(function(track){
container.appendChild(track.attach());
});
}
//附上参与者的曲目到$ DOM。
函数attachParticipantTracks(参与者,容器){
var tracks = Array.from(participant.tracks.values());
attachTracks(tracks,container);
}
//从DOM中删除曲目。
function detachTracks(tracks){
tracks.forEach(function(track){
track.detach()。forEach(function(detachedElement){
detachedElement.remove();
});
});
}
//从DOM中分离参与者的曲目。
function detachParticipantTracks(参与者){
var tracks = Array.from(participant.tracks.values());
detachTracks(曲目);
}
//当我们即将离开此页面时,如果加入,请从房间断开
//。
window.addEventListener('beforeunload',leaveRoomIfJoined);
$ rootScope。$ on('$ stateChangeSuccess',
function(event,toState,toParams,fromState,fromParams){
leaveRoomIfJoined();
}
);
$ http.get('TOKEN_URL',函数(数据){
})。然后(函数(数据){
console.log(data) ;
console.log(Token =+ data.data.token);
//document.getElementById('room-controls').style.display ='block';
//绑定点击事件并将令牌添加到数据属性
document.getElementById('button-call')。addEventListener('click',connect);
document.getElementById ('button-call')。setAttribute('data-token',data.data.token);
//连接
connect();
//绑定按钮离开Room。
document.getElementById('button-call-end')。onclick = function(){
log('Disconnecting ...');
document .getElementById('call-connected')。style.display ='none';
document.getElementById('spin-wrapper')。style.display ='none';
document.getEleme ntById('button-preview')。style.display ='block';
document.getElementById('video-overlay')。style.display ='none';
activeRoom.disconnect();
};
});
function connect(){
roomName ='Support';
log(Joining room'+ roomName +'...);
token = document.getElementById('button-call')。getAttribute('data-token');
console.log(令牌:+令牌);
var connectOptions = {
name:'Support',
logLevel:'debug'
};
if(previewTracks){
connectOptions.tracks = previewTracks;
}
//使用来自服务器的令牌和
// LocalParticipant的曲目加入会议室。
Video.connect(token,connectOptions).then(roomJoined,function(error){
log('无法连接到Twilio:'+ error.message);
});
document.getElementById('call-connected')。style.display ='block';
document.getElementById('spin-wrapper')。style.display ='inline-flex';
document.getElementById('button-preview')。style.display ='none';
}
//成功连接!
function roomJoined(room){
window.room = activeRoom = room;
log(加入为+ identity +');
document.getElementById('button-call')。style.display ='none';
document.getElementById('button-call-end')。style.display ='inline';
//附加LocalParticipant的曲目(如果尚未附加)。
var previewContainer = document.getElementById('local-media');
if(!previewContainer.querySelector('video')){
attachParticipantTracks(room.localParticipant,previewContainer);
}
//附上会议室参与者的曲目。
room.participants.forEach(函数(参与者){
log(已经在房间:'+ participant.identity +');
var previewContainer = document.getElementById(' remote-media');
attachParticipantTracks(参与者,previewContainer);
});
//当参与者加入会议室时,记录该活动。
room.on('participantConnected',函数(参与者){
//document.getElementById('remote-media').style.display ='inline';
log(加入:'\\ t'+。Particip.identity +');
});
//当参与者添加一个Track时,将其附加到DOM。
room.on('trackAdded',function(track,participant){
log(participant.identity +added track:+ track.kind);
var previewContainer = document.getElementById ('remote-media');
document.getElementById('spin-wrapper')。style.display ='none';
document.getElementById('video-overlay')。style.display = 'flex';
attachTracks([track],previewContainer);
});
//当参与者删除一个Track时,将其从DOM中分离出来。
room.on('trackRemoved',函数(曲目,参与者){
log(participant.identity +删除曲目:+ track.kind);
detachTracks([track]) ;
});
//当参与者离开房间时,分离其曲目。
room.on('participantDisconnected',函数(参与者){
log(参与者'+参与者身份+离开房间);
detachParticipantTracks(参与者);
});
//一旦LocalParticipant离开房间,分离所有参与者的轨道
//,包括LocalParticipant的轨道。
room.on('disconnected',function(){
log('Left');
if(previewTracks){
previewTracks.forEach(function(track){
track.stop();
});
}
detachParticipantTracks(room.localParticipant);
room.participants.forEach(detachParticipantTracks);
activeRoom = null;
document.getElementById('button-call')。style.display ='inline';
document.getElementById('button-call-end')。style.display ='none' ;
document.getElementById('spin-wrapper')。style.display ='none';
});
}
//预览LocalParticipant的曲目。
document.getElementById('button-preview')。onclick = function(){
var localTracksPromise = previewTracks
? Promise.resolve(previewTracks)
:Video.createLocalTracks();
localTracksPromise.then(function(tracks){
window.previewTracks = previewTracks = tracks;
var previewContainer = document.getElementById('local-media');
if(!previewContainer.querySelector('video')){
attachTracks(tracks,previewContainer);
}
},function(error){
console.error('无法访问本地媒体',错误);
log('无法访问摄像头和麦克风');
});
};
document.getElementById('mute')。onclick = function(){
console.dir(room.localParticipant);
room.localParticipant.audioTracks.disable();
};
//活动日志。
函数日志(消息){
console.dir(message);
返回false;
var logDiv = document.getElementById('log');
logDiv.innerHTML + ='< p>& gt;& nbsp;'+ message +'< / p>';
logDiv.scrollTop = logDiv.scrollHeight;
}
//离开房间。
函数leaveRoomIfJoined(){
if(activeRoom){
activeRoom.disconnect();
}
}
}]);
我希望这有助于其他希望将Twilio视频与他们的项目集成的混合移动开发者! / p>
I am using the Twilio programmable video JS SDK and having some issues. I have taken their sample code and I am able to create a room and connect to it which does trigger my camera/mic but none of the events are firing which handle things like binding video to the DOM, showing events, etc.
This is part of an Cordova app built on Angular 1 and the Ionic Framework. Here's the code in my controller:
angular.module('smartlab.controllers').controller('SupportVideoCtrl', ['$scope', '$http', function($scope, $http) {
// include Twilio Video library
const Video = Twilio.Video;
// call our "cross origin friendly" smartlab cloud server to get Twilio token (they can only be generated server-side)
$http.get('TOKEN_URL', function(data) {
}).then(function(data) {
console.log(data);
console.log("Token = " + data.data.token);
Video.connect(data.data.token, { name: 'Support' }).then(room => {
console.log('Connected to Room "%s"', room.name);
// None of the events below fire
room.participants.forEach(participantConnected);
room.on('participantConnected', participantConnected);
room.on('participantDisconnected', participantDisconnected);
room.once('disconnected', error => room.participants.forEach(participantDisconnected));
});
});
function participantConnected(participant) {
console.log('Participant "%s" connected', participant.identity);
const div = document.createElement('div');
div.id = participant.sid;
div.innerText = participant.identity;
participant.on('trackAdded', track => trackAdded(div, track));
participant.tracks.forEach(track => trackAdded(div, track));
participant.on('trackRemoved', trackRemoved);
console.log("Participant Connected");
console.dir(div);
document.body.appendChild(div);
}
function participantDisconnected(participant) {
console.log('Participant "%s" disconnected', participant.identity);
participant.tracks.forEach(trackRemoved);
document.getElementById(participant.sid).remove();
}
function trackAdded(div, track) {
console.log("Track added");
console.dir(div);
console.dir(track);
div.appendChild(track.attach());
}
function trackRemoved(track) {
track.detach().forEach(element => element.remove());
}
}]);
Has anybody used this library and have some sample code to draw from or see anything wrong w/ the code above? I have checked out their sample NodeJS app but it is quite different than my implementation here so it isn't super useful. Thanks!
After a lot of trial and error + some back and forth with the great Phil Nash I have a well working solution. This is now part of our Cordova Mobile App built with the Ionic Framework.
HTML:
<ion-view class="app-tab" hide-nav-bar="true" view-title="Support">
<ion-content class="padding">
<h3 class="tab-header-text">Live Video Support</h3>
<div id="call-connected">Connected to Live Tech Support</div>
<div id="controls">
<div id="preview" style="float:left;">
<div id="local-media"></div>
<button id="button-preview" style="margin-left:40px;">Preview My Camera</button>
</div>
<div id="call-controls" class="call-button-div">
<i id="button-call" class="icon ion-ios-telephone-outline call-buttons" style="color:green;"></i>
<i id="button-call-end" class="icon ion-ios-telephone-outline call-buttons" style="color:red; display:none;"></i>
</div>
</div>
<div id="spin-wrapper"><ion-spinner name="circles"></ion-spinner></div>
<div id="remote-media">
<div id="video-overlay">Nicholas Kreidberg</div>
</div>
</ion-content>
</ion-view>
JS:
angular.module('PROJECT_NAME.controllers').controller('SupportVideoCtrl', ['$rootScope', '$scope', '$http', function($rootScope, $scope, $http) {
// instantiate Twilio Programmable Video library
const Video = Twilio.Video;
// setup some vars
var activeRoom;
var previewTracks;
var identity;
var roomName;
// Attach the Tracks to the DOM.
function attachTracks(tracks, container) {
tracks.forEach(function(track) {
container.appendChild(track.attach());
});
}
// Attach the Participant's Tracks to the DOM.
function attachParticipantTracks(participant, container) {
var tracks = Array.from(participant.tracks.values());
attachTracks(tracks, container);
}
// Detach the Tracks from the DOM.
function detachTracks(tracks) {
tracks.forEach(function(track) {
track.detach().forEach(function(detachedElement) {
detachedElement.remove();
});
});
}
// Detach the Participant's Tracks from the DOM.
function detachParticipantTracks(participant) {
var tracks = Array.from(participant.tracks.values());
detachTracks(tracks);
}
// When we are about to transition away from this page, disconnect
// from the room, if joined.
window.addEventListener('beforeunload', leaveRoomIfJoined);
$rootScope.$on('$stateChangeSuccess',
function(event, toState, toParams, fromState, fromParams) {
leaveRoomIfJoined();
}
);
$http.get('TOKEN_URL', function(data) {
}).then(function(data) {
console.log(data);
console.log("Token = " + data.data.token);
//document.getElementById('room-controls').style.display = 'block';
// Bind click event and add token to data attribute
document.getElementById('button-call').addEventListener('click', connect);
document.getElementById('button-call').setAttribute('data-token', data.data.token);
// Connect
connect();
// Bind button to leave Room.
document.getElementById('button-call-end').onclick = function() {
log('Disconnecting...');
document.getElementById('call-connected').style.display = 'none';
document.getElementById('spin-wrapper').style.display = 'none';
document.getElementById('button-preview').style.display = 'block';
document.getElementById('video-overlay').style.display = 'none';
activeRoom.disconnect();
};
});
function connect() {
roomName = 'Support';
log("Joining room '" + roomName + "'...");
token = document.getElementById('button-call').getAttribute('data-token');
console.log("Token: "+token);
var connectOptions = {
name: 'Support',
logLevel: 'debug'
};
if (previewTracks) {
connectOptions.tracks = previewTracks;
}
// Join the Room with the token from the server and the
// LocalParticipant's Tracks.
Video.connect(token, connectOptions).then(roomJoined, function(error) {
log('Could not connect to Twilio: ' + error.message);
});
document.getElementById('call-connected').style.display = 'block';
document.getElementById('spin-wrapper').style.display = 'inline-flex';
document.getElementById('button-preview').style.display = 'none';
}
// Successfully connected!
function roomJoined(room) {
window.room = activeRoom = room;
log("Joined as '" + identity + "'");
document.getElementById('button-call').style.display = 'none';
document.getElementById('button-call-end').style.display = 'inline';
// Attach LocalParticipant's Tracks, if not already attached.
var previewContainer = document.getElementById('local-media');
if (!previewContainer.querySelector('video')) {
attachParticipantTracks(room.localParticipant, previewContainer);
}
// Attach the Tracks of the Room's Participants.
room.participants.forEach(function(participant) {
log("Already in Room: '" + participant.identity + "'");
var previewContainer = document.getElementById('remote-media');
attachParticipantTracks(participant, previewContainer);
});
// When a Participant joins the Room, log the event.
room.on('participantConnected', function(participant) {
//document.getElementById('remote-media').style.display = 'inline';
log("Joining: '" + participant.identity + "'");
});
// When a Participant adds a Track, attach it to the DOM.
room.on('trackAdded', function(track, participant) {
log(participant.identity + " added track: " + track.kind);
var previewContainer = document.getElementById('remote-media');
document.getElementById('spin-wrapper').style.display = 'none';
document.getElementById('video-overlay').style.display = 'flex';
attachTracks([track], previewContainer);
});
// When a Participant removes a Track, detach it from the DOM.
room.on('trackRemoved', function(track, participant) {
log(participant.identity + " removed track: " + track.kind);
detachTracks([track]);
});
// When a Participant leaves the Room, detach its Tracks.
room.on('participantDisconnected', function(participant) {
log("Participant '" + participant.identity + "' left the room");
detachParticipantTracks(participant);
});
// Once the LocalParticipant leaves the room, detach the Tracks
// of all Participants, including that of the LocalParticipant.
room.on('disconnected', function() {
log('Left');
if (previewTracks) {
previewTracks.forEach(function(track) {
track.stop();
});
}
detachParticipantTracks(room.localParticipant);
room.participants.forEach(detachParticipantTracks);
activeRoom = null;
document.getElementById('button-call').style.display = 'inline';
document.getElementById('button-call-end').style.display = 'none';
document.getElementById('spin-wrapper').style.display = 'none';
});
}
// Preview LocalParticipant's Tracks.
document.getElementById('button-preview').onclick = function() {
var localTracksPromise = previewTracks
? Promise.resolve(previewTracks)
: Video.createLocalTracks();
localTracksPromise.then(function(tracks) {
window.previewTracks = previewTracks = tracks;
var previewContainer = document.getElementById('local-media');
if (!previewContainer.querySelector('video')) {
attachTracks(tracks, previewContainer);
}
}, function(error) {
console.error('Unable to access local media', error);
log('Unable to access Camera and Microphone');
});
};
document.getElementById('mute').onclick = function() {
console.dir(room.localParticipant);
room.localParticipant.audioTracks.disable();
};
// Activity log.
function log(message) {
console.dir(message);
return false;
var logDiv = document.getElementById('log');
logDiv.innerHTML += '<p>> ' + message + '</p>';
logDiv.scrollTop = logDiv.scrollHeight;
}
// Leave Room.
function leaveRoomIfJoined() {
if (activeRoom) {
activeRoom.disconnect();
}
}
}]);
I hope this helps other hybrid mobile developers out there who want to integrate Twilio video with their project!
这篇关于Twilio可编程视频JS / Ionic的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!