Skip to content

Commit

Permalink
Update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
compulim committed Dec 5, 2018
1 parent f687032 commit 8ed6862
Showing 1 changed file with 112 additions and 122 deletions.
234 changes: 112 additions & 122 deletions samples/6.a.cognitive-services-bing-speech-js/README.md
Original file line number Diff line number Diff line change
@@ -1,166 +1,156 @@
# Sample - Adding Speech Cognitive Services Bing Speech
# Sample - Adding Speech Cognitive Services Bing Speech

## Description
A simple web page with a maximized and full-featured Web Chat embed from a CDN, with cognitive services added for text-to-speech ability. This sample makes changes that are based off of the [full-bundle CDN sample](./../full-bundle/README.md).

A simple web page with a maximized and full-featured Web Chat embed from a CDN, with cognitive services added for text-to-speech ability. This sample makes changes that are based off of the [full-bundle CDN sample](../1.a.getting-started-full-bundle/README.md).

# Test out the hosted sample
- [Try out MockBot](https://microsoft.github.io/BotFramework-WebChat/speech-cognitive-services-bing-speech)

# How to run locally
- Fork this repository
- Navigate to `/Your-Local-WebChat/samples/speech-cognitive-services-bing-speech` in command line
- Run `npx serve`
- Browse to [http://localhost:5000/](http://localhost:5000/)
- Append your own Speech Subscription key to the url (in the address bar) using URL Search Params: `http://localhost:5000/?s=pasteKeyHere`
- [Try out MockBot](https://microsoft.github.io/BotFramework-WebChat/speech-cognitive-services-bing-speech)

# Things to try out

- Use the microphone button: you should be able to provide commands to the bot via speech
- Speak `help`: you should see a full list of MockBot features
- Speak `card weather`: you should see a weather card built using Adaptive Cards
- Speak `carousel`: you should see a carousel of cards

# Code

> Jump to [completed code](#completed-code) to see the end-result `index.html`.
### Goals of this bot

The `index.html` page has one main goal:
- To enable cognitive services to provide speech-to-text ability

We'll start by using the [full-bundle CDN sample](../full-bundle/README.md) as our Web Chat template.
- To enable Cognitive Services Bing Speech to provide speech-to-text ability

We'll start by using the [full-bundle CDN sample](../1.a.getting-started-full-bundle/README.md) as our Web Chat template.

> Cognitive Services Bing Speech package is only available in the Web Chat full bundle
> **Retrieving the subscription key in the URL and fetching a token is for demonstration purposes only.** In a published bot, the secret should be stored on the server and generate a token to avoid exposing the secret. For more information, visit the [websocket protocol documenation](https://docs.microsoft.com/en-us/azure/cognitive-services/speech/api-reference-rest/websocketprotocol#authorization) for Cognitive Services.
There are two ways to authenticate with Cognitive Services Speech Services, either using subscription key, or time-limited authorization token.

#### Using subscription key

> This approach is for demonstration purpose only. In production code, you should always store the subscription key on a secured token server. The token server should only send out limited authorization code. This [article](https://docs.microsoft.com/en-us/azure/cognitive-services/speech/api-reference-rest/websocketprotocol#authorization) outlines the authorization process.
First, the app must retrieve the __speech cognitive services subscription key__ when running this bot. Add the `URLSearchParams` method to retrieve the key from the URL.
In this sample, we are hardcoding the subscription key in the client code.

```diff
const { token } = await res.json();
+ const SUBSCRIPTION_KEY = new URLSearchParams(window.location.search).get('s');
window.WebChat.renderWebChat({
const { token } = await res.json();

window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
+ webSpeechPonyfillFactory: await window.WebChat.createCognitiveServicesBingSpeechPonyfillFactory({ subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' })
}, document.getElementById('webchat'));
```

#### Using authorization token

Next, the bot needs to fetch a **token** using the subscription key when the previous token expires.
In this sample, we are retrieving the authorization token from a token server.

```diff
const SUBSCRIPTION_KEY = new URLSearchParams(window.location.search).get('s');
+ const TOKEN_RENEWAL_INTERVAL = 300000;
+ let accessTokenPromise;
+ let lastFetch = 0;
+
+ const fetchToken = () => {
+ const now = Date.now();
+
+ if (!accessTokenPromise || now - lastFetch > TOKEN_RENEWAL_INTERVAL) {
+ console.log(`Cognitive Services: Issuing new token using subscription key`);
+
+ lastFetch = now;
+
+ accessTokenPromise = fetch(
+ 'https://api.cognitive.microsoft.com/sts/v1.0/issueToken',
+ {
+ headers: { 'Ocp-Apim-Subscription-Key': SUBSCRIPTION_KEY },
+ }
+ )
+ .then(res => res.ok ? res.text() : Promise.reject(new Error(`Failed to issue token`)))
+ .catch(err => {
+ lastFetch = 0;
+ return Promise.reject(err);
+ });
+ }
+
+ return accessTokenPromise;
};

window.WebChat.renderWebChat({
const { token } = await res.json();
+ const res = await fetch('https://YOUR_TOKEN_SERVER/', { method: 'POST' });
+ const { token: authorizationToken } = await res.json();

window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
+ webSpeechPonyfillFactory: await window.WebChat.createCognitiveServicesBingSpeechPonyfillFactory({ authorizationToken })
}, document.getElementById('webchat'));
```

## Completed code

Finally, pass a Web Speech ponyfill factory to renderWebChat.
```diff
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
+ webSpeechPonyfillFactory: window.WebChat.createCognitiveServicesWebSpeechPonyfillFactory({ fetchToken })
}, document.getElementById('webchat'));
```
### Using subscription key

> If you prefer, you can use your own W3C Web Speech API compliant speech engine. Visit the [w3c Speech API](https://w3c.github.io/speech-api/) documentation for more information, and check out the file [createCognitiveServicesWebSpeechPonyfillFactory.js](./../packages\bundle\src\createCognitiveServicesWebSpeechPonyfillFactory.js) to reference implementation.
Here is the finished `index.html` for subscription key flow:

```diff
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Web Chat: Cognitive Services Bing Speech using JavaScript</title>
<script src="https://cdn.botframework.com/botframework-webchat/master/webchat.js"></script>
<style>
html, body { height: 100% }
body { margin: 0 }

#webchat,
#webchat > * {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="webchat"></div>
<script>
(async function () {
const res = await fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' });
const { token } = await res.json();

window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
+ webSpeechPonyfillFactory: await window.WebChat.createCognitiveServicesBingSpeechPonyfillFactory({ subscriptionKey: 'YOUR_SUBSCRIPTION_KEY' })
}, document.getElementById('webchat'));

document.querySelector('#webchat > *').focus();
})().catch(err => console.error(err));
</script>
</body>
</html>
```

### Using authorization token

## Completed code
Here is the finished `index.html`:
Here is the finished `index.html` for authorization token flow:

```diff
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Web Chat: Cognitive Services Bing Speech using JavaScript</title>
<script src="https://cdn.botframework.com/botframework-webchat/master/webchat.js"></script>
<style>
html, body { height: 100% }
body { margin: 0 }

#webchat,
#webchat > * {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="webchat"></div>
<script>
(async function () {
const res = await fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' });
const { token } = await res.json();
+ const SUBSCRIPTION_KEY = new URLSearchParams(window.location.search).get('s');
+ const TOKEN_RENEWAL_INTERVAL = 300000;
+ let accessTokenPromise;
+ let lastFetch = 0;

+ const fetchToken = () => {
+ const now = Date.now();

+ if (!accessTokenPromise || now - lastFetch > TOKEN_RENEWAL_INTERVAL) {
+ console.log(`Cognitive Services: Issuing new token using subscription key`);

+ lastFetch = now;
+ accessTokenPromise = fetch(
+ 'https://api.cognitive.microsoft.com/sts/v1.0/issueToken',
+ {
+ headers: { 'Ocp-Apim-Subscription-Key': SUBSCRIPTION_KEY },
+ method: 'POST'
+ }
+ )
+ .then(res => res.ok ? res.text() : Promise.reject(new Error(`Failed to issue token`)))
+ .catch(err => {
+ lastFetch = 0;

+ return Promise.reject(err);
+ });
+ }

+ return accessTokenPromise;
+ };

window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
+ webSpeechPonyfillFactory: window.WebChat.createCognitiveServicesWebSpeechPonyfillFactory({ fetchToken })
}, document.getElementById('webchat'));

document.querySelector('#webchat > *').focus();
})().catch(err => console.error(err));
</script>
</body>
</html>


# Further Reading
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Web Chat: Cognitive Services Bing Speech using JavaScript</title>
<script src="https://cdn.botframework.com/botframework-webchat/master/webchat.js"></script>
<style>
html, body { height: 100% }
body { margin: 0 }

#webchat,
#webchat > * {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="webchat"></div>
<script>
(async function () {
const res = await fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' });
const { token } = await res.json();
+ const res = await fetch('https://YOUR_TOKEN_SERVER/', { method: 'POST' });
+ const { token: authorizationToken } = await res.json();

window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
+ webSpeechPonyfillFactory: await window.WebChat.createCognitiveServicesBingSpeechPonyfillFactory({ authorizationToken })
}, document.getElementById('webchat'));

document.querySelector('#webchat > *').focus();
})().catch(err => console.error(err));
</script>
</body>
</html>
```

# Further reading

## Full list of Web Chat Hosted Samples

View the list of available samples by clicking [here](https://github.com/Microsoft/BotFramework-WebChat/tree/master/samples)

0 comments on commit 8ed6862

Please sign in to comment.