1. 程式人生 > >騰訊雲互動直播分享螢幕小結

騰訊雲互動直播分享螢幕小結

基於不同的場景提供不同的功能,對於而今最流行的自然是面對面直播,即通過攝像頭來形成流視訊來進行直播互動。

那麼對於線上教育行業,就需要進行螢幕分享了。

一般對於線上教育的場景就是需要顯示老師分享的螢幕(大螢幕)以及老師自己的攝像頭螢幕(小螢幕)

基於騰訊雲隨心播開發

場景1:

分享螢幕以及攝像頭螢幕

首先,在activity註冊廣播事件

 private void registerReceiver() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction
(Constants.ACTION_SURFACE_CREATED); intentFilter.addAction(Constants.ACTION_HOST_ENTER); intentFilter.addAction(Constants.ACTION_CAMERA_OPEN_IN_LIVE); intentFilter.addAction(Constants.ACTION_CAMERA_CLOSE_IN_LIVE); intentFilter.addAction(Constants.ACTION_SWITCH_VIDEO);
intentFilter.addAction(Constants.ACTION_HOST_LEAVE); intentFilter.addAction(Constants.ACTION_SCREEN_SHARE_IN_LIVE); registerReceiver(mBroadcastReceiver, intentFilter); }

其實通過翻譯還是很好理解,我覺得我還是解釋一下各個事件的含義。

ACTION_SURFACE_CREATED:AvSurfaceView 初始化成功
ACTION_HOST_ENTER:主播進入房間
ACTION_CAMERA_OPEN
_IN_LIVE:有人開啟攝像頭 ACTION_CAMERA_CLOSE_IN_LIVE:有人關閉攝像頭 ACTION_SWITCH_VIDEO:點選成員回撥 ACTION_HOST_LEAVE:主播結束直播 ACTION_SCREEN_SHARE_IN_LIVE:有人分享螢幕

針對不同的事件做不同的處理,很多功能基本上就ok了。

迴歸正題,當接收到分享螢幕訊息時

         if (action.equals(Constants.ACTION_SCREEN_SHARE_IN_LIVE)) {//有螢幕分享
                ArrayList<String> ids = intent.getStringArrayListExtra("ids");
                //如果是自己本地直接渲染
                for (String id : ids) {
                    if (!mRenderUserList.contains(id)) {
                        mRenderUserList.add(id);
                    }
                    updateHostLeaveLayout();

                    if (id.equals(MySelfInfo.getInstance().getId())) {
                        showVideoView(true, id);
                        return;
                    }
                }
                //其他人一併獲取
                int requestCount = CurLiveInfo.getCurrentRequestCount();
                mLiveHelper.requestScreenViewList(ids);
                isScreenShare = true;
                requestCount = requestCount + ids.size();
                CurLiveInfo.setCurrentRequestCount(requestCount);
            }

這裡先初始化一個使用者列表mRenderUserList,將使用者新增進去,這個使用者指的是主播和互動成員。如果不包含就新增,如果當前動作是主播,則 showVideoView(true, id);如果不是主播就去請求主播資料。

mLiveHelper.requestScreenViewList(ids);

看看請求主播資料中如何處理

  /**
     * AVSDK 請求主播資料
     *
     * @param identifiers 主播ID
     */
    public void requestScreenViewList(ArrayList<String> identifiers) {
        SxbLog.i(TAG, "requestViewList " + identifiers);
        if (identifiers.size() == 0) return;
        AVEndpoint endpoint = ((AVRoomMulti) QavsdkControl.getInstance().getAVContext().getRoom()).getEndpointById(identifiers.get(0));
        SxbLog.d(TAG, "requestViewList hostIdentifier " + identifiers + " endpoint " + endpoint);
        if (endpoint != null) {
            ArrayList<String> alreadyIds = QavsdkControl.getInstance().getRemoteVideoIds();//已經存在的IDs

            SxbLog.i(TAG, "requestViewList identifiers : " + identifiers.size());
            SxbLog.i(TAG, "requestViewList alreadyIds : " + alreadyIds.size());
            for (String id : identifiers) {//把新加入的新增到後面
                if (!alreadyIds.contains(id)) {
                    alreadyIds.add(id);
                }
            }
            int viewindex = 0;
            for (String id : alreadyIds) {//一併請求
                if (viewindex >= 4) break;
                AVView view = new AVView();
                view.videoSrcType = AVView.VIDEO_SRC_TYPE_SCREEN;
                view.viewSizeType = AVView.VIEW_SIZE_TYPE_BIG;
                //介面數
                mRequestViewList[viewindex] = view;
                mRequestIdentifierList[viewindex] = id;
                viewindex++;
            }
            QavsdkControl.getInstance().getAvRoomMulti().requestViewList(mRequestIdentifierList, mRequestViewList, viewindex, mRequestViewListCompleteCallback);

        } else {
            if (null != mContext) {
                Toast.makeText(mContext, "Wrong Room!!!! Live maybe close already!", Toast.LENGTH_SHORT).show();
            }
        }


    }

