<script type="text/javascript">
var rand = <?php echo rand(1111111,9999999); ?>;
function ready() {
//Setup publish button
let pubBtn = document.getElementById('publishBtn');
if (pubBtn) {
pubBtn.onclick = evt => {
startAgoraBroadcast();
};
}
//Get users camera and mic
getMedia()
.then(str => {
stream = str;
//set cam feed to video window so user can see self.
let vidWin = document.getElementsByTagName('video')[0];
if (vidWin) {
$('#basic-stream').removeClass('hidden');
$('.wow_go_live_btn').removeClass('hidden');
//$('.end_vdo_call').removeClass('hidden');
vidWin.srcObject = stream;
//startBroadcast();
}
})
.catch(e => {
$('#remote-media').html('<div class="empty_state"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M3.27,2L2,3.27L4.73,6H4A1,1 0 0,0 3,7V17A1,1 0 0,0 4,18H16C16.2,18 16.39,17.92 16.54,17.82L19.73,21L21,19.73M21,6.5L17,10.5V7A1,1 0 0,0 16,6H9.82L21,17.18V6.5Z" fill="currentColor"></path></svg> getUserMedia Error: '+e+'</div>');
});
}
function getCameraDevices() {
console.log("Checking for Camera Devices.....")
client.getCameras (function(cameras) {
devices.cameras = cameras; // store cameras array
cameras.forEach(function(camera, i){
//var name = camera.label.split('(')[0];
var name = camera.label;
var optionId = 'camera_' + i;
var deviceId = camera.deviceId;
if(i === 0 && localStreams.camera.camId === ''){
localStreams.camera.camId = deviceId;
}
$('#camera-list').append('<div class="dropdown-item pointer" id="' + optionId + '">' + name + '</div>');
});
$('#camera-list .dropdown-menu div').click(function(event) {
var index = event.target.id.split('_')[1];
changeStreamSource (index, "video");
});
});
}
function getMicDevices() {
console.log("Checking for Mic Devices.....")
client.getRecordingDevices(function(mics) {
devices.mics = mics; // store mics array
mics.forEach(function(mic, i){
//var name = mic.label.split('(')[0];
var name = mic.label;
var optionId = 'mic_' + i;
var deviceId = mic.deviceId;
if(i === 0 && localStreams.camera.micId === ''){
localStreams.camera.micId = deviceId;
}
if(name.split('Default - ')[1] != undefined) {
name = '[Default Device]' // rename the default mic - only appears on Chrome & Opera
}
$('#mic-list').append('<div class="dropdown-item pointer" id="' + optionId + '">' + name + '</div>');
});
$('#mic-list .dropdown-menu div').click(function(event) {
var index = event.target.id.split('_')[1];
changeStreamSource (index, "audio");
});
});
}
function changeStreamSource (deviceIndex, deviceType) {
console.log('Switching stream sources for: ' + deviceType);
var deviceId;
var existingStream = false;
if (deviceType === "video") {
deviceId = devices.cameras[deviceIndex].deviceId
}
if(deviceType === "audio") {
deviceId = devices.mics[deviceIndex].deviceId;
}
localStreams.camera.stream.switchDevice(deviceType, deviceId, function(){
console.log('successfully switched to new device with id: ' + JSON.stringify(deviceId));
// set the active device ids
if(deviceType === "audio") {
localStreams.camera.micId = deviceId;
} else if (deviceType === "video") {
localStreams.camera.camId = deviceId;
} else {
console.log("unable to determine deviceType: " + deviceType);
}
}, function(){
console.log('failed to switch to new device with id: ' + JSON.stringify(deviceId));
});
}
var agoraAppId = '<?php echo($config["agora_app_id"]) ?>'; // set app id
var channelName = "stream_<?php echo($me['user_id']) ?>_"+rand; // set channel name
// create client instance
var client = AgoraRTC.createClient({mode: 'live', codec: 'vp8'}); // h264 better detail at a higher motion
var mainStreamId; // reference to main stream
// set video profile
// [full list: https://docs.agora.io/en/Interactive%20Broadcast/videoProfile_web?platform=Web#video-profile-table]
var cameraVideoProfile = '720p_6'; // 960 × 720 @ 30fps & 750kbs
// keep track of streams
var localStreams = {
uid: rand,
camera: {
camId: '',
micId: '',
stream: {}
}
};
// keep track of devices
var devices = {
cameras: [],
mics: []
}
var externalBroadcastUrl = '';
// default config for rtmp
var defaultConfigRTMP = {
width: 640,
height: 360,
videoBitrate: 400,
videoFramerate: 15,
lowLatency: false,
audioSampleRate: 48000,
audioBitrate: 48,
audioChannels: 1,
videoGop: 30,
videoCodecProfile: 100,
userCount: 0,
userConfigExtraInfo: {},
backgroundColor: 0x000000,
transcodingUsers: [],
};
// set log level:
// -- .DEBUG for dev
// -- .NONE for prod
AgoraRTC.Logger.setLogLevel(AgoraRTC.Logger.DEBUG);
// init Agora SDK
function startAgoraBroadcast() {
client.init(agoraAppId, function () {
console.log('AgoraRTC client initialized');
joinChannel(); // join channel upon successfull init
}, function (err) {
console.log('[ERROR] : AgoraRTC client init failed', err);
});
}
// client callbacks
client.on('stream-published', function (evt) {
console.log('Publish local stream successfully');
});
// when a remote stream is added
client.on('stream-added', function (evt) {
console.log('new stream added: ' + evt.stream.getId());
});
client.on('stream-removed', function (evt) {
var stream = evt.stream;
stream.stop(); // stop the stream
stream.close(); // clean up and close the camera stream
console.log("Remote stream is removed " + stream.getId());
});
//live transcoding events..
client.on('liveStreamingStarted', function (evt) {
console.log("Live streaming started");
});
client.on('liveStreamingFailed', function (evt) {
console.log("Live streaming failed");
});
client.on('liveStreamingStopped', function (evt) {
console.log("Live streaming stopped");
});
client.on('liveTranscodingUpdated', function (evt) {
console.log("Live streaming updated");
});
// ingested live stream
client.on('streamInjectedStatus', function (evt) {
console.log("Injected Steram Status Updated");
console.log(JSON.stringify(evt));
});
// when a remote stream leaves the channel
client.on('peer-leave', function(evt) {
console.log('Remote stream has left the channel: ' + evt.stream.getId());
});
// show mute icon whenever a remote has muted their mic
client.on('mute-audio', function (evt) {
console.log('Mute Audio for: ' + evt.uid);
});
client.on('unmute-audio', function (evt) {
console.log('Unmute Audio for: ' + evt.uid);
});
// show user icon whenever a remote has disabled their video
client.on('mute-video', function (evt) {
console.log('Mute Video for: ' + evt.uid);
});
client.on('unmute-video', function (evt) {
console.log('Unmute Video for: ' + evt.uid);
});
// join a channel
function joinChannel() {
var token = generateToken();
var userID = 0; // set to null to auto generate uid on successfull connection
// set the role
client.setClientRole('host', function() {
console.log('Client role set as host.');
}, function(e) {
console.log('setClientRole failed', e);
});
//client.join(token, 'allThingsRTCLiveStream', 0, function(uid) {
client.join(token, channelName, userID, function(uid) {
createCameraStream(uid, {});
localStreams.uid = uid; // keep track of the stream uid
console.log('User ' + uid + ' joined channel successfully');
$('#main_live_video').html('')
$('#publishBtn').removeAttr('disabled');
$('#publishBtn').text("{{LANG please_wait}}");
$('#publishBtn').addClass('hidden');
$('.end_vdo_call').removeClass('hidden');
$.post(link('live/create'), {stream_name: channelName}, function(data, textStatus, xhr) {
if (data.status == 200) {
$('#live_post_id').val(data.post_id);
$('.live_mic_cam_switch').slideDown();
setTimeout(function () {
image = capture_video_frame("video"+uid, 'png');
var thumb = new File([base64_2_blob(image.dataUri)], "thumb.png", {type:"image/png"});
var formData = new FormData();
formData.append('thumb',thumb);
formData.append('post_id',data.post_id);
$.ajax({
processData: false,
url: link('live/create_thumb') + '?hash=<?php echo($context["csrf_token"]);?>',
type: 'POST',
dataType: 'json',
data: formData,
contentType: false,
})
.done(function() {
console.log("success");
})
.fail(function() {
console.log("error");
})
.always(function() {
console.log("complete");
});
},500);
}
});
}, function(err) {
console.log('[ERROR] : join channel failed', err);
});
}
// video streams for channel
function createCameraStream(uid, deviceIds) {
console.log('Creating stream with sources: ' + JSON.stringify(deviceIds));
var localStream = AgoraRTC.createStream({
streamID: uid,
audio: true,
video: true,
screen: false
});
localStream.setVideoProfile(cameraVideoProfile);
// The user has granted access to the camera and mic.
localStream.on("accessAllowed", function() {
if(devices.cameras.length === 0 && devices.mics.length === 0) {
console.log('[DEBUG] : checking for cameras & mics');
getCameraDevices();
getMicDevices();
}
console.log("accessAllowed");
});
// The user has denied access to the camera and mic.
localStream.on("accessDenied", function() {
console.log("accessDenied");
});
localStream.init(function() {
console.log('getUserMedia successfully');
$('#main_live_video').html('')
localStream.play('main_live_video'); // play the local stream on the main div
// publish local stream
client.publish(localStream, function (err) {
console.log('[ERROR] : publish local stream error: ' + err);
});
localStreams.camera.stream = localStream; // keep track of the camera stream for later
}, function (err) {
console.log('[ERROR] : getUserMedia failed', err);
});
}
// use tokens for added security
function generateToken() {
return null; // TODO: add a token generation
}
</script>