当你使用 RTC 实现实时音视频通信时,采集、编解码、前后处理、渲染等通信链路各环节中的音视频数据默认使用 RTC SDK 内部的对应模块进行处理。若你在应用中已自行实现了部分音视频处理逻辑,也可以对数据进行自定义处理,并交由 RTC 进行传输。
在使用 Flutter 跨平台框架进行应用开发时,受平台性能限制,自定义音视频处理相关功能未在 Flutter 层提供接口。但 RTC Flutter SDK 提供从 Native 层获取原生 RTC 引擎实例的能力,你可以将相关功能放在 Native 层实现,再通过自定义 MethodChannel
进行调用。
详情参看撰写双端平台代码(插件编写实现),了解 Flutter 应用如何借助原生平台能力实现所需功能。
本文以自定义音频处理功能为例,详细介绍原生平台接口的调用方法。
注意:
调用 Native 端相关接口前,请先从 Flutter 端创建好
RTCVideo
实例。请勿在 Native 端调用
destroy
接口,否则会引起功能异常。
自定义 MethodChannel
,并调用需要使用的 Native 接口
#import <Flutter/FlutterPlugin.h> #import <volc_engine_rtc/ByteRTCVideoManager.h> #import <VolcEngineRTC/VolcEngineRTC.h> @interface RTCEngineFlutterPlugin : NSObject <FlutterPlugin> @end @implementation RTCEngineFlutterPlugin // FlutterPlugin + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar { RTCEngineFlutterPlugin *instance = [[RTCEngineFlutterPlugin alloc] init]; // “MethodChannelName” 字段可自行定义,但注意需与 Flutter 侧保持一致 FlutterMethodChannel *methodChannel = [FlutterMethodChannel methodChannelWithName:@"MethodChannelName" binaryMessenger:registrar.messenger]; [registrar addMethodCallDelegate:instance channel:methodChannel]; } - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { // 转发消息 // method 字段可自行定义,但注意需与 Flutter 侧保持一致。建议直接使用 Native 接口名,此处以 registerAudioProcessor 为例 if ([call.method isEqualToString:@"registerAudioProcessor"]) { [self registerAudioProcessor:call.arguments result:result]; return; } result(FlutterMethodNotImplemented); } // custom method - (void)registerAudioProcessor:(NSDictionary *)arguments result:(FlutterResult)result { // 获取 ByteRTCVideo 实例 ByteRTCVideo *rtcVideo = [ByteRTCVideoManager getVideo]; if (rtcVideo == nil) { result(@(-1)); return; } // 注册自定义音频处理器 int res = [rtcVideo registerAudioProcessor:processor]; result(@(res)); } @end
将自定义 MethodChannel
注册进 Flutter 引擎
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [GeneratedPluginRegistrant registerWithRegistry:self]; // Override point for customization after application launch. [RTCEngineFlutterPlugin registerWithRegistrar:[self registrarForPlugin:@"RTCEngineFlutterPlugin"]]; return [super application:application didFinishLaunchingWithOptions:launchOptions]; }
在 Android 项目工程中的 build.gradle
文件中添加依赖
dependencies { // 版本号请与 Flutter SDK 中依赖的 Android SDK 版本号保持一致 // 从 SDK 根目录/android/build.gradle 文件中查看 implementation 'com.volcengine:VolcEngineRTC:X.X.X' }
自定义MethodChannel
,并调用需要使用的 Native 接口
import androidx.annotation.NonNull; import com.ss.bytertc.engine.RTCVideo; import com.ss.bytertc.engine.flutter.base.RTCVideoManager; import java.util.Objects; import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.StandardMethodCodec; public class RTCEngineFlutterPlugin implements FlutterPlugin, MethodChannel.MethodCallHandler { private MethodChannel channel; @Override public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { BinaryMessenger binaryMessenger = binding.getBinaryMessenger(); // “MethodChannelName” 字段可自行定义,但注意需与 Flutter 侧保持一致 channel = new MethodChannel(binaryMessenger, "MethodChannelName", StandardMethodCodec.INSTANCE); channel.setMethodCallHandler(this); } @Override public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { channel.setMethodCallHandler(null); } @Override public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { // 转发消息 // method 字段可自行定义,但注意需与 Flutter 侧保持一致。建议直接使用 Native 接口名,此处以 registerAudioProcessor 为例 if (Objects.equals(call.method, "registerAudioProcessor")) { registerAudioProcessor(call, result); return; } result.notImplemented(); } void registerAudioProcessor(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { RTCVideo rtcVideo = null; try { // 获取 RTCVideo 实例 rtcVideo = RTCVideoManager.getRTCVideo(); } catch (Exception e) { result.success(-1); return; } // 注册自定义音频处理器 int res = rtcVideo.registerAudioProcessor(processor); result.success(res); } }
将自定义 MethodChannel
注册进 Flutter 引擎
public class MainActivity extends FlutterActivity { @Override public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { super.configureFlutterEngine(flutterEngine); flutterEngine.getPlugins().add(new RTCEngineFlutterPlugin()); } }
实现自定义 MethodChannel
class RTCEngineExtension { // “MethodChannelName” 字段可自行定义,但注意需与 Native 侧保持一致 static const MethodChannel _staticChannel = MethodChannel('MethodChannelName'); static Future<int?> registerAudioProcessor() { // method 字段可自行定义,但注意需与 Native 侧保持一致。建议直接使用 Native 接口名,此处以 registerAudioProcessor 为例 return _staticChannel.invokeMethod<int>("registerAudioProcessor"); } }