又快到一年一度的雙十一了。淘寶直播一姐曾在去年雙十一,一我的賣出了3.3億的銷售額,創造了行業的銷售神話。近兩年,不少電商平臺開始關注起直播互動電商,但願在直播中,也能夠增長互動,例如在直播過程當中,拋出限量優惠商品,實時發送搶購的消息給觀衆。因而咱們作了一個簡單的Demo。java
Demo大體的總體想法以下:以視頻直播爲主的互動模型基礎上,結合語音轉寫功能進行設計,爲主播擺脫Windows端繁瑣操做,實現快速發題的功能。主播經過語音輸入題目(問答題,答案只有是和否),確認後將題目文本發送給全部房間內的觀衆,觀衆收到題目後App主動彈框給觀衆選擇結果。git
一個簡單的視頻直播Demo按如下幾個步驟就能夠實現了,能夠找幾個Android設備run一下看看效果,仍是至關easy滴。github
Step1 SDK集成api
SDK還好支持maven依賴,在build.gradle的dependencies模塊中加一行就行:maven
dependencies {
...
implementation 'io.agora.rtc:full-sdk:2.8.1'
}
複製代碼
Step2 直播引擎建立ide
聲網SDK有個重要的類RtcEngine,負責直播功能管理,提供了上/下線、狀態監聽、音/視頻設置等比較豐富的Api,碰到問題時,首先查這個類就對了。建立引擎時APP_ID參數爲聲網開發平臺建立的應用id。工具
private RtcEngine mRtcEngine;
try {
mRtcEngine = RtcEngine.create(context, LiveDefine.APP_ID,
mRtcEventHandler);
mRtcEngine.setChannelProfile(Constants.CHANNEL_PROFILE_COMMUNICATION);
mRtcEngine.enableAudio(); // 開啓音頻功能
mRtcEngine.enableVideo(); // 開啓視頻功能
} catch (Exception e) {
e.printStackTrace();
}
複製代碼
Step3 直播View關聯測試
角色有主播和觀衆區分,關聯View時有些許區別。ANCHOR_UID爲主播用戶id,主播端關聯View時爲本身的用戶id,觀衆端關聯view時爲觀看的主播的用戶id。用戶系統須要應用本身管理,聲網SDK不提供用戶管理。gradle
SurfaceView surface = RtcEngine.CreateRendererView(this);
// 主播端View關聯
mRtcEngine.setClientRole(Constants.CLIENT_ROLE_BROADCASTER);
mRtcEngine.enableLocalAudio(true); // 主播端須要打開本地音頻
mRtcEngine.setupLocalVideo(new VideoCanvas(surface,
VideoCanvas.RENDER_MODE_HIDDEN, ANCHOR_UID)); // 主播端設置的是本地video
mRtcEngine.startPreview(); //主播須要開啓視頻預覽
// 觀衆端View關聯
mRtcEngine.setClientRole(Constants.CLIENT_ROLE_AUDIENCE);
mRtcEngine.enableLocalAudio(false); // 觀衆端不須要打開本地音頻
mRtcEngine.setupRemoteVideo(new VideoCanvas(surface,
VideoCanvas.RENDER_MODE_HIDDEN, ANCHOR_UID)); // 觀衆端設置的是遠端即主播video
複製代碼
Step4 加入房間ui
加入房間時第一個參數token爲當前登陸帳戶對應的token,應用本身管理,測試時可從傳空。第二個參數爲頻道id,也是由應用本身管理的。第三個參數爲頻道名稱。最後一個參數爲當前登陸的帳戶id
mRtcEngine.joinChannel("", CHANNEL_ID, "CHANNEL_NAME", uid);
複製代碼
Step5 離開房間
// 主播端離開
mRtcEngine.setupLocalVideo(null);
mRtcEngine.stopPreview();
mRtcEngine.leaveChannel();
// 觀衆端離開
mRtcEngine.setupRemoteVideo(null);
mRtcEngine.leaveChannel();
複製代碼
直播房間消息功能能夠說是相對基礎而簡單的了,咱們選用的是聲網實時信息SDK,這是一個獨立的工具類SDK,聲網將實時消息功能解耦出來,能夠給各個場景提供消息支持。羣聊實時消息可參考以下步驟:
Step1 依賴配置
dependencies {
...
implementation 'io.agora.rtm:rtm-sdk:1.0.1'
}
複製代碼
Step2 消息引擎建立
// APP_ID同視頻互動SDK保持一致便可
private RtmClient mRtmClient;
mRtmClient = RtmClient.createInstance(context, LiveDefine.APP_ID, listener);
複製代碼
Step3 房間消息初始化
建立一個消息頻道前須要調一次登陸操做,第一個參數爲應用帳戶token,第二個參數爲帳戶標識。
mRtmClient.login("", userId,
new ResultCallback<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "rtmClient login success");
}
@Override
public void onFailure(ErrorInfo errorInfo) {
Log.d(TAG, "rtmClient login fail : " + errorInfo);
}
});
複製代碼
建立消息頻道,CHANNEL_ID是一個標識,能夠和直播頻道不一致,可是建議保持一致:
RtmChannel mRtmChannel;
RtmChannelListener rtmListener = new RtmChannelListener(){
@Override
public void onMessageReceived(RtmMessage var1, RtmChannelMember var2){
// 收到消息,本身發送的消息也會有該方法回調,能夠經過RtmChannelMember判斷髮送消息的人是否是本身,若是是不處理本次消息便可。
}
@Override
public void onMemberJoined(RtmChannelMember var1){
// 有用戶加入,可用來作用戶上線消息處理
}
@Override
public void onMemberLeft(RtmChannelMember var1){
// 有用戶離開,可用來作用戶離線消息處理
}
};
mRtmChannel = mRtmClient.createChannel(CHANNEL_ID,
rtmListener );;
複製代碼
Step4 發送消息
RtmMessage rtmMessage = mRtmClient.createMessage();
rtmMessage.setText(msg);
mRtmChannel.sendMessage(rtmMessage, callback);
複製代碼
Step5 退出消息頻道
可在退出直播房間時,調用該方法。
mRtmChannel.release();
複製代碼
首先也是須要註冊帳戶並建立應用,詳見搜狗知音文檔中心,實現可參考以下步驟:
Step1 初始化
調用init方法初始化
// 如下信息從知音平臺申請得到
private static final String BASE_URL = "api.zhiyin.sogou.com";
private static final String APP_ID = "";
private static final String APP_KEY = "";
private SogoSpeech mSogouSpeech;
private DefaultAudioSource mAudioSource;
private OnSogouAsrListener mListener;
public void init(Context context) {
ZhiyinInitInfo.Builder builder = new ZhiyinInitInfo.Builder();
ZhiyinInitInfo initInfo = builder.setBaseUrl(BASE_URL).setUuid(UUID).setAppid(APP_ID).setAppkey(APP_KEY).create();
SogoSpeech.initZhiyinInfo(context, initInfo);
SogoSpeechSettings settings = SogoSpeechSettings.shareInstance();
settings.setProperty(SpeechConstants.Parameter.ASR_ONLINE_AUDIO_CODING_INT,
1);
settings.setProperty(SpeechConstants.Parameter.ASR_ONLINE_VAD_ENABLE_BOOLEAN,
false);
settings.setProperty(SpeechConstants.Parameter.ASR_ONLINE_VAD_LONGMODE_BOOLEAN,
true); // 長時間ASR
settings.setProperty(Parameter.ASR_ONLINE_LANGUAGE_STRING,
ASRLanguageCode.CHINESE); // 也支持英文ASR ASRLanguageCode.ENGLIS
mSogouSpeech = new SogoSpeech(context);
mSogouSpeech.registerListener(mSpeechEventListener);
mAudioSource = new DefaultAudioSource(new AudioRecordDataProviderFactory(context));
mAudioSource.addAudioSourceListener(mAudioSourceListener);
}
private EventListener mSpeechEventListener = new EventListener() {
@Override
public void onEvent(String eventName, String param, byte[] data, int offset, int length, Object extra) {
if (TextUtils.equals(SpeechConstants.Message.MSG_ASR_ONLINE_LAST_RESULT,
eventName)) {
if (null != mListener) {
mListener.onSogouAsrResult(param);
}
stopTransform();
}
}
@Override
public void onError(String errorDomain, int errorCode, String errorDescription, Object extra) {
// 9002 用戶主動取消
if (9002 != errorCode && null != mListener) {
mListener.onSogouAsrResult("");
}
stopTransform();
}
};
private IAudioSourceListener mAudioSourceListener = new IAudioSourceListener() {
@Override
public void onBegin(IAudioSource iAudioSource) {
Log.d(TAG, "AudioSource onBegin");
mSogouSpeech.send(SpeechConstants.Command.ASR_ONLINE_START, "", null, 0, 0);
}
@Override
public void onNewData(IAudioSource audioSource, Object dataArray, long packIndex, long sampleIndex, int flag) {
final short[] data = (short[]) dataArray;
mSogouSpeech.send(SpeechConstants.Command.ASR_ONLINE_RECOGIZE, "", data, (int) packIndex, 0);
}
@Override
public void onEnd(IAudioSource audioSource, int status, Exception e, long sampleCount) {
Log.d(TAG, "AudioSource onEnd");
mSogouSpeech.send(SpeechConstants.Command.ASR_ONLINE_STOP, "", null, 0, 0);
}
};
public interface OnSogouAsrListener {
void onSogouAsrResult(String result);
}
複製代碼
Step2 開始語音識別
public void startTransform(OnSogouAsrListener listener) {
mListener = listener;
mSogouSpeech.send(SpeechConstants.Command.ASR_ONLINE_CREATE,
null, null, 0, 0);
new Thread(mAudioSource, "audioRecordSource").start();
}
複製代碼
Step3 中止語音識別
正常狀況下不須要調用該方法,在EventListener 回調中已經調用過該方法了,爲了確保狀態正常也能夠在退出房間時手動調用一次。
public void stopTransform() {
mListener
= null;
if (null != mAudioSource) {
mAudioSource.stop();
}
}
複製代碼
咱們已經將這個 Demo上傳至 Github,你們能夠直接下載使用。
Android:github.com/AgoraIO-Com…
iOS:github.com/AgoraIO-Com…
最後秀一下Demo 實現的效果。
(1)主播端直播發題(語音轉文字):
若是你們有疑問,歡迎到 RTC 開發者社區與做者討論。
做者:聲網 Agora 佈道師金葉清