用声网 React Native UIKit 给视频通话添加 AI 降噪功能

用 React Native UIKit 可以在几分钟内搭建一个视频通话应用。本文教给大家的是如何扩展 UIKit 以及如何为视频通话应用添加自定义功能(以 AI 降噪为例)。


前期准备


设置

大家可以在 GitHub 上获得本示例的代码,或自行创建 React Native 项目。打开一个终端并执行:

npx react-native init demo --template react-native-template-typescript
cd demo

安装声网 React Native SDK 和 UIKit:

npm i react-native-agora agora-rn-uikit

注意:截止 2022 年 3 月 15 日, agora-rn-uikit 的最新版本是 v3.3.0, react-native-agora 的最新版本是 v3.5.1。

如果使用 iOS 设备,要运行 cd ios && pod install 来安装 CocoaPods,还需要配置应用签名和权限。大家可以打开 Xcode 里的 /ios/<projectname>.xcworkspace 文件进行配置。

设置完成后,执行 npm run androidnpm run ios ,开启服务器,会得到一个基础的 React Native 应用。


搭建视频通话

我们可以通过 UIKit 访问高级组件 <AgoraUIKit> ,用 <AgoraUIKit> 渲染一个完整的视频通话。UIKit blog 对如何使用少量代码定制 UI 和功能进行了深度讲解。<AgoraUIKit> 组件是用更小的组件搭建而成的,我们可以不考虑视频通话逻辑,用这些小组件搭建一个完全自定义的组件。

首先,清除 App.tsx 文件,重新开始:

import React, {useState} from 'react';
import {View} from 'react-native';

const App = () => {
  const [inCall, setCall] = useState(true);
  return inCall ? (
    /* Render Video Call here */
  ) : (
    <View />
  );
};

export default App;

创建状态变量 inCall 。当状态变量为 true 时,渲染视频通话,当状态变量为 false 时,暂时渲染空的 <View>

import React, {useState} from 'react';
import {View} from 'react-native';
import {RtcConfigure, GridVideo} from 'agora-rn-uikit/Components';
import {PropsContext} from 'agora-rn-uikit/Contexts';
import Controls from './src/Controls';

const App = () => {
  const [inCall, setCall] = useState(true);
  return inCall ? (
    <PropsContext.Provider
      value={{
        rtcProps: {appId: '<Agora App ID>', channel: 'test'},
        callbacks: {EndCall: () => setCall(false)},
      }}>
      <RtcConfigure>
        <GridVideo />
        <Controls />
      </RtcConfigure>
    </PropsContext.Provider>
  ) : (
    <View />
  );
};

export default App;

要搭建视频通话,需要从 UIKit 中输入 PropsContextRtcConfigure、和 GridVideo 组件。RtcConfigure 组件处理视频通话逻辑。我们用 PropsContext 封装 RtcConfigure 组件,把用户道具传递到 UIKit 中。

然后,渲染 <GridVideo> 组件,该组件会把所有用户的视频呈网格状排列,大家也可以用 <PinnedVideo> 组件。因为我们想创建一个开启/关闭 AI 降噪的按钮,所以我们创建一个自定义组件 <Controls>,在网格下方渲染。

import React from 'react';
import {StyleProp, View, ViewStyle} from 'react-native';
import {LocalAudioMute, LocalVideoMute, SwitchCamera, Endcall} from 'agora-rn-uikit/Components';
import {LocalUserContext} from 'agora-rn-uikit/Contexts';
import CustomButton from './CustomButton';

function Controls() {
  return (
    <LocalUserContext>
      <View style={styles.Controls as StyleProp<ViewStyle>}>
        <LocalAudioMute />
        <LocalVideoMute />
        <SwitchCamera />
        <CustomButton />
        <Endcall />
      </View>
    </LocalUserContext>
  );
}