這裡就是請求主播分享螢幕資料,回撥在mRequestViewListCompleteCallback,支援最多四個,型別為

view.videoSrcType = AVView.VIDEO_SRC_TYPE_SCREEN;

看看回調


    private AVRoomMulti.RequestViewListCompleteCallback mRequestViewListCompleteCallback = new AVRoomMulti.RequestViewListCompleteCallback() {
        public void OnComplete(String identifierList[], AVView viewList[], int count, int result,String s) {
            String ids = "";

            for (String id : identifierList) {
                mLiveView.showVideoView(REMOTE, id);
                ids = ids + " " + id;
            }
            SxbLog.d(TAG, LogConstants.ACTION_VIEWER_SHOW + LogConstants.DIV + MySelfInfo.getInstance().getId() + LogConstants.DIV + "get stream data"
                    + LogConstants.DIV + LogConstants.STATUS.SUCCEED + LogConstants.DIV + "ids " + ids);
            // TODO
            SxbLog.d(TAG, "RequestViewListCompleteCallback.OnComplete");
        }
    };

主要是走了 mLiveView.showVideoView(REMOTE, id);,在這裡面開啟相應視窗


    /**
     * 載入視訊資料
     *
     * @param isLocal 是否是本地資料
     * @param id      身份
     */
    @Override
    public void showVideoView(boolean isLocal, final String id) {
        Log.i(TAG, "showVideoView " + id + "isLocal" + isLocal);
        //渲染本地Camera
        if (isLocal == true) {
            QavsdkControl.getInstance().setSelfId(id);
            QavsdkControl.getInstance().setLocalHasVideo(true, id);
            //主播通知使用者伺服器
            Log.i(TAG, "showVideoView host :" + id);
        } else {
            Log.i(TAG, "showVideoView :" + id);
            if (isScreenShare) {
                QavsdkControl.getInstance().setRemoteHasVideo(true, id, AVView.VIDEO_SRC_TYPE_SCREEN);
                isScreenShare = false;
            } else {
                QavsdkControl.getInstance().setRemoteHasVideo(true, id, AVView.VIDEO_SRC_TYPE_CAMERA);
            }
        }
    }

至此整個流程結束。然而事實並沒有那麼簡單。
顯示攝像頭小視窗,同上,然而我們點選進去隨心播setRemoteHasVideo看一下

 public void setRemoteHasVideo(boolean isRemoteHasVideo, String identifier, int videoSrcType) {
        SxbLog.i(TAG, "setRemoteHasVideo : " + identifier);
        if (null != mAVUIControl) {
            mAVUIControl.setSmallVideoViewLayout(isRemoteHasVideo, identifier, videoSrcType);
        }
    }

我滴天,竟然是小窗口布局,分享螢幕要全屏啊,是不是很溜。彆著急,我們在找找,然後找到了

  public void setRemoteHasVideo(String identifier, int videoSrcType, boolean isRemoteHasVideo) {
        if (null != mAVUIControl) {
            mAVUIControl.setRemoteHasVideo(identifier, videoSrcType, isRemoteHasVideo, false, false);
        }
    }

所以方法需要改一下,畢竟引數位置不一樣,修改後的呼叫

 if (isScreenShare) {
                QavsdkControl.getInstance().setRemoteHasVideo(id, AVView.VIDEO_SRC_TYPE_SCREEN, true);
                isScreenShare = false;
            } else {
                QavsdkControl.getInstance().setRemoteHasVideo(true, id, AVView.VIDEO_SRC_TYPE_CAMERA);
            }

分享螢幕呼叫大屏,開啟攝像頭需要呼叫小屏。

然而事實並沒有什麼卵用,不對,有用,但是在某些場景下需要調整。

