開源:用這套代碼快速實現3 種在線課堂場景

儘管疫情還未結束,但不少學生已經在線開啓了新的一學期。不少教育巨頭爲老師與學生搭建的在線教學場景,都是經過聲網 Agora SDK 實現的。爲了方便更多用戶能夠基於 Agora SDK 快速實現多種在線教學場景,咱們現已開源聲網雲課堂 Demo,你們可在文末獲取源碼。html

image.png

除了 demo 開源,咱們也提供了Web、Android、iOS 應用供你們體驗。推薦老師使用 Web 端應用,學生可以使用以上任一版本。前端

  • Web(推薦用Chrome訪問):https://solutions.agora.io/ed...
  • iOS:App Store 搜索「聲網雲課堂」
  • Android:華爲應用市場搜索「聲網雲課堂」,或掃碼下載(密碼:123)

image.png

場景與功能

聲網雲課堂 Demo 實現的教學場景包括:web

  • 1 對 1 互動教學:1 位老師對 1 名學生進行專屬線上輔導教學,老師和學生能實時音視頻互動。
  • 1 對 N 在線小班課:1 位教師對多名學生進行在線輔導教學,最多支持 16 名學生。
  • 低延遲大班課:1 位老師進行教學,多名學生實時觀看和收聽,學生人數無上限。與此同時,學生能夠「舉手」發言,與老師進行實時音視頻互動。

除了支持實時音視頻的互動,本示例項目還支持在線課堂中許多必不可少的功能。咱們僅以 Web 端來介紹一下。json

教學白板:在以上三個場景中,都支持白板功能。1 對 1 互動教學中,老師和學生均可以操做白板;1 對 1 在線小班課、低延遲大班課中,能夠受權學生操做白板。後端

image.png
image.png

共享PPT等文件:老師能夠在授課的同時,共享 PPT、PDF、word、圖片、mp四、mp3 等多媒體文件。學生端只能觀看,不能上傳。安全

image.png

屏幕共享:老師能夠發起屏幕共享,展現桌面、網頁或其餘應用窗口。app

image.png

文字消息:除了連麥之外,學生還能夠經過文字消息在課堂中提問交流。less

image.png

錄製回放:老師登陸 Web端,能夠進行課程錄製。在白板的下方,有錄製按鈕,制完成後,在右側的消息窗口中會自動彈出回放地址。async

image.png

另外,老師端還支持一些控制學生端音視頻流的權限,好比在 1 對 N 在線小班課中,老師還能夠訪問學生列表,開啓或關閉學生的麥克風,好比在但願某個學生髮言,那麼就能夠直接開啓對方的麥克風。接下來,咱們來經過 Demo 中的代碼來看一下如何實現以上各個功能。ide

源碼講解

如下功能咱們會主要基於Java 代碼來進行講解。
這個示例中,課程的直播、師生的連麥,都是基於 Agora SDK 實現的。咱們經過如下代碼可讓用戶加入RTC頻道,實現音視頻的互通。

@Override
    public void joinChannel(Map<String, String> data) {
        sdk.joinChannel(data.get(TOKEN), data.get(CHANNEL_ID), null, Integer.valueOf(data.get(USER_ID)));
    }

在課堂中的文字消息、控制指令(好比學生髮出申請使用白板)等,都是基於 Agora 實時消息RTM SDK 實現的。在這裏咱們集成 RTM SDK 後,經過如下代碼讓用戶加入 RTM 頻道。

public void joinChannel(String rtcToken) {
        RtmManager.instance().joinChannel(new HashMap<String, String>() {{
            put(SdkManager.CHANNEL_ID, getChannelId());
        }});
        RtcManager.instance().joinChannel(new HashMap<String, String>() {{
            put(SdkManager.TOKEN, rtcToken);
            put(SdkManager.CHANNEL_ID, getChannelId());
            put(SdkManager.USER_ID, getLocal().getUserId());
        }});
    }

你們能夠參考 Demo 中的白板部分的代碼來實現白板功能,以下所示:

public void initBoard(String uuid, String token) {
        if (TextUtils.isEmpty(uuid)) return;
        boardManager.getRoomPhase(new Promise<RoomPhase>() {
            @Override
            public void then(RoomPhase phase) {
                if (phase != RoomPhase.connected) {
                    pb_loading.setVisibility(View.VISIBLE);
                    boardManager.roomJoin(uuid, token, new Callback<RoomJoin>() {
                        @Override
                        public void onSuccess(RoomJoin res) {
                            RoomParams params = new RoomParams(uuid, res.roomToken);
                            boardManager.init(whiteSdk, params);
                        }
​
                        @Override
                        public void onFailure(Throwable throwable) {
                            ToastManager.showShort(throwable.getMessage());
                        }
                    });
                }
            }
​
            @Override
            public void catchEx(SDKError t) {
                ToastManager.showShort(t.getMessage());
            }
        });
    }

老師端的屏幕共享,僅支持在 Web 端發起,如下是 Web 代碼是老師端的實現邏輯。

async startScreenShare (token: string) {
    this.shareClient = new AgoraRTCClient();
    await this.shareClient.createLocalStream({
      video: false,
      audio: false,
      screen: true,
      screenAudio: true,
      streamID: SHARE_ID,
      microphoneId: '',
      cameraId: ''
    })
    await this.shareClient.createClient(APP_ID);
    await this.shareClient.join(SHARE_ID, this.channel, token);
    await this.shareClient.publish();
    this.shared = true;
  }

