Language Confidence
A JavaScript SDK to simplify connecting with the Language Confidence online service via the REST API.
Project page: https://bitbucket.org/languageconfidence/client-sdk-js
How to start
You have different options to start with the library:
todo
- Download the latest release.
- Clone the repo:
git clone https://bitbucket.org/languageconfidence/client-sdk-js.git
. - Install with npm:
npm install --save todo
. - Install with Bower:
bower install todo
. - Use the CDNjs hosted lib.
Production files are available under the dist/
directory.
Examples
To see a simple example in action, click here
For more examples see:
- todo: whatever other examples could be useful, e.g:
- demonstrate how to capture audio and convert to Base64 encoding for sending to the server.
- show different scoring systems and how to use them
- show a simple React application
- show a simple Angular application
Usage
Getting an API Access Token
In order to access the Language Confidence API you must first register for a Language Confidence account, and then use your client ID and client secret to request an API token.
You should not include your client secret in your client side code as that would allow your account to be used by others. Instead you should set up your own API endpoint (integrated with your service offering) that then requests the API token on your client's behalf. Your client can then request the API token from your service, and then use that key to access to Language Confidence API.
[todo: ideally set up some docco or a sample project on how to do this that we link to from here]
For testing purposes, the easiest way to get an API Token is to use CURL:
curl -X POST "https://api.languageconfidence.ai/oauth/access_token"
-u "<your-client-id>:<your-client-secret>"
-H "Content-Type: application/x-www-form-urlencoded"
-d "grant_type=client_credentials"
The resulting JSON response should look something like:
{
"refresh_token_expires_in" : "0",
"api_product_list" : "[Pronunciation API]",
"api_product_list_json" : [ "Pronunciation API" ],
"organization_name" : "YourCompany",
"developer.email" : "you@yourcompany.com",
"token_type" : "BearerToken",
"issued_at" : "1545022453794",
"client_id" : "<your-client-id>",
"access_token" : "<the-access-token-to-use>",
"application_name" : "5500356a-755c-4797-a44a-7b92024badfc",
"scope" : "",
"expires_in" : "35999",
"refresh_count" : "0",
"status" : "approved"
}
Copy the value for the access_token
from this response and use it in the API calls below.
Initialising the LanguageConfidence SDK
Create a new instance of the LanguageConfidence class, passing in your API key. You can then use this instance to make calls to the server.
let langConf = new LanguageConfidence({
accessToken: '<your-access-token>'
});
You can also set other default values when initialising your LangugaeConfidence object. For a full list see the API documentation.
Gathering your request data
Each request to the server includes a text phrase and the matching audio to be checked for pronunciation quality.
Audio data should be formatted in base64 and included as part of the JSON request to the server. How you capture this audio will depend on your environment. For an example of capturing audio in HTML5 see this example (can we find anything better?)
let request = {
"format": "mp3",
"content": "After the show we went to a restaurant.",
"audioBase64": "<base-64-encoded-audio-data>"
};
At a minimum your request should include the format ('mp3' or 'wav'), the content (i.e. the phrase being read), and the base 64 audio data. You can also include options to change how the audio is processed. For a full list see the API documentation.
Sending data to the server
// send the request data to the server and get back score values
langConf.getPronunciationScore(request)
.then( result => {
// success! you can now use the response
console.log('Response from server', result);
})
.catch( error => {
// something went wrong, handle the error
console.log('Error getting scores from server', error);
});
Getting the score for the whole sentence
Once you have your processed data you can extract scores for different parts of the phrase. The 'sentence score' is the overall score for the whole phrase.
Scores are available as a raw percentage value, or as a 'graded' score, in which case the percent is mapped to a grade of 'poor', 'average' or 'good', based on the difficulty level set when the request was made.
langConf.getPronunciationScore(request)
.then( result => {
let sentenceScore = result.getSentenceScore();
// get the overall score as a raw percent (as a decimal fraction)
console.log('Overall score: ' + sentenceScore.rawScore);
// get the overall score graded ('poor', 'average' or 'good'). This will depend
// on the grading difficulty used.
console.log('Overall score (graded): ' + sentenceScore.gradedScore);
})
Getting the score for specific words
You can also get the score for individual words. As the same word may appear multiple times in a phrase, word scores are returned as an array. Each entry in the array is the score for the word, in order that it occurred in the phrase.
langConf.getPronunciationScore(request)
.then( result => {
// we get the first element as we know the word only occurred once
let wordScore = result.getWordScores('restaurant')[0];
// get the score for that word as a raw percent (as a decimal fraction)
console.log('Score for "restaurant": ' + wordScore.rawScore);
// get the score graded ('poor', 'average' or 'good') for that word
console.log('Score for "restaurant" (graded): ' + wordScore.gradedScore);
})
Getting the score for specific phonemes within a word
You can also extract the scores for specific phonemes within each word.
Phonemes also include extra information in the 'sounds_like'. This is a two dimensional array, where each entry in the array gives details on an alternate phoneme that the audio sounded like. The details is then another array, with just two values, the first value is the phoneme, and the second is a value for how strongly the audio matched it.
langConf.getPronunciationScore(request)
.then( result => {
// we get the first element as we know the word only occurred once
let phonemes = result.getPhonemeScoresList('restaurant')[0];
// the result is a list of phonemes within that word
console.log('Found ' + phonemes.length + ' phonemes in "restaurant"');
phonemes.forEach(score => {
console.log('Score for phoneme "' + score.label + '" is: ');
console.log(' - raw score: ' + score.rawScore);
console.log(' - graded score: ' + score.gradedScore);
score.soundedLike.forEach(soundLike => {
console.log(' - sounded like: ' + soundLike[0]
+ ', (confidence ' + soundLike[1] + ')');
});
});
})
Changing the grading level
The grade ('poor', 'average', 'good') a particular score gets depends on the difficulty
('beginner', 'intermediate', 'advanced') that was set at the time of requesting the score.
You can however regrade a response for a new difficulty by using the adjustPronunciationScoreGrades
method. This creates a new graded score, leaving the original score intact.
langConf.getPronunciationScore(request)
.then( result => {
langConf.adjustPronunciationScoreGrades(result, 'beginner')
.then(beginnerScore => {
console.log('Grade when a beginner: '
+ beginnerScore.getSentenceScore().rawScore);
});
langConf.adjustPronunciationScoreGrades(result, 'advanced')
.then(advancedScore => {
console.log('Grade when advanced: '
+ advancedScore.getSentenceScore().rawScore);
});
})
You can also change the difficulty level used by default by setting the value on the LanguageConfidence instance:
// all requests made will use the advanced grading system unless
// specifically overridden in the request
langConf.setDifficulty('advanced');
Or on a per request level by passing the difficulty in as an extra request option
let request = {
"format": "mp3",
"content": "After the show we went to a restaurant.",
"audioBase64": "<base-64-encoded-audio-data>",
"difficulty": "intermediate"
};
langConf.getPronunciationScore(request).then(...);
Refreshing the Authentication token
todo - example of a auth error and trying to refresh. Could also show checking the timeout and preemptively refreshing.
Maybe could also add a 'autoRefreshToken' and 'storeTokenAsCookie' stuff to the API but maybe v2?
Report a bug / Ask for a feature
todo
Contributing
todo
Available commands
npm test
test code - todo
npm run docs
generate documentation - todo
npm run build
build the source code - todo
npm run watch
build and watch the source code (for local dev) - todo
Versioning
We use SemVer as a guideline for our versioning here.
What does that mean?
Releases will be numbered with the following format:
<major>.<minor>.<patch>
And constructed with the following guidelines:
- Breaking backward compatibility bumps the
<major>
(and resets the<minor>
and<patch>
) - New additions without breaking backward compatibility bump the
<minor>
(and reset the<patch>
) - Bug fixes and misc. changes bump the
<patch>
Authors and contributors
Copyright and License
Copyright (c) 2018 Language Confidence Pty Ltd, Australia MIT license