比如,學生進入直播的時候老師已經開啟攝像頭以及分享了螢幕。那麼學生進入需要幾乎是同時處理開啟攝像頭,這樣會造成頁面卡頓,或者說兩個頁面會有一個視屏流不動了。大家做專案的時候可以親測一下,為了解決這個問題,我在接收分享螢幕的廣播後面增加一個延遲。

 if (action.equals(AVConstants.ACTION_SCREEN_SHARE_IN_LIVE)) {//有螢幕分享
                LogUtils.e("有螢幕分享");
                isBegin=true;
                HandlerUtils.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        ArrayList<String> ids = intent.getStringArrayListExtra("ids");
                        //如果是自己本地直接渲染
                        String identifier = Constants.TEST_T + UserManager.getInstance().getUserModel().getId();
                        for (String id : ids) {
                            if (!mRenderUserList.contains(id)) {
                                mRenderUserList.add(id);
                            }
                            if (id.equals(identifier)) {
                                showVideoView(true, id);
                                return;
                            }
                        }
                        //其他人一併獲取
                        int requestCount = CurLiveInfo.getCurrentRequestCount();
                        mLiveHelper.requestScreenViewList(ids);
                        isScreenShare = true;
                        requestCount = requestCount + ids.size();
                        CurLiveInfo.setCurrentRequestCount(requestCount);
                    }
                }, 1000);

            }

這裡程式碼肯定要寫在主執行緒的,不用多想,這樣解決同時請求兩路資料,會造成一路卡屏的情況。
如果你以為這樣就結束了,那就太小看直播的整合難度了。

在學生進入直播間,老師未分享螢幕的情況下,如果老師點選分享螢幕還是會造成卡頓,就類似與如果分開去拿AVSDK資料,在開啟相應視窗顯示就會遇到這種情況。

那麼如何解決?殺死一萬腦細胞之後是這麼做的。

    /**
     * AVSDK 請求主播資料
     *
     * @param identifiers 主播ID
     */
    public void requestScreenViewList(ArrayList<String> identifiers) {
        Log.i(TAG, "requestViewList " + identifiers);
        if (identifiers.size() == 0) return;
        AVEndpoint endpoint = QavsdkControl.getInstance().getAVContext().getRoom().getEndpointById(identifiers.get(0));
        Log.d(TAG, "requestViewList hostIdentifier " + identifiers + " endpoint " + endpoint);
        if (endpoint != null) {
            ArrayList<String> alreadyIds = QavsdkControl.getInstance().getRemoteVideoIds();//已經存在的IDs

            Log.i(TAG, "requestViewList identifiers : " + identifiers.size());
            Log.i(TAG, "requestViewList alreadyIds : " + alreadyIds.size());
            for (String id : identifiers) {//把新加入的新增到後面
                if (!alreadyIds.contains(id)) {
                    alreadyIds.add(id);
                }
            }
            int viewindex = 0;
            for (String id : alreadyIds) {//一併請求
                if (viewindex >= 4) break;
                AVView view2 = new AVView();
                view2.videoSrcType = AVView.VIDEO_SRC_TYPE_CAMERA;
                view2.viewSizeType = AVView.VIEW_SIZE_TYPE_BIG;
                //介面數
                mRequestViewList[viewindex] = view2;
                mRequestIdentifierList[viewindex] = id;
                viewindex++;
                AVView view = new AVView();
                view.videoSrcType = AVView.VIDEO_SRC_TYPE_SCREEN;
                view.viewSizeType = AVView.VIEW_SIZE_TYPE_BIG;
                //介面數
                mRequestViewList[viewindex] = view;
                mRequestIdentifierList[viewindex] = id;
                viewindex++;
            }
            QavsdkControl.getInstance().getAvRoomMulti().requestViewList(mRequestIdentifierList, mRequestViewList, viewindex, mRequestViewListCompleteCallback);

        } else {
            if (null != mContext) {
                Toast.makeText(mContext, "Wrong Room!!!! Live maybe close already!", Toast.LENGTH_SHORT).show();
            }
        }


    }

在去請求分享螢幕的主播資料的時候,同時請求攝像頭的主播資料,就類似於請求分享螢幕的資料時重新整理攝像頭的資料,這樣就解決了分享螢幕造成的卡頓問題。

基本上到這,分享螢幕以及開啟攝像頭就能共存運行了,來一張專案效果圖吧

這裡寫圖片描述

當然還有一些其他的處理問題,比如當你沒有收到分享資訊該怎麼辦,你在老師上課之後進入如何保證收到監聽資訊。

這些都需要進行心跳連線,通過心跳連線接收主播端實時資料,進行相應處理。

