WebphoneLib
WebphoneLib copied to clipboard
Easier web calling by providing a layer of abstraction around SIP.js
Open VoIP Alliance Webphone Lib
Makes calling easier by providing a layer of abstraction around SIP.js. To figure out why we made this, read our blog post.
Documentation
Check out the documentation here.
Cool stuff
- Allows you to switch audio devices mid-call.
- Automatically recovers calls on connectivity loss.
- Offers an easy-to-use modern javascript api.
Join us!
We would love more input for this project. Create an issue, create a pull request for an issue, or if you're not really sure, ask us. We're often hanging around on discourse. We would also love to hear your thoughts and feedback on our project and answer any questions you might have!
Getting started
$ git clone [email protected]:open-voip-alliance/WebphoneLib.git
$ cd WebphoneLib
$ touch demo/config.mjs
Add the following to demo/config.mjs
export const authorizationUserId = <your-voip-account-id>;
export const password = '<your-voip-password>';
export const realm = '<realm>';
export const websocketUrl = '<websocketUrl>';
Run the demo-server:
$ npm i && npm run demo
And then play around at http://localhost:1235/demo/.
Examples
Connecting and registering
import { Client } from 'webphone-lib';
const account = {
user: 'accountId',
password: 'password',
uri: 'sip:accountId@<realm>',
name: 'test'
};
const transport = {
wsServers: '<websocket-url>', // or replace with your
iceServers: [] // depending on if your provider needs STUN/TURN.
};
const media = {
input: {
id: undefined, // default audio device
audioProcessing: true,
volume: 1.0,
muted: false
},
output: {
id: undefined, // default audio device
volume: 1.0,
muted: false
}
};
const client = new Client({ account, transport, media });
await client.register();
Incoming call
// incoming call below
client.on('invite', (session) => {
try {
ringer();
let { accepted, rejectCause } = await session.accepted(); // wait until the call is picked up
if (!accepted) {
return;
}
showCallScreen();
await session.terminated();
} catch (e) {
showErrorMessage(e)
} finally {
closeCallScreen();
}
});
Outgoing call
const session = client.invite('sip:518@<realm>');
try {
showOutgoingCallInProgress();
let { accepted, rejectCause } = await session.accepted(); // wait until the call is picked up
if (!accepted) {
showRejectedScreen();
return;
}
showCallScreen();
await session.terminated();
} catch (e) {
} finally {
closeCallScreen();
}
Attended transfer of a call
if (await sessionA.accepted()) {
await sessionA.hold();
const sessionB = client.invite('sip:519@<realm>');
if (await sessionB.accepted()) {
// immediately transfer after the other party picked up :p
await client.attendedTransfer(sessionA, sessionB);
await sessionB.terminated();
}
}
Audio device selection
Set a primary input & output device:
const client = new Client({
account,
transport,
media: {
input: {
id: undefined, // default input device
audioProcessing: true,
volume: 1.0,
muted: false
},
output: {
id: undefined, // default output device
volume: 1.0,
muted: false
}
}
});
Change the primary I/O devices:
client.defaultMedia.output.id = '230988012091820398213';
Change the media of a session:
const session = await client.invite('123');
session.media.input.volume = 50;
session.media.input.audioProcessing = false;
session.media.input.muted = true;
session.media.output.muted = false;
session.media.setInput({
id: '120398120398123',
audioProcessing: true,
volume: 0.5,
muted: true
});
Commands
Command | Help |
---|---|
npm run docs | Generate the docs |
npm run test | Run the tests |
npm run test -- --verbose | Show output of console.log during tests |
npm run test-watch | Watch the tests as you make changes |
npm run build | Build the projects |
npm run prepare | Prepare the project for publish, this is automatically run before npm publish |
npm run lint | Run tslint over the source files |
npm run typecheck | Verifies type constraints are met |
Generate documentation
Typedoc is used to generate the
documentation from the jsdoc
comments in the source code. See this
link for more information on which
jsdoc
tags are supported.
Run puppeteer tests
Using docker
Add a .env file with the following:
USER_A = <user-a>
USER_B = <user-b>
PASSWORD_A = <password-user-a>
PASSWORD_B = <password-user-b>
NUMBER_A = <number-user-a>
NUMBER_B = <number-user-b>
WEBSOCKET_URL = <your-websocket-url>
REALM = <realm>
Then call docker-compose up
to run the tests.
Note: Don't forget to call npm ci
in the puppeteer folder. :)
Without docker
If you don't want to use docker, you will need to run the demo with the npm run demo
command (and keep it running) and run the tests with npm run test:e2e
. For this you will need the .env file with your settings.