Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update sample document. #465

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ public AuthenticationProvider(string appName, string appId, string appSecret, IG
/// In this case we are using the Microsoft.IdentityModel.Clients.ActiveDirectory library
/// to stamp the outbound http request with the OAuth 2.0 token using an AAD application id
/// and application secret. Alternatively, this method can support certificate validation.
/// Note that this is only for demonstration purpose. Since acquiring token can be a costly operation,
/// it is recomended to acquire token before hand and cache the token, instead of acquiring it for every incoming request.
/// </summary>
/// <param name="request">The request.</param>
/// <param name="tenant">The tenant.</param>
Expand All @@ -105,6 +107,7 @@ public async Task AuthenticateOutboundRequestAsync(HttpRequestMessage request, s
AuthenticationResult result;
try
{
// This request can take some time to complete. It's recommended to acquire it beforehand and use the cached version.
result = await this.AcquireTokenWithRetryAsync(context, resource, creds, attempts: 3).ConfigureAwait(false);
}
catch (Exception ex)
Expand Down
28 changes: 0 additions & 28 deletions Samples/PublicSamples/Sample_README_Template.md

This file was deleted.

39 changes: 25 additions & 14 deletions Samples/V1.0Samples/AksSamples/teams-recording-bot/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
# Introduction
---
page_type: sample
languages:
- csharp
products:
- dotnet
description: "Add 150 character max description"
urlFragment: "update-this-to-unique-url-stub"
---

The teams-recording-bot sample guides you through building, deploying and testing a Teams recording bot running within a container, deployed into Azure Kubernetes Services.
# Official Microsoft Sample

<!--
Guidelines on README format: https://review.docs.microsoft.com/help/onboard/admin/samples/concepts/readme-template?branch=master

Guidance on onboarding samples to docs.microsoft.com/samples: https://review.docs.microsoft.com/help/onboard/admin/samples/process/onboarding?branch=master

Taxonomies for products and languages: https://review.docs.microsoft.com/new-hope/information-architecture/metadata/taxonomies?branch=master
-->

Give a short description for your sample here. What does it do and why is it important?

## Contents

Expand Down Expand Up @@ -94,18 +112,11 @@ If you are running the project locally, you will need Ngrok running to forward t
1. Create a new file called `ngrok.yaml` in the [scripts](scripts) folder.
2. Copy the contents of [ngrok.yaml-template](scripts/ngrok.yaml-template) over to `ngrok.yaml`.
3. Update `ngrok.yaml` with
```
<AUTH_TOKEN>: Your Ngrok authentication token.

<YOUR_SUBDOMAIN>: The subdomain portion of your Ngrok reserved domain.
For example: if your reserved domain is `bot.ngrok.io`, then this value would be `bot`.

<CALL_SIGNALING_PORT>: LOCALHOST_HTTP_PORT
For example: 9441

<INSTANT_INTERNAL_PORT>: LOCALHOST_TCP_PORT
For example 8445
```
* Your Ngrok authentication token.
* The subdomain portion of your Ngrok reserved domain.
* For example: if your reserved domain is `bot.ngrok.io`, then this value would be `bot`.
* Your full TCP reserved Ngrok address.
* For example: `1.tcp.ngrok.io:000000`

Once you've done that, run [runngrok.bat](scripts/runngrok.bat) in command prompt and leave it running.

Expand Down
22 changes: 0 additions & 22 deletions Samples/V1.0Samples/AksSamples/teams-recording-bot/build/certs.bat

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,3 @@
{{- printf "%d" (int .Values.scale.maxReplicaCount) -}}
{{- end -}}
{{- end -}}

{{/* Check if host is set */}}
{{- define "hostName" -}}
{{- if .Values.host -}}
{{- printf "%s" .Values.host -}}
{{- else -}}
{{- fail "You need to specify a host" -}}
{{- end -}}
{{- end -}}

{{/* Check if image.domain is set */}}
{{- define "imageDomain" -}}
{{- if .Values.image.domain -}}
{{- printf "%s" .Values.image.domain -}}
{{- else -}}
{{- fail "You need to specify image.domain" -}}
{{- end -}}
{{- end -}}

{{/* Check if public.ip is set */}}
{{- define "publicIP" -}}
{{- if .Values.public.ip -}}
{{- printf "%s" .Values.public.ip -}}
{{- else -}}
{{- fail "You need to specify public.ip" -}}
{{- end -}}
{{- end -}}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
{{- $fullName := include "fullName" . -}}
{{- $namespace := include "namespace" . -}}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ $fullName }}
namespace: {{ include "namespace" . }}
namespace: {{ $namespace }}
labels:
app: {{ $fullName }}
helmVersion: {{ .Chart.Version }}
Expand Down Expand Up @@ -46,7 +47,7 @@ spec:
terminationGracePeriodSeconds: {{ .Values.terminationGracePeriod }}
containers:
- name: recording-bot
image: "{{ include "imageDomain" . }}/teams-recording-bot:{{ .Values.image.tag | default .Chart.AppVersion }}"
image: "{{ .Values.image.domain }}/teams-recording-bot:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
lifecycle:
preStop:
Expand Down Expand Up @@ -79,7 +80,7 @@ spec:
name: bot-application-secrets
key: applicationSecret
- name: AzureSettings__ServiceDnsName
value: {{ include "hostName" . }}
value: {{ .Values.host }}
- name: AzureSettings__InstancePublicPort
value: "{{ .Values.public.media }}"
- name: AzureSettings__InstanceInternalPort
Expand All @@ -88,6 +89,10 @@ spec:
value: "{{ .Values.internal.port }}"
- name: AzureSettings__PlaceCallEndpointUrl
value: https://graph.microsoft.com/v1.0
- name: AzureSettings__ArchiveDuration
value: "{{ .Values.container.env.azureSetting.archiveDuration }}"
- name: AzureSettings__AudioFrameDuration
value: "{{ .Values.container.env.azureSetting.audioFrameDuration }}"
- name: AzureSettings__CaptureEvents
value: "{{ .Values.container.env.azureSetting.captureEvents }}"
- name: AzureSettings__EventsFolder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ metadata:
spec:
type: LoadBalancer
externalTrafficPolicy: Cluster
loadBalancerIP: {{ include "publicIP" . }}
loadBalancerIP: {{ .Values.public.ip }}
ports:
- name: http
port: 80
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ metadata:
spec:
tls:
- hosts:
- {{ include "hostName" . }}
- {{ .Values.host }}
secretName: {{ .Values.ingress.tls.secretName }}
rules:
- host: {{ include "hostName" . }}
- host: {{ .Values.host }}
http:
paths:
- backend:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ scale:
maxReplicaCount: 3
replicaCount: 3

