關于流媒體開發的若干筆記

近期遇到項目,其中有在Android平臺播放rtsp流媒體的需求。整理若干資料如下,備查。

何謂流媒體

有別于傳統的視頻文件播放,流媒體是專門用于在網絡上傳輸的,采用所謂的流式傳輸方式。

既然在網絡上傳輸,就免不了有協議用來規定傳輸過程中的各個場景。流媒體的協議很多,經過前期選型,項目中采用了較為常用的RTSP協議。也曾經考慮過用RTMP協議,但考慮到RTSP的實時性要好于RTMP,更貼合項目需求,故而選擇了RTSP。

百度百科的詞條里介紹的比較清楚了,在決定開發之前,最好先通讀一遍。

編碼器、服務器與解碼器

以近期火爆的直播為例,編碼器是指流媒體的采集端,如美女主播用的手機APP、游戲直播用的PC端軟件(如OBS)等。編碼器將攝像頭、屏幕或具體的視頻文件,處理成流媒體特定的格式發往服務器。而項目中使用的則是專門的硬件編碼器,作用是將HDMI傳輸的視頻流編碼成網絡信號傳給服務器。

服務器起到中轉的作用,一方面接收編碼器的推送,另一方面負責向單個或多個解碼器分發視頻流。當然,很多時候還會有存儲功能。

解碼器就是用來播放視頻流的,如各類視頻播放器。

常見的解決方案

VLCFFmpeg 是最為常用的開源跨平臺的音視頻流解決方案。live555是一個為流媒體提供解決方案的跨平臺的C++開源項目,據說是為VLC提供了視頻播放方案,由于沒有官方的Android支持,故而未曾深入研究。

對編碼器而言,常見的OBS可以支持win、mac、Linux三大平臺,Android上有libstreaming,而iOS未曾深入研究。當然,還有前面提到的專門的編碼器設備。

服務器的解決方案主要有(引自知乎李楊的回答

  • 流媒體解決方案 Live555 (C++)
  • 流媒體平臺框架 EasyDarwin (C++,國產精品)
  • 實時流媒體播放服務器程序DarwinStreamingSrvr (C++)
  • Flash流媒體服務器 Red5 (Java)
  • 流媒體服務器 Open Streaming Server (Java)
  • FMS流媒體服務器 (Adobe,收費的)
  • Wowza流媒體服務器(Java)
  • 開源流媒體平臺FreeCast(Java)
  • Nginx+RTMP插件(可以走走歪門邪道)

開放的直播平臺也不失為一種快速解決方案,如目睹直播(親測,無需認證或充值即可測試)、樂視云視頻(資質認證一直未能通過)等。一些直播方面的知識也可從這些網站上獲取。

國內的開發者平臺,如阿里云的視頻直播百度云的音視頻直播LSS等,是無需自己搗騰服務器軟件、而又可自主掌控直播的另一種途徑。并且,作為開發者平臺的產物,要比普通直播平臺提供了更為開放的接口和擴展能力。

此外,mplayerffdshow 提供了開源的解碼器方案,但相對復雜。vitamio支持Android和iOS,是國產媒體播放領域的翹楚。需要注意的是,vitamio對于企業商用是需要授權的,但官網提到的執行周期是14年底,也算是對混亂的國內知識產權領域的一種冷嘲吧。

使用vitamio播放rtsp遇到的問題

vitamio官網官方github 的版本較亂,但好在使用并不復雜。

從官網下載vitamio20160930.zip,加壓后有InitActivityVitamioListActivity兩個文件夾,后面這個目測用不到,在AndroidStudio中將前者引入成Module,并在原項目Module中增加InitActivity的依賴。

接下來的開發中遇到了些許問題,記錄如下。

  • 無法固定外框大小
    單獨的使用io.vov.vitamio.widget.VideoView插件,即使在xml中設置了高和寬,或者在代碼中動態設置,均無法生效。下面是一個無效的例子:
<io.vov.vitamio.widget.VideoView   
  android:id="@+id/surface_view"   
  android:layout_width="280dp"  
  android:layout_height="210dp"  
  android:layout_centerHorizontal="true" 
  android:layout_centerVertical="true" />
  • 動態調整外框大小后無法正確顯示
    網上一般的寫法,是在io.vov.vitamio.widget.VideoView外面包裹一層io.vov.vitamio.widget.CenterLayout,這對于意圖在代碼中動態調整外框的需求是無效的。
    同時,記得在調整大小后,調用
    videoView.setVideoLayout(VideoView.VIDEO_LAYOUT_FIT_PARENT, 0);
    經過嘗試,下面的做法是可行的:
<RelativeLayout
    android:padding="4dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/bg_video">

    <io.vov.vitamio.widget.VideoView
        android:id="@+id/surface_view"
        android:layout_width="280dp"
        android:layout_height="210dp"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true" />

</RelativeLayout>
  • 透屏及花屏問題
    項目中是在百度地圖上層放置一個VideoView播放視頻,而實際使用中發現,啟動后,VideoView不顯示;而將地圖層先隱藏再手動顯示后,會出現花屏現象,且顯示極不清晰。
    網上介紹的兩種方法在我的項目中并沒能生效:
    1. vitamio插件的io.vov.vitamio.widget.VideoView.java
    152行 surfaceCreated函數,加入一行代碼搞定
    mSurfaceHolder.setFormat(PixelFormat.RGBX_8888);
    2. AndroidManifest.xml文件中,播放器的Activity主題背景修改為
    android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"
    據查,原因應該是VideoView啟動后,默認至于最下層。
    修改VideoView.java源碼,在initVideoView函數中任意地方增加如下代碼即可:
    setZOrderOnTop(true);

  • 無法響應click事件
    項目需求是在VideoView上單擊后變大,再次單擊后返回原始狀態。
    而setOnClickListener后,發現點擊事件不會被觸發。
    原因是VideoView.java中的onTouchEvent將事件“消化”掉了,修改即可。

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (isInPlaybackState() && mMediaController != null)
            toggleMediaControlsVisiblity();
        //return false;
        return super.onTouchEvent(ev);
    }
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容