比如學生進入直播間會給老師發生進入直播訊息,相應老師會通過心跳傳送直播狀態資訊,學生根據資訊做相應處理,就增加了直播的穩定性。

    /**
     * 攝像頭開閉
     *
     * @param b
     */
    private void toggleCameraViewOfTeacher(final boolean b) {
        String identifier = Constants.TEST_T + CurLiveInfo.getHostID();
        if (b) {
            QavsdkControl.getInstance().setRemoteHasVideo(true, identifier, AVView.VIDEO_SRC_TYPE_CAMERA);
        } else {
            QavsdkControl.getInstance().setRemoteHasVideo(false, identifier, AVView.VIDEO_SRC_TYPE_CAMERA);
        }
    }

    /**
     * 螢幕分享開閉
     *
     * @param b
     */
    private void toggleShareViewOfTeacher(final boolean b) {
        String identifier = Constants.TEST_T + CurLiveInfo.getHostID();
        LogUtils.e("toggleShareViewOfTeacher identifier:" + identifier + " b:" + b);
        if (!b) {
            QavsdkControl.getInstance().setRemoteHasVideo(identifier, AVView.VIDEO_SRC_TYPE_SCREEN, false);
        } else {
            QavsdkControl.getInstance().setRemoteHasVideo(identifier, AVView.VIDEO_SRC_TYPE_SCREEN, true);
        }
    }

其他相應處理這裡就不多說了,根據相應功能場景定製好相應的文字結構。

相關推薦

互動直播分享螢幕小結

基於不同的場景提供不同的功能,對於而今最流行的自然是面對面直播,即通過攝像頭來形成流視訊來進行直播互動。 那麼對於線上教育行業,就需要進行螢幕分享了。 一般對於線上教育的場景就是需要顯示老師分享的螢幕(大螢幕)以及老師自己的攝像頭螢幕(小螢幕) 基於騰訊雲

互動直播SDK整合綜述

SDK構成 互動直播SDK由兩部分構成,IMSDK和AVSDK 其中IMSDK為雲通訊SDK,為AVSDK提供賬號登入、信令通道、IM彈幕訊息、日誌模組、日誌上報等功能 AVSDK提供攝像頭採集、編碼、解碼、美顏等一系列功能(下圖為AVSDK整體框架) 登

申請參加自媒體分享計劃,送代金券+CN域名

gdal 認證 port 其它 計劃 CA wan 參加 面向 layout: default title: 申請參加騰訊雲自媒體分享計劃,送代金券+CN域名 category: [技術, 破解] comments: true --- 文章介紹 看到騰訊支持博客了,就嘗試

直播demo配置流程

騰訊小直播配置流程 1.        開通視訊雲解決方案,先申請若5天內未通過直接撥打客戶電話會馬上開通。 2.        進入視訊直播控制檯,在一鍵部署中開通各項服務,其中Bucket為自己建立的Bucket名稱,AppId在自己的賬號資訊中可獲得,SecretId

視訊直播sdk開發攻略

視訊直播這一兩年在移動網際網路上可以說是非常的火,各種視訊直播軟體層出不窮。有的通過自己的推廣宣傳確實火了起來,比如:映客。 我之前也是在一家專門做視訊直播的公司打醬油,當時對這個概念還是很模糊,後來才慢慢的瞭解清楚視訊直播的這個概念。後來離開這家公司,到現在的公司,做了一

iOSMTA嵌入方法使用小結

1 開始嵌入SDK 1.1 獲取AppKey 登陸騰訊雲分析移動統計前臺http://mta.qq.com,點選"檢視資料",選擇"註冊應用",按照步驟提示註冊應用,即可獲得AppKey。 如果應用是

Android學習之互動直播開發經驗小結

最近外派到XXX公司做一個帶直播功能的pad專案,整合的是騰訊的互動直播,今天寫了一下經驗小結,方便以後使用。 互動直播整合流程: 1:需要到騰訊雲直播平臺下載SDK,注意點,現在騰訊SDK的下載需要經過實名制認證的賬戶才具有下載資格許可權,只有通過騰訊資格

短信服務使用記錄與.NET Core C#代碼分享

date dom factory reat throw must ret off ont 1、即使是相同的短信簽名與短信正文模板,也需要針對“國內文本短信”與“海外文本短信”分別申請。開始不知道,以為只要申請一次,給國外手機發

一文帶你深度解析直播答題方案

exc com erp 同學 col 測試 的確 影響 cep 歡迎大家前往雲+社區,獲取更多騰訊海量技術實踐幹貨哦~ 作者:騰訊視頻雲 進入2018年最火的新鮮事物無疑就是“直播答題”了,動輒上百萬的獎金更是吸引了大量用戶的參與。一場直播動輒幾百萬的獎金,每人可以分到

