实现字节火山美颜
本文介绍如何通过声网美颜场景化 API (Beauty API) 集成字节火山美颜功能到实时音视频互动中。
示例项目
声网在 GitHub 上提供开源 BeautyAPI
示例项目供你参考。
准备开发环境
前提条件
开始前,请确保满足以下前提条件:
创建项目并集成 SDK
在 Xcode 中进行以下操作,在你的 App 中实现场景化美颜功能:
-
创建一个新的项目,Application 选择 App,Interface 选择 Storyboard,Language 选择 Swift。
注意如果你没有添加过开发团队信息,会看到 Add account… 按钮。点击该按钮并按照屏幕提示登入 Apple ID,点击 Next,完成后即可选择你的 Apple 账户作为开发团队。
-
为你的项目设置自动签名。
-
设置部署你的 App 的目标设备。
-
添加项目的设备权限。在项目导航栏中打开
info.plist
文件,编辑属性列表,添加以下属性:key type value Privacy - Microphone Usage Description String 使用麦克风的目的,例如 for a live interactive streaming Privacy - Camera Usage Description String 使用摄像头的目的,例如 for a live interactive streaming 注意如果你的项目中需要添加第三方插件或库(例如第三方摄像头),且该插件或库的签名与项目的签名不一致,你还需勾选 Hardened Runtime > Runtime Exceptions 中的 Disable Library Validation。
更多注意事项,可以参考 Preparing Your App for Distribution。
-
将字节火山美颜 SDK 复制到你的项目中:请联系字节火山技术支持获取美颜 SDK、美颜资源、证书等文件。下载并解压文件,然后添加到美颜项目对应的文件路径下:
文件 项目路径 byted_effect_ios_static/iossample_static/app/Resource/*.bundle
iOS/ByteEffectLib/Resource/*.bundle
byted_effect_ios_static/iossample_static/effect-sdk.framework
iOS/ByteEffectLib/effect-sdk.framework
byted_effect_ios_static/libeffect-sdk.a
iOS/ByteEffectLib/ibeffect-sdk.a
证书: LicenseBag.bundle/<prefix>_<your_bundle_id>_<version_id>.licbag
iOS/ByteEffectLib/Resource/LicenseBag.bundle/<prefix>_<your_bundle_id>_<version_id>.licbag
-
将声网美颜场景化 API 集成到你的项目中。添加 iOS/BeautyAPI/BeautyAPI 目录下的文件到项目中,具体文件如下:
Render/BytesRender
文件夹BeautyAPI.h
文件BeautyAPI.m
文件
注意为方便后续代码升级,请不要修改你添加的这些文件的名称和路径。
-
将声网 RTC SDK 和字节火山美颜依赖库集成到你的项目。
- 在终端里进入项目根目录,并运行
pod init
命令。项目文件夹下会生成一个Podfile
文本文件。 - 打开
Podfile
文件,修改文件为如下内容。注意将Your App
替换为你的 Target 名称。
Rubyplatform :ios, '9.0'
# 替换成你的 target 名称
target 'Your App' do
# x.y.z 请填写具体的 RTC SDK 版本号,如 4.0.1 或 4.0.0.4
# 可通过实时互动发版说明获取最新版本号
pod 'AgoraRtcEngine_iOS', 'x.y.z'
# 配置字节火山美颜的依赖库
pod 'bytedEffect', :path => 'bytedEffect.podspec'
end - 在终端里进入项目根目录,并运行
-
在终端内运行
pod install
命令安装声网 RTC SDK 和字节火山美颜依赖。 -
成功安装后,Terminal 中会显示
Pod installation complete!
。项目文件夹下会生成一个后缀为.xcworkspace
的文件,通过 Xcode 打开该文件进行后续操作。
实现美颜
本节展示如何在直播间内实现美颜功能,参考 API 时序图可查看总览。声网 RTC SDK 承担实时音视频的业务,字节火山美颜 SDK 提供美颜功能,声网 Beauty API 封装了两个 SDK 中的 API 调用逻辑以简化你需要实现的代码逻辑。通过 Beauty API,你可以实现基础美颜功能,但是如果你还需要更丰富的美颜效果,例如贴纸、美妆风格,请直接调用美颜 SDK 中的 API。
1. 初始化 AgoraRtcEngineKit
调用声网 RTC SDK 中的 sharedEngineWithConfig
创建并初始化 AgoraRtcEngineKit
对象。调用 enableVideo
开启声网 RTC SDK 的视频模块。
// 初始化 AgoraRtcEngineKit
private lazy var rtcEngine: AgoraRtcEngineKit = {
let config = AgoraRtcEngineConfig()
// 传入你从控制台获取的声网项目的 APP ID
config.appId = KeyCenter.AppId
config.channelProfile = .liveBroadcasting
let rtc = AgoraRtcEngineKit.sharedEngine(with: config, delegate: self)
// 设置用户角色为主播,主播可以发送音视频流也可以接收音视频流
rtc.setClientRole(.broadcaster)
// 开启 SDK 音频模块
rtc.enableAudio()
// 开启 SDK 视频模块
rtc.enableVideo()
// 设置默认音频路由为扬声器
rtc.setDefaultAudioRouteToSpeakerphone(true)
return rtc
}()
2. 初始化美颜和 Beauty API
创建 BytesBeautyRender
和 Beauty API 对象。Beauty API 对象基于 BytesBeautyRender
对象封装。
private lazy var bytesRender = BytesBeautyRender()
private lazy var beautyAPI = BeautyAPI()
调用 initialize
初始化 Beauty API 对象。你需要在 config
参数中传入如下字段:
AgoraRtcEngineKit
:传入之前初始化的AgoraRtcEngineKit
对象。beautyRender
:传入之前初始化的BytesBeautyRender
对象。captureMode
:视频的采集模式:- 如果你使用声网模块采集视频,请传入
CaptureMode.Agora
。 - 如果自定义采集视频,请传入
CaptureMode.Custom
。
- 如果你使用声网模块采集视频,请传入
cameraConfig
:设置视频镜像模式。如果在初始化 Beauty API 后你想修改镜像模式,可以调用 Beauty API 的updateCameraConfig
。statsEnable
:是否开启美颜统计数据回调。true
代表开启,false
代表不开启。开启后,会有周期性回调事件。statsDuration
:美颜统计数据回调的周期。单位为秒。eventCallback
:监听的美颜统计数据回调事件。
let config = BeautyConfig()
// AgoraRtcEngineKit
config.rtcEngine = rtcEngine
// 设置视频采集模式
// .agora 意味着使用声网模块采集视频
// .custom 意味着使用开发者自定义采集视频
config.captureMode = capture == "Custom" ? .custom : .agora
// 配置视频镜像模式
config.cameraConfig = cameraConfig
// BytesBeautyRender
config.beautyRender = bytesRender
// 是否开启美颜统计数据
// 开启后,会有周期性回调事件
config.statsEnable = false
// 设置美颜统计数据的统计区间为 1 秒(默认)
config.statsDuration = 1
// Beauty API 的回调事件
config.eventCallback = { stats in
print("min == \(stats.minCostMs)")
print("max == \(stats.maxCostMs)")
print("averageCostMs == \(stats.averageCostMs)")
}
// 初始化 Beauty API 对象
let result = beautyAPI.initialize(config)
if result != 0 {
print("initialize error == \(result)")
}
3. 开启美颜
调用 Beauty API 的 enable
方法并将参数设为 true
开启美颜。
beautyAPI.enable(true)
4. 开启视频采集
开发者可以使用声网模块采集视频,也可以自定义采集视频。本节介绍在这两种场景下如何开启视频采集。
使用声网模块采集视频
使用声网模块采集视频视频时,调用 Beauty API 的 setupLocalVideo
开启本地视图。
beautyAPI.setupLocalVideo(localView, renderMode: .hidden)
自定义视频采集
使用自定义视频采集时,你需要在完成视频自采集后,通过 Beauty API 的 onFrame
函数将外部自采集的视频数据传入并进行处理。
如下示例代码展示通过声网 RTC SDK 的 API 进行的自定义视频采集,具体逻辑为通过 AgoraRtcEngineKit
类的 setVideoFrameDelegate
注册原始视频数据观测器并在其中实现 onCaptureVideoFrame
函数。你可以根据实际情况参考这种自采集方式,或使用第三方视频自采集。
if capture == "Custom" {
// 注册原始视频数据观测器
// 自定义视频采集时,即 CaptureMode 为 Custom 时,你需要注册原始视频观测器
rtcEngine.setVideoFrameDelegate(self)
}
extension BeautyViewController: AgoraVideoFrameDelegate {
func onCapture(_ videoFrame: AgoraOutputVideoFrame, sourceType: AgoraVideoSourceType) -> Bool {
// 将外部自采集的视频数据传入声网 RTC SDK
guard let pixelBuffer = videoFrame.pixelBuffer else { return true }
beautyAPI.onFrame(pixelBuffer) { pixelBuffer in
videoFrame.pixelBuffer = pixelBuffer
}
return true
}
// 设置是否对原始视频数据作镜像处理
func getMirrorApplied() -> Bool {
beautyAPI.getMirrorApplied()
}
// 设置观测点为本地采集时的视频数据
func getObservedFramePosition() -> AgoraVideoFramePosition {
.postCapture
}
// 实现视频观测器中的其他回调函数
...
}
5. 加入频道
调用 AgoraRtcEngineKit
类的 joinChannelByToken
加入频道,同时传入如下参数:
token
:用于鉴权的动态密钥。如果在创建声网项目时启用调试模式,那么将token
参数传空。如果启用安全模式,那么你先参考使用 Token 鉴权在你的业务服务端生成 Token,然后将生成的 Token 传入该参数。channelId
:频道名。mediaOptions
:频道媒体设置选项。
let mediaOption = AgoraRtcChannelMediaOptions()
mediaOption.clientRoleType = isBroadcast ? .broadcaster : .audience
// 设置进入频道时是否自动订阅频道内其他用户的音频流
mediaOption.autoSubscribeAudio = true
// 设置进入频道时是否自动订阅频道内其他用户的视频流
mediaOption.autoSubscribeVideo = true
// 设置是否发布摄像头采集的视频流(适用于使用声网模块采集视频的情况)
// 用户角色为主播时,设置发布
// 用户角色为观众时,设置不发布
mediaOption.publishCameraTrack = mediaOption.clientRoleType == .broadcaster
// 设置是否发布自定义采集的视频流(适用于自定义采集视频的情况)
mediaOption.publishCustomVideoTrack = false
// 设置是否发布麦克风采集的音频流
// 用户角色为主播时,设置发布
// 用户角色为观众时,设置不发布
mediaOption.publishMicrophoneTrack = mediaOption.clientRoleType == .broadcaster
// 加入频道
let result = rtcEngine.joinChannel(byToken: nil, channelId: channelName ?? "", uid: 0, mediaOptions: mediaOption)
if result != 0 {
print("join failed")
}
6.(可选)更新摄像头配置
Beauty API 默认用户使用设备前置摄像头参与直播。默认的镜像行为如下:
- 使用设备前置摄像头时,本地和远端视图都使用镜像。
- 使用设别后置摄像头时,本地和远端视图都不使用镜像。
如果默认的摄像头配置不满足你的业务需求,你可以参考本节更新摄像头配置。具体步骤如下:
-
如果当前使用的摄像头不是前置,那么调用 Beauty API 的
switchCamera
切换摄像头。调用后,Beauty API 内部会通过isFrontCamera
知晓当前使用的是前置还是后置摄像头,从而在后续步骤中让你能针对前后置摄像头设置正确的镜像效果。SwiftbeautyAPI.switchCamera()
多次调用该方法可以多次切换前后置摄像头。
-
如果默认的镜像行为不满足你的业务需求,那么调用 Beauty API 的
updateCameraConfig
并通过cameraConfig
配置前置和后置摄像头的镜像效果。所有镜像类型包含如下:LOCAL_REMOTE
:本地和远端视图都使用镜像。前置摄像头默认使用该配置。LOCAL_ONLY
:本地视图使用镜像,远端视图不使用镜像。建议在直播画面中会出现告示牌或者文字的情况下使用该配置。REMOTE_ONLY
:本地视图不使用镜像,远端视图使用镜像。NONE
:本地和远端视图都不使用镜像。后置摄像头默认使用该配置。
Swiftlet cameraConfig = BeautyManager.shareManager.cameraConfig
// 判断 isFrontCamera
if self.beautyAPI?.isFrontCamera ?? false {
// 通过 frontMirror 配置前置摄像头
cameraConfig.frontMirror = Configs.mirrorTypes[value] ?? .LOCAL_REMOTE
} else {
// 通过 backMirror 配置后置摄像头
cameraConfig.backMirror = Configs.mirrorTypes[value] ?? .NONE
}
// 更新摄像头配置
self.beautyAPI?.update(cameraConfig)
7. 离开频道
调用 AgoraRtcEngineKit
类的 leaveChannel
离开频道。
rtcEngine.leaveChannel()
8. 销毁资源
调用 Beauty API 的 destroy
销毁 Beauty API。
beautyAPI.destroy()
Beauty API 自 1.0.2 版起,已将存在笔误的 destory
方法名修正为 destroy
。
调用 AgoraRtcEngineKit
的 destroy
销毁 AgoraRtcEngineKit
。
AgoraRtcEngineKit.destroy()