Skip to content

Commit

Permalink
add docs
Browse files Browse the repository at this point in the history
  • Loading branch information
kanat committed Oct 8, 2024
1 parent 8a947bf commit da9433a
Show file tree
Hide file tree
Showing 18 changed files with 244 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ import io.getstream.video.android.compose.ui.components.call.renderer.copy
import io.getstream.video.android.core.Call
import io.getstream.video.android.core.RealtimeConnection
import io.getstream.video.android.core.call.state.ChooseLayout
import io.getstream.video.android.core.utils.isEnabled
import io.getstream.video.android.filters.video.BlurredBackgroundVideoFilter
import io.getstream.video.android.filters.video.VirtualBackgroundVideoFilter
import io.getstream.video.android.mock.StreamPreviewDataUtils
Expand Down Expand Up @@ -461,10 +462,13 @@ fun CallScreen(
var isNoiseCancellationEnabled by remember {
mutableStateOf(call.isAudioProcessingEnabled())
}
val settings by call.state.settings.collectAsStateWithLifecycle()
val noiseCancellationFeatureEnabled = settings?.audio?.noiseCancellation?.isEnabled == true
SettingsMenu(
call = call,
selectedVideoFilter = selectedVideoFilter,
showDebugOptions = showDebugOptions,
noiseCancellationFeatureEnabled = noiseCancellationFeatureEnabled,
noiseCancellationEnabled = isNoiseCancellationEnabled,
onDismissed = { isShowingSettingMenu = false },
onSelectVideoFilter = { filterIndex ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import io.getstream.chat.android.client.ChatClient
import io.getstream.video.android.core.Call
import io.getstream.video.android.core.DeviceStatus
import io.getstream.video.android.core.StreamVideo
import io.getstream.video.android.core.utils.isAutoOn
import io.getstream.video.android.datastore.delegate.StreamUserDataStore
import io.getstream.video.android.model.StreamCallId
import io.getstream.video.android.model.User
Expand Down Expand Up @@ -116,7 +117,7 @@ class CallLobbyViewModel @Inject constructor(
// based on it
val settings = call.state.settings.first { it != null }

val enabled = when (call.camera.status.first()) {
val isCameraEnabled = when (call.camera.status.first()) {
is DeviceStatus.NotSelected -> {
settings?.video?.cameraDefaultOn ?: false
}
Expand All @@ -131,7 +132,10 @@ class CallLobbyViewModel @Inject constructor(
}

// enable/disable camera capture (no preview would be visible otherwise)
call.camera.setEnabled(enabled)
call.camera.setEnabled(isCameraEnabled)

val isNoiseCancellationEnabled = settings?.audio?.noiseCancellation?.isAutoOn ?: false
call.setAudioProcessingEnabled(isNoiseCancellationEnabled)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import io.getstream.video.android.ui.menu.base.SubMenuItem
*/
fun defaultStreamMenu(
showDebugOptions: Boolean = false,
noiseCancellationFeatureEnabled: Boolean = false,
noiseCancellationEnabled: Boolean = false,
codecList: List<MediaCodecInfo>,
onCodecSelected: (MediaCodecInfo) -> Unit,
Expand Down Expand Up @@ -111,14 +112,16 @@ fun defaultStreamMenu(
action = onToggleScreenShare,
),
)
add(
ActionMenuItem(
title = "Noise cancellation",
icon = Icons.Default.SpatialAudioOff,
highlight = noiseCancellationEnabled,
action = onNoiseCancellation,
),
)
if (noiseCancellationFeatureEnabled) {
add(
ActionMenuItem(
title = "Noise cancellation",
icon = Icons.Default.SpatialAudioOff,
highlight = noiseCancellationEnabled,
action = onNoiseCancellation,
),
)
}
if (showDebugOptions) {
add(
SubMenuItem(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ internal fun SettingsMenu(
call: Call,
selectedVideoFilter: Int,
showDebugOptions: Boolean,
noiseCancellationFeatureEnabled: Boolean,
noiseCancellationEnabled: Boolean,
onDismissed: () -> Unit,
onSelectVideoFilter: (Int) -> Unit,
Expand Down Expand Up @@ -208,6 +209,7 @@ internal fun SettingsMenu(
},
items = defaultStreamMenu(
showDebugOptions = showDebugOptions,
noiseCancellationFeatureEnabled = noiseCancellationFeatureEnabled,
noiseCancellationEnabled = noiseCancellationEnabled,
codecList = codecInfos,
availableDevices = availableDevices,
Expand Down
6 changes: 3 additions & 3 deletions docusaurus/docs/Android/02-tutorials/03-livestream.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -363,10 +363,10 @@ It also went into more details about HLS & RTMP-in.
There are several advanced features that can improve the livestreaming experience:

* ** [Co-hosts](../03-guides/02-joining-creating-calls.mdx) ** You can add members to your livestream with elevated permissions. So you can have co-hosts, moderators etc.
* ** [Custom events](../03-guides/09-reactions-and-custom-events.mdx) ** You can use custom events on the call to share any additional data. Think about showing the score for a game, or any other realtime use case.
* ** [Reactions & Chat](../03-guides/09-reactions-and-custom-events.mdx) ** Users can react to the livestream, and you can add chat. This makes for a more engaging experience.
* ** [Custom events](../03-guides/10-reactions-and-custom-events.mdx) ** You can use custom events on the call to share any additional data. Think about showing the score for a game, or any other realtime use case.
* ** [Reactions & Chat](../03-guides/10-reactions-and-custom-events.mdx) ** Users can react to the livestream, and you can add chat. This makes for a more engaging experience.
* ** [Notifications](../06-advanced/01-ringing.mdx) ** You can notify users via push notifications when the livestream starts
* ** [Recording](../06-advanced/06-recording.mdx) ** The call recording functionality allows you to record the call with various options and layouts
* ** [Recording](../06-advanced/09-recording.mdx) ** The call recording functionality allows you to record the call with various options and layouts

### Recap

Expand Down
146 changes: 146 additions & 0 deletions docusaurus/docs/Android/03-guides/05-noise-cancellation.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
---
title: Noise Cancellation
description: How to implement noise cancellation in Stream Video Android SDK
---

Noise Cancellation capabilities of our Android Video SDK can be enabled by installing our NoiseCancellation package. Under the hood, this package uses the technology developed by krisp.ai.

## Installation

### Add the SDK to your project

To add the Stream Video Noise Cancellation SDK, open your app's `build.gradle.kts` file and add the following dependency:
```kotlin
dependencies {
implementation(libs.stream.video.android.noise.cancellation)
}
```

Make sure you have the correct version specified in your `libs.versions.toml` file:

```toml
[versions]
streamNoiseCancellation = "1.0.1"

[libraries]
stream-video-android-noise-cancellation = { module = "io.getstream:stream-video-android-noise-cancellation", version.ref = "streamNoiseCancellation" }
```

## Integration

Our Android SDK provides a utility component that makes the integration smoother. You'll need to create a `NoiseCancellation` instance and pass it to the `StreamVideoBuilder` when initializing the SDK.
```kotlin
import io.getstream.video.android.core.StreamVideoBuilder
import io.getstream.video.android.noise.cancellation.NoiseCancellation

// ...

val noiseCancellation = NoiseCancellation(context)
val streamVideo = StreamVideoBuilder(
context = context,
apiKey = apiKey,
user = user,
token = token,
// ... other configuration options
audioProcessing = noiseCancellation
).build()

// ...
```

## Feature availability

The availability of noise cancellation is controlled by the call settings. You can check the availability and status of noise cancellation through the `Call` object:

```kotlin
val call: Call = // ... obtain your call object
val noiseCancellationMode = call.state.settings.value?.audio?.noiseCancellation?.mode
```

There are three possible modes for noise cancellation:

### Available

```kotlin
if (noiseCancellationMode == NoiseCancellationSettings.Mode.Available) {
// The feature is enabled on the dashboard and available for the call
// You can present noise cancellation toggle UI in your application
}
```

The feature has been enabled on the dashboard and it's available for the call. In this case, you are free to present any noise cancellation toggle UI in your application.

:::info
Even though the feature may be enabled for your call, you should note that NoiseCancellation is a very performance-heavy process. For that reason, it's recommended to only allow the feature on devices with sufficient processing power.

While there isn't a definitive way to determine if a device can handle noise cancellation efficiently, you can use the following method to check for advanced audio processing capabilities:

```kotlin
import android.content.pm.PackageManager

val context: Context = // ... obtain your context
val hasAdvancedAudioProcessing = context.packageManager.hasSystemFeature(PackageManager.FEATURE_AUDIO_PRO)
```

This can serve as an indicator of whether the device might be capable of handling noise cancellation efficiently. Devices with this feature are more likely to have the necessary hardware to support performance-intensive audio processing tasks.

For the most accurate assessment of noise cancellation performance, you may want to consider implementing your own benchmarking or testing mechanism on different device models.
:::

For more info, you can refer to our UI docs about Noise Cancellation.

### Disabled

````kotlin
if (noiseCancellationMode == NoiseCancellationSettings.Mode.Disabled) {
// The feature is not enabled on the dashboard or not available for the call
// You should hide any noise cancellation toggle UI in your application
}
````

The feature hasn't been enabled on the dashboard or the feature isn't available for the call. In this case, you should hide any noise cancellation toggle UI in your application.

### AutoOn

````kotlin
if (noiseCancellationMode == NoiseCancellationSettings.Mode.AutoOn) {
// Noise cancellation is automatically enabled
}
````

Similar to `Available` with the difference that if possible, the StreamVideo SDK will enable the filter automatically, when the user joins the call.

:::note
The requirements for `AutoOn` to work properly are:

1. A `NoiseCancellation` instance provided when you initialize StreamVideo:
```kotlin
val noiseCancellation = NoiseCancellation(context)
val streamVideo = StreamVideoBuilder(
// ... other parameters
audioProcessing = noiseCancellation
).build()
```
2. Device has sufficient processing power (you can use the `FEATURE_AUDIO_PRO` check as an indicator)
:::


## Activate/Deactivate the filter

To toggle noise cancellation during a call, you can use the `toggleAudioProcessing()` method on the `StreamVideo` instance:

```kotlin
val streamVideo: StreamVideo = // ... obtain your StreamVideo instance

// Check if audio processing (noise cancellation) is enabled
val isAudioProcessingEnabled = streamVideo.isAudioProcessingEnabled()

// Toggle noise cancellation
val isEnabled = streamVideo.toggleAudioProcessing()

// Or using the setAudioProcessingEnabled method
streamVideo.setAudioProcessingEnabled(!isAudioProcessingEnabled)
```

Note that toggling noise cancellation affects all ongoing and future calls for the current `StreamVideo` instance.

Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ The permissions are required and any usage of the `Call` object without them may
:::

In order to notify an inconsistency the SDK will log a warning when `Call.join()` is being called without the required permissions.
This is completely ok, if you have a [call type](./05-call-types.mdx) which does not require streaming audio or video from the users device (e.g. `audio_room` or live broadcast where the user is only a guest and listens in to the stream).
This is completely ok, if you have a [call type](./06-call-types.mdx) which does not require streaming audio or video from the users device (e.g. `audio_room` or live broadcast where the user is only a guest and listens in to the stream).

The SDK by default will check for runtime permissions based on call capabilities, so if your call requires audio to be sent, the SDK will expect that the `android.Manifest.permission.RECORD_AUDIO` is granted.

:::warning
If you are not overriding the `runForegroundServiceForCalls` flag to `false` in the `StreamVideoBuilder` the resulting foreground service that starts for [keeping the call alive](./06-keeping-the-call-alive.mdx) can not run without the permissions and will crash with a detailed message.
If you are not overriding the `runForegroundServiceForCalls` flag to `false` in the `StreamVideoBuilder` the resulting foreground service that starts for [keeping the call alive](./07-keeping-the-call-alive.mdx) can not run without the permissions and will crash with a detailed message.
:::

If you wish to override the behavior on which permissions are required for your calls you can provide a new implementation of `StreamPermissionCheck` to the `StreamVideoBuilder`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ The `AudioCallContent` component is an alternative to the [`CallContent`](./1-ca
:::note
The `AudioCallContent` by itself does not make the call audio only.
In order to have true audio only call you must update the capabilities of the call type and disable video via the Stream dashboard.
The call can still stream video if this is allowed by the call configuration. See [call types](../.././03-guides/05-call-types.mdx) for more details.
The call can still stream video if this is allowed by the call configuration. See [call types](../.././03-guides/06-call-types.mdx) for more details.
:::

This component renders a call UI similar to the [ringing calls](./05-ringing-call.mdx) UI and has parameters (without the `videoRenderer` etc..) similar to [`CallContent`](./01-call-content.mdx) component.
Expand Down
1 change: 1 addition & 0 deletions docusaurus/shared
9 changes: 9 additions & 0 deletions stream-video-android-core/api/stream-video-android-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public final class io/getstream/video/android/core/Call {
public final fun sendReaction (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun sendReaction$default (Lio/getstream/video/android/core/Call;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public final fun setAudioFilter (Lio/getstream/video/android/core/call/audio/InputAudioFilter;)V
public final fun setAudioProcessingEnabled (Z)V
public final fun setVideoFilter (Lio/getstream/video/android/core/call/video/VideoFilter;)V
public final fun setVisibility (Ljava/lang/String;Lstream/video/sfu/models/TrackType;Z)V
public final fun startHLS (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
Expand Down Expand Up @@ -1042,6 +1043,7 @@ public final class io/getstream/video/android/core/call/connection/StreamPeerCon
public final fun makePeerConnection (Lkotlinx/coroutines/CoroutineScope;Lorg/webrtc/PeerConnection$RTCConfiguration;Lio/getstream/video/android/core/model/StreamPeerType;Lorg/webrtc/MediaConstraints;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;I)Lio/getstream/video/android/core/call/connection/StreamPeerConnection;
public static synthetic fun makePeerConnection$default (Lio/getstream/video/android/core/call/connection/StreamPeerConnectionFactory;Lkotlinx/coroutines/CoroutineScope;Lorg/webrtc/PeerConnection$RTCConfiguration;Lio/getstream/video/android/core/model/StreamPeerType;Lorg/webrtc/MediaConstraints;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;IILjava/lang/Object;)Lio/getstream/video/android/core/call/connection/StreamPeerConnection;
public final fun makeVideoTrack (Lorg/webrtc/VideoSource;Ljava/lang/String;)Lorg/webrtc/VideoTrack;
public final fun setAudioProcessingEnabled (Z)V
public final fun setAudioRecordDataCallback (Lkotlin/jvm/functions/Function4;)V
public final fun setAudioSampleCallback (Lkotlin/jvm/functions/Function1;)V
public final fun toggleAudioProcessing ()Z
Expand Down Expand Up @@ -4574,6 +4576,13 @@ public final class io/getstream/video/android/core/utils/MinimalSdpParser {
public final fun setSdp (Ljava/lang/String;)V
}

public final class io/getstream/video/android/core/utils/NoiseCancellationUtilsKt {
public static final fun isAutoOn (Lorg/openapitools/client/models/NoiseCancellationSettings;)Z
public static final fun isAvailable (Lorg/openapitools/client/models/NoiseCancellationSettings;)Z
public static final fun isDisabled (Lorg/openapitools/client/models/NoiseCancellationSettings;)Z
public static final fun isEnabled (Lorg/openapitools/client/models/NoiseCancellationSettings;)Z
}

public final class io/getstream/video/android/core/utils/RtpMapAttribute {
public fun <init> (ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
public final fun component1 ()I
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,10 @@ public class Call(
return clientImpl.isAudioProcessingEnabled()
}

fun setAudioProcessingEnabled(enabled: Boolean) {
return clientImpl.setAudioProcessingEnabled(enabled)
}

fun toggleAudioProcessing(): Boolean {
return clientImpl.toggleAudioProcessing()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1115,6 +1115,10 @@ internal class StreamVideoImpl internal constructor(
return peerConnectionFactory.isAudioProcessingEnabled()
}

internal fun setAudioProcessingEnabled(enabled: Boolean) {
return peerConnectionFactory.setAudioProcessingEnabled(enabled)
}

internal fun toggleAudioProcessing(): Boolean {
return peerConnectionFactory.toggleAudioProcessing()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,13 @@ public class StreamPeerConnectionFactory(
return audioProcessing?.isEnabled ?: false
}

/**
* Sets the audio processing on or off.
*/
public fun setAudioProcessingEnabled(enabled: Boolean) {
audioProcessing?.isEnabled = enabled
}

/**
* Toggles the audio processing on and off.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2014-2024 Stream.io Inc. All rights reserved.
*
* Licensed under the Stream License;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://github.com/GetStream/stream-video-android/blob/main/LICENSE
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.getstream.video.android.core.utils

import org.openapitools.client.models.NoiseCancellationSettings

/**
* Returns true if the noise cancellation mode is "auto-on".
*/
val NoiseCancellationSettings.isAutoOn get() = mode == NoiseCancellationSettings.Mode.AutoOn

/**
* Returns true if the noise cancellation mode is "available".
*/
val NoiseCancellationSettings.isAvailable get() = mode == NoiseCancellationSettings.Mode.Available

/**
* Returns true if the noise cancellation mode is "disabled".
*/
val NoiseCancellationSettings.isDisabled get() = mode == NoiseCancellationSettings.Mode.Disabled

/**
* Returns true if the noise cancellation mode is "auto-on" or "available".
*/
val NoiseCancellationSettings.isEnabled get() = when (mode) {
NoiseCancellationSettings.Mode.Available,
NoiseCancellationSettings.Mode.AutoOn,
-> true
else -> false
}

0 comments on commit da9433a

Please sign in to comment.