如下 Java 代碼是學生端處理屏幕共享流(僅支持觀看屏幕共享)的代碼。

public void onScreenShareJoined(int uid) {
       if (surface_share_video == null) {
           surface_share_video = RtcManager.instance().createRendererView(this);
       }
       layout_whiteboard.setVisibility(View.GONE);
       layout_share_video.setVisibility(View.VISIBLE);
       removeFromParent(surface_share_video);
       surface_share_video.setTag(uid);
       layout_share_video.addView(surface_share_video, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
       RtcManager.instance().setupRemoteVideo(surface_share_video, VideoCanvas.RENDER_MODE_FIT, uid);
   }
   @Override
   public void onScreenShareOffline(int uid) {
       Object tag = surface_share_video.getTag();
       if (tag instanceof Integer) {
           if ((int) tag == uid) {
               layout_whiteboard.setVisibility(View.VISIBLE);
               layout_share_video.setVisibility(View.GONE);
               removeFromParent(surface_share_video);
               surface_share_video = null;
           }
       }
   }

在線錄製只有使用 Web 端的老師才能夠發起,如下是 Web 老師端開啓雲端錄製的代碼邏輯:

public async start(): Promise<any> {
    if (this.resourceId === undefined) {
      throw {
        recordingErr: {
          message: 'start recording failed',
        },
        reason: 'resourceId is undefined',
      }
    }
    const response = await AgoraFetch(`${PREFIX}/v1/apps/${this.agoraAppId}/cloud_recording/resourceid/${this.resourceId}/mode/${this.mode}/start`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: this.basicAuthorization(this.customerId, this.customerCertificate),
      },
      body: JSON.stringify({
        cname: this.channelName,
        uid: this.uid,
        clientRequest: {
          token: this.token,
          recordingConfig: this.recordingConfig,
          storageConfig: this.storageConfig,
        },
      })
    });
    const res = await response.json();
    if (typeof res.sid === "string") {
        this.recordId = res.sid;
    } else {
      throw {
        recordingErr: {
          message: 'start recording failed',
        },
        reason: 'recordId is invalid',
      }
    }
    return res;
  }

FAQ

Q:支持的平臺和版本(iOS/Android/Web)

本示例項目支持如下平臺和版本:

  • iOS 10 及以上。
  • Android 4.4 及以上。
  • Web Chrome 72 及以上。
注意,目前示例 Demo 還未適配 iPad,因此部分 iPad 運行 Demo 時會出現黑邊,須要你根據本身的業務需求在代碼中進行調整、適配。

Q:一直報錯人數已滿(iOS/Android/Web)

這是因爲本示例項目沒有用戶系統,沒法及時查詢在線人數。本示例項目使用 Agora RTM SDK 查詢在線人數。在用戶異常退出後,RTM 沒法及時知曉該用戶狀態。通常狀況下,須要等待 10 秒左右 RTM 才能更新當前用戶狀態。若是你有用戶系統,就能夠不須要使用 RTM 查詢在線人數。

Q:音視頻沒法鏈接(iOS/Android/Web)

這頗有多是由於 Agora RTC SDK 的 token 配置存在問題。請檢查你的 token 配置。請在聲網文檔中心搜索「校驗用戶權限」,參考相關文檔。

請注意,Agora RTC SDK 的 token 和 channelId 須要對應。若是 channelId 變了,配置的 token 也須要變。

Q:白板鏈接異常(iOS/Android/Web)

Demo 中的白板採用的是合做夥伴 Netless 的接口,若是發現鏈接異常,多是 token 配置有問題。白板的 token 分爲 sdkToken 和 roomToken,請在https://developer.netless.lin... 搜索這兩個關鍵詞,檢查 token 的設置是否存在問題。

Q:教室裏雲端錄製(Web)

若是你的團隊有後端開發能力,咱們建議使用聲網本地服務端錄製 SDK,將錄製功能集成在後端。

若是沒有後端開發團隊,也能夠參考聲網文檔中心的「雲端錄製快速開始」,實現雲端錄製功能。要注意,本示例項目將錄製集成在了前端,存在暴露 OSS 訪問操做的安全隱患,部署雲錄製業務也可能存在困難。 如遇到問題能夠訪問 RTC 開發者社區(rtcdeveloper.com),發帖尋求幫助。

聲網雲端錄製服務支持合流錄製和單流錄製。合流錄製是比較簡單的集成方案,具體可參考聲網文檔中心教程。

Q:白板課件管理(Web)

本示例項目中,白板課件管理部署在前端。建議你實現排課業務後,在課程裏預先上傳課件,Web 端只讀取課件便可。

本示例項目中涉及的 OSS 相關的接入,建議參考 stsToken 的上傳方案集成(https://help.aliyun.com/docum...)。建議不要使用示例項目中的 accessKey 和 secretKey 的上傳方案集成,可能存在安全隱患。

注意

  • 本示例源碼中,屏幕共享的 UID 固定爲 7,你須要根據本身的業務進行調整。
  • 本示例項目中的 channelId 是 MD5 後的,你須要對接本身的環境進行修改。
  • 推薦你使用本身的業務後臺管理頻道屬性,將 Agora RTM SDK 做爲指令收發器,配合 Agora Native/Web SDK 實現具體業務邏輯。

源碼與更多

歡迎在測試源碼的同時,提出更多關於 Demo 優化、改進的更多想法。咱們會對每位提出有效建議的開發者送上豐厚獎勵。

點擊這裏獲取Demo源碼,瞭解 Demo 評測獎勵

相關文章
相關標籤/搜索