Skip to content

Instantly share code, notes, and snippets.

@shah-smit
Created July 16, 2017 08:54
Show Gist options
  • Save shah-smit/dd0a16f7069a60b25d4dc59afbe18597 to your computer and use it in GitHub Desktop.
Save shah-smit/dd0a16f7069a60b25d4dc59afbe18597 to your computer and use it in GitHub Desktop.
Angular 4, Live Streaming
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router } from '@angular/router';
import { LoginService, AzureService } from '../services'
import { User, LiveSession } from '../models'
import { SharedService } from "app/services/shared.service";
//declare var SimpleWebRTC;
declare var io;
declare var conference;
@Component({
selector: 'live-multi-video',
templateUrl: 'live-multi-video.component.html',
styleUrls: ['live-multi-video.component.css']
})
export class LiveMultiVideoComponent implements OnInit, OnDestroy {
connection;
studentsContainer;
currentStudentContainer;
tutorContainer;
config;
conferenceUI;
session: string;
currentUser: User;
onlineUsers: LiveSession[];
liveSession: LiveSession;
cudySocket;
localStream;
isMute;
constructor(private loginService: LoginService, private router: Router, private azureService: AzureService,private sharedService: SharedService) { }
ngOnInit() {
this.isMute = false;
this.currentUser = this.sharedService.currentUser;
this.onlineUsers = new Array<LiveSession>();
this.liveSession = new LiveSession();
if (this.currentUser && this.currentUser != undefined && this.currentUser.id != undefined && this.currentUser.name != undefined && this.sharedService.selectedProgrammeWrapper.programme.id) {
console.log("currentUser", this.currentUser);
console.log("SelectProgrammeID", this.sharedService.selectedProgrammeWrapper.programme)
this.liveSession.programmeId = this.sharedService.selectedProgrammeWrapper.programme.id
this.liveSession.roomName = this.liveSession.programmeId;
this.liveSession.channelId = this.liveSession.programmeId;
this.liveSession.userId = this.currentUser.id;
this.liveSession.userName = this.currentUser.name;
this.liveSession.isTutor = this.currentUser.role == 'tutor' ? true : false;
this.setup();
}
}
setup() {
var self = this;
self.studentsContainer = document.getElementById('students-container');
self.tutorContainer = document.getElementById('tutor-container');
self.currentStudentContainer = document.getElementById('current-student-container')
var roomsList = document.getElementById('rooms-list')
if (self.currentUser.role == 'tutor') {
document.getElementById('setup-new-room').style.display = 'block';
document.getElementById('waiting-for-teacher-message').style.display = "none"
}
else {
document.getElementById('session').style.display = "block";
roomsList.style.display = "block";
}
self.config = {
openSocket: function (config) {
var SIGNALING_SERVER = 'https://cudy-socketio-over-nodejs.herokuapp.com:443/',
//var SIGNALING_SERVER = 'http://localhost:5000/',
defaultChannel = location.href.replace(/\/|:|#|%|\.|\[|\]/g, '');
var channel = config.channel || self.liveSession.channelId || defaultChannel;
console.log("channel sent:", channel)
var sender = self.liveSession.userId;
console.log("sender sent:", sender);
io.connect(SIGNALING_SERVER).emit('new-channel', {
channel: channel,
sender: sender
});
var socket = io.connect(SIGNALING_SERVER + channel);
socket.channel = channel;
socket.on('connect', function () {
console.log("socket connect", socket)
if (config.callback) config.callback(socket);
});
socket.send = function (message) {
console.log("socket send message", {
sender: sender,
data: message
})
socket.emit('message', {
sender: sender,
data: message
});
};
socket.on('message', (msg) => {
console.log("socket on message", msg);
config.onmessage(msg);
});
socket.on('user-video-stream', (msg) => {
console.log("socket on user-video-stream", msg);
self.onlineUsers = JSON.parse(msg);
});
self.cudySocket = socket;
},
onRemoteStream: function (media) {
var video = media.video;
console.log("ON REMOTE STREAM FOUND", media)
console.log("ONLINE USERS: ", self.onlineUsers);
self.onlineUsers.forEach((element) => {
if (element.isTutor == true && element.videoId == media.stream.id) {
document.getElementById('waiting-for-teacher-message').style.display = "none"
console.log("is tutor")
video.setAttribute('controls', true);
video.setAttribute('id', media.stream.id);
video.height = 700;
video.width = 700;
self.tutorContainer.insertBefore(video, self.tutorContainer.firstChild);
video.play();
}
else {
document.getElementById('waiting-for-student-message').style.display = "none"
video.setAttribute('controls', true);
video.setAttribute('id', media.stream.id);
video.height = 300;
video.width = 300;
self.studentsContainer.insertBefore(video, self.studentsContainer.firstChild);
video.play();
}
})
},
onRemoteStreamEnded: function (stream) {
console.log("onRemoteStreamEnded", stream)
var video = document.getElementById(stream.id);
if (video) video.parentNode.removeChild(video);
},
onRoomFound: function (room) {
console.log("on room found", room)
var alreadyExist = document.querySelector('button[data-broadcaster="' + room.broadcaster + '"]');
if (alreadyExist) return;
if (room.roomName == self.liveSession.roomName) {
var tr = document.createElement('tr');
tr.innerHTML = '<td><strong>' + room.roomName + '</strong> has been started, do you wish to continue?!</td>' +
'<td><button class="join">Join</button></td>';
roomsList.insertBefore(tr, roomsList.firstChild);
var joinRoomButton = <any>tr.querySelector('.join');
joinRoomButton.setAttribute('data-broadcaster', room.broadcaster);
joinRoomButton.setAttribute('data-roomToken', room.broadcaster);
joinRoomButton.onclick = function () {
var result = confirm(`With respect to documents available from this server, neither Cudy.co nor any of its employees, makes any warranty, express or implied, including the warranties of merchantability and fitness for a particular purpose, or assumes any legal liability or responsibility for the accuracy, completeness, or usefulness of any information, apparatus, product, or process disclosed, or represents that its use would not infringe privately owned rights.
Information from this server resides on a computer system funded by Cudy.co. The use of this system may be monitored for computer security purposes. Any unauthorised access to this system is prohibited and is subject to criminal and civil penalties.
The User understands that Cudy.co merely provides the relevant Web Services, and that the User is solely responsible for his/her own required equipment (such as PC, cell phone or any other devices used for connecting to the internet or cellular network) relevant to these Web Services, as well as the necessary costs (such as telephone or internet charges for internet connection and cell phone charges for cellular network usage) thereof.`);
if (result) {
this.disabled = true;
console.log("room broadcaster: ", room.broadcaster)
var broadcaster = this.getAttribute('data-broadcaster');
var roomToken = this.getAttribute('data-roomToken');
self.captureUserMedia(function () {
self.conferenceUI.joinRoom({
roomToken: roomToken,
joinUser: broadcaster
});
});
}
else{
console.log("user clicked cancel")
}
};
}
}
};
self.conferenceUI = conference(self.config);
console.log();
document.getElementById('setup-new-room').onclick = function () {
// if the ok button is clicked, result will be true (boolean)
var result = confirm(`With respect to documents available from this server, neither Cudy.co nor any of its employees, makes any warranty, express or implied, including the warranties of merchantability and fitness for a particular purpose, or assumes any legal liability or responsibility for the accuracy, completeness, or usefulness of any information, apparatus, product, or process disclosed, or represents that its use would not infringe privately owned rights.
Information from this server resides on a computer system funded by Cudy.co. The use of this system may be monitored for computer security purposes. Any unauthorised access to this system is prohibited and is subject to criminal and civil penalties.
The User understands that Cudy.co merely provides the relevant Web Services, and that the User is solely responsible for his/her own required equipment (such as PC, cell phone or any other devices used for connecting to the internet or cellular network) relevant to these Web Services, as well as the necessary costs (such as telephone or internet charges for internet connection and cell phone charges for cellular network usage) thereof.`);
if (result) {
document.getElementById('session').style.display = "block";
document.getElementById('setup-new-room').hidden = true;
self.captureUserMedia(function () {
console.log(self.liveSession.roomName)
self.conferenceUI.createRoom({
roomName: self.liveSession.roomName
});
});
} else {
console.log('cancel was encountered')
}
};
}
addOnlineUsers(sender) {
var userExists = false;
this.onlineUsers.forEach(element => {
if (element == sender) userExists = true;
})
if (!userExists) this.onlineUsers.push(sender);
}
captureUserMedia(callback) {
var self = this;
var video = document.getElementById('current-student-container')
video.setAttribute('autoplay', 'true');
//self.currentStudentContainer.insertBefore(video, self.currentStudentContainer.firstChild);
self.getUserMedia({
video: video,
onsuccess: function (stream) {
self.config.attachStream = stream;
self.config.attachStream.tutor = self.getRandom();
video.setAttribute('muted', 'true');
callback();
}
});
}
functionguid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
getUserMedia(options) {
var muteButton = document.getElementById('mute-button');
var self = this;
var n = navigator,
media;
//n.getUserMedia = n.mediaDevices.getUserMedia || n.getUserMedia;
var video_constraints = {
mandatory: {},
optional: []
};
n.getUserMedia(options.constraints || {
audio: true,
video: video_constraints
}, streaming, options.onerror || function (e) {
console.error(e);
});
function streaming(stream) {
var video = options.video;
self.liveSession.videoId = stream.id;
self.liveSession.status = "online";
console.log("user-video-stream emit", {
sender: self.liveSession.userId,
data: self.liveSession
})
self.cudySocket.emit('user-video-stream', {
sender: self.liveSession.userId,
data: self.liveSession
})
if (!stream.stop && stream.getTracks) {
stream.stop = function () {
this.getTracks().forEach(function (track) {
track.stop();
});
};
}
self.localStream = stream;
if (video) {
video['src'] = window.URL.createObjectURL(stream);
video.height = 300;
video.width = 300;
video.play();
}
options.onsuccess && options.onsuccess(stream);
media = stream;
muteButton.style.display = 'block';
}
return media;
}
getRandom() {
var bools = [true, false]
var x = Math.floor((Math.random() * 2));
return bools[x];
}
toggleMic() { // stream is your local WebRTC stream
var stream = this.localStream;
console.log(stream)
var audioTracks = stream.getAudioTracks();
for (var i = 0, l = audioTracks.length; i < l; i++) {
audioTracks[i].enabled = !audioTracks[i].enabled;
if (audioTracks[i].enabled) this.isMute = false;
else this.isMute = true;
}
}
ngOnDestroy() {
if (this.localStream) this.localStream.stop();
}
canDeactivate() {
var result = confirm("Are you sure you want to exit? - This may lead loss of connection")
// if the editName !== this.user.name
if (result) {
if (this.cudySocket) this.cudySocket.socket.disconnect();
if (this.localStream) this.localStream.stop();
return true;
}
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment