本文介绍如何实现实时传译的功能,包括与 Express 的接口对接,主播与观众之间的通信方式。
在实现实时传译功能之前,请确保:
已在 ZEGO 控制台 创建项目,并申请有效的 AppID 和 AppSign,详情请参考 控制台 - 项目管理 - 项目信息。
已在项目中集成 ZEGO Express SDK,实现基本的实时音视频功能,详情请参考 实时音视频 - 快速开始 - 集成 SDK。
已在项目中集成 ZegoRealtimeTranslation SDK,详情请参考 集成 SDK 文档。
已开通相关权限,并获取到实时传译的 License。
ZEGO 提供了 示例源码,以供开发者进一步了解 ZEGO 实时传译功能。
请您根据自己的业务需要,选择实现相关的内容识别传译功能。
创建界面。根据场景需要,为您的项目展示实时传译的用户界面,推荐您在项目中添加如下元素:
创建引擎。调用 ZEGO Express SDK 的 createEngine 接口,将申请到的 AppID 和 AppSign 分别传入参数“appID”和“appSign”,创建引擎单例对象。
注册回调,可将实现了 IZegoEventHandler 的对象传入参数 “eventHandler”。
ZegoEngineProfile zegoEngineProfile = new ZegoEngineProfile();
// 请通过 ZEGO 控制台获取,格式为:1234567890
zegoEngineProfile.appID = Config.appID;
// 请通过 ZEGO 控制台获取,格式为:"0123456789012345678901234567890123456789012345678901234567890123"(共64个字符)
zegoEngineProfile.appSign = Config.appSign;
zegoEngineProfile.application = application;
// 实时通讯场景接入
zegoEngineProfile.scenario = ZegoScenario.COMMUNICATION;
// 创建引擎
ZegoExpressEngine.createEngine(zegoEngineProfile, zegoEventHandler);
...
private IZegoEventHandler zegoEventHandler = new IZegoEventHandler() {
// 重载的方法见后面的步骤需要,在后面步骤有详细实现
...
};
调用 ZEGO Express SDK 的 loginRoom 接口登录房间。roomID 和 user 的参数由开发者的本地业务生成,但是需要满足以下条件:同一个 AppID 内,需保证 “roomID” 全局唯一。
// 创建用户对象,ZegoUser 的构造方法 userWithUserID 会将 “userName” 设为与传的参数 “userID” 一样。“userID” 与 “userName” 不能为 “null”,否则会导致登录房间失败。
String roomID = "your_room_id";
ZegoUser user = new ZegoUser("your_user_id");
// 登录房间
ZegoExpressEngine.getEngine().loginRoom(roomID, user);
在使用 ZegoRealtimeTranslation SDK 功能前,必须先进行初始化。
ZegoRealtimeTranslation zegoRealtimeTranslation = ZegoRealtimeTranslation.getInstance();
zegoRealtimeTranslation.init(license); // 传入申请到的license
登录房间后如果是主播需要开始推流,设置声音采集的参数。同时设置声音采集的回调接口,把声音数据传给 ZegoRealtimeTranslation SDK。
engine.startPublishingStream(streamID); // streamID是流ID
// 设置采集声音的参数,必须sampleRate是16k,单声道格式。
ZegoAudioFrameParam audioFrameParam = new ZegoAudioFrameParam();
audioFrameParam.sampleRate = ZegoAudioSampleRate.ZEGO_AUDIO_SAMPLE_RATE_16K;
audioFrameParam.channel = ZegoAudioChannel.MONO;
engine.startAudioDataObserver(ZegoAudioDataCallbackBitMask.CAPTURED.value(), audioFrameParam);
// 设置接收麦克风收集到的声音数据回调,并传给ZegoRealtimeTranslation SDK.
engine.setAudioDataHandler(new IZegoAudioDataHandler() {
@Override
public void onCapturedAudioData(ByteBuffer byteBuffer, int dataLength, ZegoAudioFrameParam zegoAudioFrameParam) {
zegoRealtimeTranslation.sendSpeechPCM(byteBufferToByteArray(byteBuffer), dataLength);
}
};
// ByteBuffer转Byte数组的方法
public static byte[] byteBufferToByteArray(ByteBuffer bytes) {
int len = bytes.limit() - bytes.position();
byte[] bytes1 = new byte[len];
bytes.get(bytes1);
return bytes1;
}
主播和观众都需要拉流,当有流新增时,进行拉流操作。
// zegoEventHandler对应创建引擎时传的参数
private IZegoEventHandler zegoEventHandler = new IZegoEventHandler() {
...
@Override
public void onRoomStreamUpdate(String roomID, ZegoUpdateType zegoUpdateType, ArrayList<ZegoStream> arrayList, JSONObject jsonObject) {
ZegoCanvas zegoCanvas = new ZegoCanvas(textureView); // textureView是TextureView
zegoCanvas.viewMode = ZegoViewMode.ASPECT_FILL;
engine.startPlayingStream(streamID, zegoCanvas);
}
}
SEI 通道用来传识别和翻译后的文本,这里可以自己定义规则,
Demo使用的规制是:
"zegoa2ti:{"username":"小明", "text":"今天天气不错", "trans":"It's a nice day today"}"
// zegoEventHandler对应创建引擎时传的参数
private IZegoEventHandler zegoEventHandler = new IZegoEventHandler() {
...
@Override
public void onPlayerRecvSEI(String streamID, byte[] bytes) {
String str = new String(data, StandardCharsets.UTF_8);
// 根据自定义规则处理文本
if (str.startWith("zegoa2ti") {
...
} else if (str.startWith("zegoa2td") {
...
} else {
// 其他用途的SEI
}
}
}
...
// json定义的数据类
public static class RecognizeModel{
@SerializedName("username")
public String userName;
@SerializedName("text")
public String text;
@SerializedName("trans")
public String translateText;
}
开启实时传译前需要设置参数,包括服务提供商,源语言和目标语言。
zegoRealtimeTranslation.enableTranslate(true); // 如果不需要翻译可以设置为false
zegoRealtimeTranslation.enableInterimTranslation(true);// 如果不需要中间结果翻译可以设置为false,开启会增加很多翻译请求量
zegoRealtimeTranslation.setSpeechToTextService(ZegoRTServiceProvider.Iflytek); // 设置语音识别使用的服务提供商
zegoRealtimeTranslation.setTextTranslationService(ZegoRTServiceProvider.Iflytek); // 设置翻译使用的服务提供商
zegoRealtimeTranslation.setSourceSpeechLanguage(ZegoSpeechLanguage.zh_CN); // 设置语音识别的语言
zegoRealtimeTranslation.setTargetTranslationLanguage(ZegoTranslationLanguage.en); // 设置翻译的目标语言
zegoRealtimeTranslation.setRealtimeTranslationHandler(new IZegoRealtimeTranslationHandler() {
@Override
public void onRecognizingText(String sttText) {
RecognizeModel recognizeModel = new RecognizeModel();
recognizeModel.userName = viewModel.userName; // 自己的用户名
recognizeModel.text = sttText;
if (!TextUtils.isEmpty(sttText)) {
// 把识别的文本显示出来
}
// 把识别结果通过SEI通道发送出去
engine.sendSEI(("zegoa2ti:" + gson.toJson(recognizeModel)).getBytes(StandardCharsets.UTF_8));
}
@Override
public void onRecognizingTranslatedText(String translateText) {
RecognizeModel recognizeModel = new RecognizeModel();
recognizeModel.userName = viewModel.userName; // 自己的用户名
recognizeModel.translateText = translateText;
if (!TextUtils.isEmpty(translateText)) {
// 把翻译的文本显示出来
}
// 把识别结果通过SEI通道发送出去
engine.sendSEI(("zegoa2ti:" + gson.toJson(recognizeModel)).getBytes(StandardCharsets.UTF_8));
}
@Override
public void onRecognizedText(String sttText) {
RecognizeModel recognizeModel = new RecognizeModel();
recognizeModel.userName = viewModel.userName; // 自己的用户名
recognizeModel.text = sttText;
if (!TextUtils.isEmpty(sttText)) {
// 把识别的文本显示出来
}
// 把识别结果通过SEI通道发送出去
engine.sendSEI(("zegoa2td:" + gson.toJson(recognizeModel)).getBytes(StandardCharsets.UTF_8));
}
@Override
public void onRecognizedTranslatedText(String translateText) {
RecognizeModel recognizeModel = new RecognizeModel();
recognizeModel.userName = viewModel.userName; // 自己的用户名
recognizeModel.translateText = translateText;
if (!TextUtils.isEmpty(translateText)) {
// 把翻译的文本显示出来
}
// 把识别结果通过SEI通道发送出去
engine.sendSEI(("zegoa2td:" + gson.toJson(recognizeModel)).getBytes(StandardCharsets.UTF_8));
}
@Override
public void onError(int error) {
// 处理出错情况
}
});
// 开始识别
int ret = zegoRealtimeTranslation.startRealtimeTranslation();
// 在适当的时机,停止实时传译
zegoRealtimeTranslation.stopRealtimeTranslation();
// 退出房间
ZegoExpressEngine.getEngine().logoutRoom();
主持人退出房间后,如果没有暂停或停止视频播放,房间内的观众可以继续观看当前视频。
zegoRealtimeTranslation.unInit();
ZegoExpressEngine.destroyEngine{ };
在使用 ZegoRealtimeTranslation SDK 功能前,必须先进行初始化。
ZegoRealtimeTranslation zegoRealtimeTranslation = ZegoRealtimeTranslation.getInstance();
zegoRealtimeTranslation.init(license); // 传入申请到的license
主持人登录房间、并且播放器设置完成后,可以调用 ZegoRealtimeTranslation SDK 的 translate。
zegoRealtimeTranslation.translate(text, ZegoRTServiceProvider.Google, ZegoTranslationLanguage.zh_Hans, ZegoTranslationLanguage.en,
(errorCode, resultText) -> {
if (errorCode == ZegoRealtimeTranslationError.SUCCESS) {
// 翻译成功,显示resultText
}
});
// 退出房间
ZegoExpressEngine.getEngine().logoutRoom();
主持人退出房间后,如果没有暂停或停止视频播放,房间内的观众可以继续观看当前视频。
zegoRealtimeTranslation.unInit();
ZegoExpressEngine.destroyEngine{ };
联系我们
文档反馈