I have this script:
//import $ from 'https://code.jquery.com/jquery-3.5.1.min.js';
//import JitsiMeetJS from 'https://meet.jit.si/libs/lib-jitsi-meet.min.js';
// import JitsiMeetJS from 'https://esm.sh/lib-jitsi-meet@1.0.6';
/* global $, JitsiMeetJS */
class Video {
constructor(roomId) {
this.roomId = roomId.replace(':', '-');
this.domain = 'meet.jit.si';
this.initOptions = {
disableAudioLevels: true
};
this.conferenceOptions = {
p2p: {
enabled: false
}
};
this.connectionOptions = {
// window.location.protocol === 'https:' ? 'wss://' : 'ws://'
serviceUrl: `${window.location.protocol}//${this.domain}/http-bind?room=${this.roomId}`,
hosts: {
domain: this.domain,
muc: `conference.${this.domain}`,
focus: `focus.${this.domain}`
},
clientNode: `${window.location.protocol}://jitsi.org/jitsimeet`
};
this.connection = null;
this.isJoined = false;
this.room = null;
this.localTracks = [];
this.remoteTracks = {};
this.isVideo = true;
this.unload = this.unload.bind(this);
this.onConnectionSuccess = this.onConnectionSuccess.bind(this);
this.onConnectionFailed = this.onConnectionFailed.bind(this);
this.onDeviceListChanged = this.onDeviceListChanged.bind(this);
this.disonnect = this.disconnect.bind(this);
this.onLocalTracks = this.onLocalTracks.bind(this);
this.onRemoteTrack = this.onRemoteTrack.bind(this);
this.onConferenceJoined = this.onConferenceJoined.bind(this);
this.onUserLeft = this.onUserLeft.bind(this);
this.getPhoneNumber = this.getPhoneNumber.bind;
}
setupJitsi() {
window.addEventListener('beforeunload', this.unload);
window.addEventListener('unload', this.unload);
// todo: support import jitsi lib here
JitsiMeetJS.init(this.initOptions);
this.connection = new JitsiMeetJS.JitsiConnection(null, null, this.connectionOptions);
this.connection.addEventListener(
JitsiMeetJS.events.connection.CONNECTION_ESTABLISHED,
this.onConnectionSuccess
);
this.connection.addEventListener(
JitsiMeetJS.events.connection.CONNECTION_FAILED,
this.onConnectionFailed
);
this.connection.addEventListener(
JitsiMeetJS.events.connection.CONNECTION_DISCONNECTED,
this.disconnect
);
JitsiMeetJS.mediaDevices.addEventListener(
JitsiMeetJS.events.mediaDevices.DEVICE_LIST_CHANGED,
this.onDeviceListChanged
);
this.connection.connect();
JitsiMeetJS.createLocalTracks({ devices: ['audio', 'video'] })
.then(this.onLocalTracks)
.catch((error) => {
throw error;
});
if (JitsiMeetJS.mediaDevices.isDeviceChangeAvailable('output')) {
JitsiMeetJS.mediaDevices.enumerateDevices((devices) => {
const audioOutputDevices = devices.filter((d) => d.kind === 'audiooutput');
if (audioOutputDevices.length > 1) {
const selector = document.querySelector('#audioOutputSelect');
selector.innerHTML = audioOutputDevices
.map((d) => `<option value="${d.deviceId}">${d.label}</option>`)
.join('\n');
selector.style.display = 'block';
}
});
}
}
/**
* Handles remote tracks
* @param track JitsiTrack object
*/
onRemoteTrack(track) {
if (track.isLocal()) {
return;
}
const participant = track.getParticipantId();
if (!this.remoteTracks[participant]) {
this.remoteTracks[participant] = [];
}
const idx = this.remoteTracks[participant].push(track);
track.addEventListener(JitsiMeetJS.events.track.TRACK_AUDIO_LEVEL_CHANGED, (audioLevel) =>
console.log(`Audio Level remote: ${audioLevel}`)
);
track.addEventListener(JitsiMeetJS.events.track.TRACK_MUTE_CHANGED, () =>
console.log('remote track muted')
);
track.addEventListener(JitsiMeetJS.events.track.LOCAL_TRACK_STOPPED, () =>
console.log('remote track stoped')
);
track.addEventListener(JitsiMeetJS.events.track.TRACK_AUDIO_OUTPUT_CHANGED, (deviceId) =>
console.log(`track audio output device was changed to ${deviceId}`)
);
const id = participant + track.getType() + idx;
if (track.getType() === 'video') {
document
.querySelector('.streams')
.insertAdjacentHTML('beforeend', `<video autoplay='1' id='${participant}video${idx}' />`);
} else {
document
.querySelector('.streams')
.insertAdjacentHTML('beforeend', `<audio autoplay='1' id='${participant}audio${idx}' />`);
}
track.attach(document.querySelector(`#${id}`));
}
/**
*
* @param selected
*/
changeAudioOutput(selected) {
// eslint-disable-line no-unused-vars
JitsiMeetJS.mediaDevices.setAudioOutputDevice(selected.value);
}
/**
* That function is executed when the conference is joined
*/
onConferenceJoined() {
console.log('conference joined!');
this.isJoined = true;
for (let i = 0; i < this.localTracks.length; i++) {
this.room.addTrack(this.localTracks[i]);
}
}
/**
*
*/
switchVideo() {
// eslint-disable-line no-unused-vars
this.isVideo = !isVideo;
if (this.localTracks[1]) {
this.localTracks[1].dispose();
this.localTracks.pop();
}
JitsiMeetJS.createLocalTracks({
devices: [this.isVideo ? 'video' : 'desktop']
})
.then((tracks) => {
this.localTracks.push(tracks[0]);
this.localTracks[1].addEventListener(JitsiMeetJS.events.track.TRACK_MUTE_CHANGED, () =>
console.log('local track muted')
);
this.localTracks[1].addEventListener(JitsiMeetJS.events.track.LOCAL_TRACK_STOPPED, () =>
console.log('local track stoped')
);
this.localTracks[1].attach(document.querySelector('#localVideo1'));
this.room.addTrack(this.localTracks[1]);
})
.catch((error) => console.log(error));
}
/**
* Handles local tracks.
* @param tracks Array with JitsiTrack objects
*/
onLocalTracks(tracks) {
this.localTracks = tracks;
for (let i = 0; i < this.localTracks.length; i++) {
this.localTracks[i].addEventListener(
JitsiMeetJS.events.track.TRACK_AUDIO_LEVEL_CHANGED,
(audioLevel) => console.log(`Audio Level local: ${audioLevel}`)
);
this.localTracks[i].addEventListener(JitsiMeetJS.events.track.TRACK_MUTE_CHANGED, () =>
console.log('local track muted')
);
this.localTracks[i].addEventListener(JitsiMeetJS.events.track.LOCAL_TRACK_STOPPED, () =>
console.log('local track stoped')
);
this.localTracks[i].addEventListener(
JitsiMeetJS.events.track.TRACK_AUDIO_OUTPUT_CHANGED,
(deviceId) => console.log(`track audio output device was changed to ${deviceId}`)
);
if (this.localTracks[i].getType() === 'video') {
document
.querySelector('.streams')
.insertAdjacentHTML('beforeend', `<video autoplay='1' id='localVideo${i}' />`);
this.localTracks[i].attach(document.querySelector(`#localVideo${i}`));
} else {
document
.querySelector('.streams')
.insertAdjacentHTML(
'beforeend',
`<audio autoplay='1' muted='true' id='localAudio${i}' />`
);
this.localTracks[i].attach(document.querySelector(`#localAudio${i}`));
}
if (this.isJoined) {
this.room.addTrack(this.localTracks[i]);
}
}
}
/**
*
* @param id
*/
onUserLeft(id) {
console.log('user left');
if (!this.remoteTracks[id]) {
return;
}
const tracks = this.remoteTracks[id];
for (let i = 0; i < tracks.length; i++) {
const participant = tracks[i].getParticipantId();
tracks[i].detach(document.querySelector(`#${id}${tracks[i].getType()}`));
document.querySelector(`.streams #${participant}${tracks[i].getType()}${id}`).remove();
}
}
/**
* That function is called when connection is established successfully
*/
onConnectionSuccess() {
this.room = this.connection.initJitsiConference(this.roomId, this.conferenceOptions);
this.room.on(JitsiMeetJS.events.conference.TRACK_ADDED, this.onRemoteTrack);
this.room.on(JitsiMeetJS.events.conference.TRACK_REMOVED, (track) => {
console.log(`track removed!!!${track}`);
});
this.room.on(JitsiMeetJS.events.conference.CONFERENCE_JOINED, this.onConferenceJoined);
this.room.on(JitsiMeetJS.events.conference.USER_JOINED, (id) => {
console.log('user join');
this.remoteTracks[id] = [];
});
this.room.on(JitsiMeetJS.events.conference.USER_LEFT, this.onUserLeft);
this.room.on(JitsiMeetJS.events.conference.TRACK_MUTE_CHANGED, (track) => {
console.log(`${track.getType()} - ${track.isMuted()}`);
});
this.room.on(JitsiMeetJS.events.conference.DISPLAY_NAME_CHANGED, (userID, displayName) =>
console.log(`${userID} - ${displayName}`)
);
this.room.on(JitsiMeetJS.events.conference.TRACK_AUDIO_LEVEL_CHANGED, (userID, audioLevel) =>
console.log(`${userID} - ${audioLevel}`)
);
this.room.on(JitsiMeetJS.events.conference.PHONE_NUMBER_CHANGED, () =>
console.log(`Phone Number: ${this.room.getPhoneNumber()} - ${this.room.getPhonePin()}`)
);
this.room.join();
}
getPhoneNumber() {
return this.room.getPhoneNumber();
}
/**
*
*/
unload() {
for (let i = 0; i < this.localTracks.length; i++) {
this.localTracks[i].dispose();
}
this.room.leave();
this.connection.disconnect();
}
/**
* This function is called when the connection fail.
*/
onConnectionFailed() {
console.error('Connection Failed!');
}
/**
* This function is called when the connection fail.
*/
onDeviceListChanged(devices) {
console.info('current devices', devices);
}
/**
* This function is called when we disconnect.
*/
disconnect() {
console.log('disconnect!');
this.connection.removeEventListener(
JitsiMeetJS.events.connection.CONNECTION_ESTABLISHED,
this.onConnectionSuccess
);
this.connection.removeEventListener(
JitsiMeetJS.events.connection.CONNECTION_FAILED,
this.onConnectionFailed
);
this.connection.removeEventListener(
JitsiMeetJS.events.connection.CONNECTION_DISCONNECTED,
this.disconnect
);
}
}
I’m trying to make it work with audio only (no video at all). HOw can I do this?