+社區分享——OCR文字識別

取出 文章分享 經理 復雜 獲取 圖文 沒有 離線 服務 歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐幹貨哦~ 本文由雲+社區運營團隊發布在騰訊雲+社區 前言 2018年3月27日騰訊雲雲+社區聯合騰訊雲智能圖像團隊共同在客戶群舉辦了騰訊雲OCR文字識別——

融合通信應用場景及案例分享

客戶 告訴 公司 通道 降低成本 傳輸 sage 公眾 先後 歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐幹貨哦~ 本文由雲加社區技術沙龍發表於騰訊雲技術沙龍 張騰,騰訊通信雲高級產品經理,先後負責過手機、智能硬件等終端產品,對運營商、即時通信、音視頻產品均有了解,

從QQ音樂開發,探討如何利用SDK在直播中加入視頻動畫

根據 經理 主存 不存在 alloc 依然 騰訊遊戲 配置 目前 歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐幹貨哦~ 本文由騰訊遊戲雲發表於雲+社區專欄 看著精彩的德甲賽事,突然裁判一聲口哨,球賽斷掉了,屏幕開始自動播放“吃麥趣雞盒,看德甲比賽”的視頻廣告 那麽

融合通訊應用場景及案例分享

歡迎大家前往騰訊雲+社群,獲取更多騰訊海量技術實踐乾貨哦~ 張騰,騰訊通訊雲高階產品經理,先後負責過手機、智慧硬體等終端產品,對運營商、即時通訊、音視訊產品均有了解,負責產品場景話包裝,對融合通訊的應用場景具有較深瞭解。 如何幫助這些很大的企業,基於我們

直播(入門版)快速整合

這篇部落格為快速整合篇,按照此部落格,你可以快速整合一個相當簡單的Demo,如果你需要一個功能完整的專案,我也在GitHub上為你準備好。下面跟我快速整合一下騰訊雲直播吧! 第一步:註冊 騰訊雲賬號 並且實名認證。 接下來 你就拿到了推流和播放地址啦

從QQ音樂開發,探討如何利用SDK在直播中加入視訊動畫

歡迎大家前往騰訊雲+社群,獲取更多騰訊海量技術實踐乾貨哦~ 本文由騰訊遊戲雲發表於雲+社群專欄 看著精彩的德甲賽事,突然裁判一聲口哨,球賽斷掉了,螢幕開始自動播放“吃麥趣雞盒,看德甲比賽”的視訊廣告 那麼問題來了,如何在直播流中,無縫的插入點播視訊檔案呢?

優測優分享 | 談談移動端螢幕適配的幾種方法

騰訊優測是專業的移動雲測試平臺,自動化測試提供全面相容性適配測試,雲真機提供遠端真機租用服務,優分享不定時提供大量移動研發及測試相關乾貨! 移動端web開發相對於PC端web開發,我們可以慶幸不用相容那麼多瀏覽器了,但是隨之而來的卻是各種螢幕尺寸的適配,個人覺得,比PC端還

直播面試時的問題和解答

1.直播功能???? 答:我們這個專案裡的直播採用的是整合騰訊雲直播SDK進行的,因為在直播中可能會涉及到彈幕和刷禮物等功能所以還需要整合騰訊的IM即時通訊,並且通過騰訊雲服務,直播的流程大概由以下幾個步驟組成,採集、編碼、封裝、主播推流到伺服器、伺服器通過CDN對流進行

直播初體驗

移動直播安卓的整合其實相對簡單,主要分為推流端功能和播放端功能,主要實現條件大致分為以下三點: ①RTMP SDK整合與使用 ②拼接出推流地址(可由後臺伺服器提供) ③拼接出播放地址(可由後臺伺服器提供) ***本文將主要介紹SDK的整合和功能實現方案。*** 一、RTMP SDK整合 ① [SDK下載

直播相關問題處理

問題①:彈幕有時候沒有從最右邊出現,一開始就顯示在彈幕區中間,是因為上一條彈幕劃過改變了起始位置。 mDanmakuView.pause(); mDanmakuView.addDanmaku(danm

EasyNVR結合阿里/CDN實現微信/小程式直播的方案

背景需求: 許多客戶有這樣的需求:微信公眾號做為平臺來對攝像機進行直播;可以讓使用者隨時隨地開啟公共號就可以觀看;保證畫面的流暢性;保證視訊的併發訪問量等。 問題分析: 雖然需求看似很簡單,其實真正實現起來還是有相當多的阻礙。 首先:如何讓攝像機