const styles = {
  Controls: {
    position: 'absolute',
    bottom: 25,
    left: 0,
    width: '100%',
    height: 70,
    zIndex: 10,
    display: 'flex',
    flexDirection: 'row',
    justifyContent: 'space-evenly',
    alignItems: 'center',
  },
};

export default Controls;

我们可以从 UIKit 中输入 LocalAudioMuteLocalVideoMuteSwitchCameraEndcall 按钮,在 <View> 中渲染。

另外,我们会创建一个新组件 CustomButton,该组件包含开启/关闭降噪功能的代码。

import React, {useContext, useState} from 'react';
import {Image, StyleSheet, TouchableOpacity} from 'react-native';
import {RtcContext} from 'agora-rn-uikit/Contexts';

function Button() {
  const {RtcEngine} = useContext(RtcContext);
  const [enabled, setEnabled] = useState(false);
  
  return (
    <TouchableOpacity
      style={styles.localButton}
      onPress={async () => {
        if (!enabled) {
          await RtcEngine.enableDeepLearningDenoise(true);
          setEnabled(true);
        } else {
          await RtcEngine.enableDeepLearningDenoise(false);
          setEnabled(false);
        }
      }}>
      <Image
        style={[styles.icon, {tintColor: enabled ? '#00ff00' : '#fff'}]}
        source={{
          uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAABRklEQVRIieXUyy4EQRTG8R/WTNyaldiR8B6CJ2FPxiU8iHgMl40NNsSKBWHDziURT2As6ky0TmZ0m5FInKRSVadO/U/116eKP2hjqOMCr9FOsYH+TuELeEajRVvqFP4eoD3MYQq34bvCyE/h43gJ0BZ6kAW0Cc8idhjLKspVD9B+wGst4PmkG1USXMSmuZivfwNv4AR6SyaYiP4s+kZhPcMRZnEXvpnSx8dbQAdiXpQoP56O8WOVBKexab5w6rwkTbkWYn5eFp7hJjbVC2s1rIW/JhXAYcSuloXnP79dnfdgO2KfpBtfCd6sllFsSnKNYEiS5SBi332VshK8qHuxPXULfoNj6aF7kcp3JRfb0kZxGZBr6Ylo569kgyVOnvdXtt3fhPP5Wk7+BhweArYYSboKJ93IYtl1DQ59keRekmtH+vH/3D4A73qGGEQiRsYAAAAASUVORK5CYII=',
        }}
      />
    </TouchableOpacity>
  );
}

const styles = StyleSheet.create({
  icon: {
    width: 24,
    height: 24,
    tintColor: '#fff',
  },
  localButton: {
    width: 46,
    height: 46,
    backgroundColor: '#007bff',
    alignItems: 'center',
    justifyContent: 'center',
    borderRadius: 23,
  },
});

export default Button;

可以用 RtcContext 访问 RtcEngine 示例,访问声网Agora SDK 里的供 UIKit 使用的引擎示例。我们会定义一个变量,开启该变量时,可以触发降噪效果。

另外,用<TouchableOpacity> 创建一个按钮,该按钮会根据状态在引擎示例上调用 enableDeepLearningDenoise 方法。记得要添加一个图形图标来显示状态。

以上是所有添加自定义功能所需的设置,大家也可以用同样的方式添加事件监听器,用来访问引擎事件,执行自定义操作。


总结

如果大家发现了可以添加在声网 UIKit 上的好用的 React Native 功能,欢迎随时复刻资源库并添加拉取请求。

也欢迎大家在资源库里开启功能请求哦,谢谢大家~


原文作者:Ekaansh Arora
原文链接:Add AI Denoising to your Video Calls using the Agora React Native UIKit
推荐阅读
相关专栏
SDK 教程
164 文章
本专栏仅用于分享音视频相关的技术文章,与其他开发者和声网 研发团队交流、分享行业前沿技术、资讯。发帖前,请参考「社区发帖指南」,方便您更好的展示所发表的文章和内容。