host: null
host: ms.com

image:
domain: null
domain: acr.azurecr.io
pullPolicy: IfNotPresent
tag: ""

Expand All @@ -26,7 +26,7 @@ internal:

public:
media: 28550
ip: null
ip:

node:
target: scale
Expand All @@ -36,6 +36,8 @@ terminationGracePeriod: 54000
container:
env:
azureSetting:
archiveDuration: 300 # 5 minutes
audioFrameDuration: 640 # Default PCM frame size in bytes on a teams call
captureEvents: false
eventsFolder: events
mediaFolder: archive
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
- Policies can only be applied to members of your AAD subscription. Guests cannot have a recording policy, it has to be applied in their home Active Directory.
- If you need the capability to have a user sometimes recorded and sometimes not, that user either needs two identities or a capability to instruct the bot not to record. This is possible but adds complexity to the overall architecture of a solution and requires a centralised mechanism to query the status and request status changes in the bot.
- Scaling of the recording bot is non-trivial
- Due to the bot being stateful and potentially participating in long running transactions (calls can be up to 24 Hours in duration), it is non-trivial to upgrade or scale down the number of bots deployed. A bot has to wait until all calls it is interacting with are complete. There are samples of configuration for Kubernetes in this repository that demonstrate how to do this.
- Due to the bot being stateful and potentially participating in long running transactions (calls can be up to 24 Hours in duration), it is non-trivial to upgrade or scale down the number of bots deployed. A bot has to wait until all calls it is interacting with are complete. There are samples of configuration for Kubernetes in this repo that demonstrate how to do this.
- Dependencies on Media Libraries that are Windows only
- A full installation of Windows is required for the bot to work. This creates large containers on build (includes the full Windows installation). It also requires consideration and management of the node types in Kubernetes as there will be at least one Windows pod instance in the cluster and therefore Windows nodes. There is nothing difficult about it, it just requires thinking about.
- Development is done with the .NET Framework (it cannot be done using .NET Core).
- Micro-services architectures that depend on the bot require careful planning
- Handing off processing to other services in latency critical applications, while in a call is not simple. This is not specific to the bot or its deployment environment but a consequence of working with audio or any near real-time source and expected output. When working with speech it does not make sense to break segments at arbitrary points. This will significantly impact the accuracy of things like speech recognition. The implications are you either have to re-assemble coherent segments of speech in a downstream service (and then determining what is a coherent segment becomes challenging and dealing with latency) or manage the service from the bot itself. This is easier to develop but results in the bot becoming monolithic. Services that are not latency dependent (e.g. speech recognition after the event) would not be impacted by this.
-
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,21 @@ The bot itself is developed in C# and has to run on a full Windows machine. This

The bot will most likely be deployed to a cloud based server, likely in a container. This however makes development and debugging cumbersome.

For local development purposes it is possible to use Ngrok to act as the signalling and TCP media traffic endpoitn and have it redirected to your local machine. There are notes about how to setup this development environment in the repository.
For local development purposes it is possible to use ngrok to act as the signalling and TCP media traffic endpoitn and have it redirected to your local machine. There are notes about how to setup this development environment in the repository.

## Delivered assets

The main asset delivered in this repository is a media receiving bot and associated documentation. The bot is joined into meetings via a Compliance Policy attached to a user. Once connected to a meeting/call a media stream is delivered to the bot and the bot can then do various things with that stream for example:
The main asset delivered in this repo is a media receiving bot and associated documentation. The bot is joined into meetings via a Compliance Policy attached to a user. Once connected to a meeting/call a media stream is delivered to the bot and the bot can then do various things with that stream for example:

- Persisting the stream and associated metadata to act as a meeting recorded

- Use the content of the stream to connect to other services (like speech to text for near real-time transcription)

The bot as delivered here is intended to be a sample that can be a starting point for further development. To this end it is intended to be a base starting point and a 'skeleton' that can be built out on. It is also intended to be as flexible as possible so that it can be deployed in different ways.

The repository includes instructions on how to deploy the bot into Kubernetes. This is to support scaling requirements for when a lot of calls are being connected to. The deployment documentation also deals with how to scale the bot. It is a stateful application with potentially long running processes (meetings and calls can be up to 24 hours in duration) therefore scaling the number of bots down must consider ongoing calls and letting them complete.
The repo includes instructions on how to deploy the bot into Kubernetes. This is to support scaling requirements for when a lot of calls are being connected to. The deployment documentation also deals with how to scale the bot. It is a stateful application with potenitally long running processes (meetings and calls can be up to 24 hours in duration) therefore scaling the number of bots down must consider ongoing calls and letting them complete.

## What is in the repository?
## What is in the repo?

The repository contains the following items/code/information

Expand Down
Loading