近期遇到項目,其中有在Android平臺播放rtsp流媒體的需求。整理若干資料如下,備查。
何謂流媒體
有別于傳統的視頻文件播放,流媒體是專門用于在網絡上傳輸的,采用所謂的 流式傳輸 方式。
既然在網絡上傳輸,就免不了有協議用來規定傳輸過程中的各個場景。流媒體的協議很多,經過前期選型,項目中采用了較為常用的RTSP協議。也曾經考慮過用RTMP協議,但考慮到RTSP的實時性要好于RTMP,更貼合項目需求,故而選擇了RTSP。
百度百科 的詞條里介紹的比較清楚了,在決定開發之前,最好先通讀一遍。
編碼器、服務器與解碼器
以近期火爆的直播為例,編碼器是指流媒體的采集端,如美女主播用的手機APP、游戲直播用的PC端軟件(如OBS)等。編碼器將攝像頭、屏幕或具體的視頻文件,處理成流媒體特定的格式發往服務器。而項目中使用的則是專門的硬件編碼器,作用是將HDMI傳輸的視頻流編碼成網絡信號傳給服務器。
服務器起到中轉的作用,一方面接收編碼器的推送,另一方面負責向單個或多個解碼器分發視頻流。當然,很多時候還會有存儲功能。
解碼器就是用來播放視頻流的,如各類視頻播放器。
常見的解決方案
VLC 和 FFmpeg 是最為常用的開源跨平臺的音視頻流解決方案。 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 等,是無需自己搗騰服務器軟件、而又可自主掌控直播的另一種途徑。并且,作為開發者平臺的產物,要比普通直播平臺提供了更為開放的接口和擴展能力。
此外, mplayer 、 ffdshow 提供了開源的解碼器方案,但相對復雜。 vitamio 支持Android和iOS,是國產媒體播放領域的翹楚。需要注意的是,vitamio對于企業商用是需要授權的,但 官網提到的執行周期 是14年底,也算是對混亂的國內知識產權領域的一種冷嘲吧。
使用vitamio播放rtsp遇到的問題
vitamio官網 和 官方github 的版本較亂,但好在使用并不復雜。
從官網下載vitamio20160930.zip,加壓后有 InitActivity 和 VitamioListActivity 兩個文件夾,后面這個目測用不到,在AndroidStudio中將前者引入成Module,并在原項目Module中增加 InitActivity 的依賴。
接下來的開發中遇到了些許問題,記錄如下。
-
無法固定外框大小
單獨的使用 io.vov.vitamio.widget.VideoView 插件,即使在xml中設置了高和寬,或者在代碼中動態設置,均無法生效。下面是一個無效的例子:
lt;io.vov.vitamio.widget.VideoView android:id=quot;@ id/surface_viewquot; android:layout_width=quot;280dpquot; android:layout_height=quot;210dpquot; android:layout_centerHorizontal=quot;truequot; android:layout_centerVertical=quot;truequot; /gt;
-
動態調整外框大小后無法正確顯示
網上一般的寫法,是在 io.vov.vitamio.widget.VideoView 外面包裹一層 io.vov.vitamio.widget.CenterLayout ,這對于意圖在代碼中動態調整外框的需求是無效的。
同時,記得在調整大小后,調用
videoView.setVideoLayout(VideoView.VIDEO_LAYOUT_FIT_PARENT, 0);
經過嘗試,下面的做法是可行的:
lt;RelativeLayout android:padding=quot;4dpquot; android:layout_width=quot;wrap_contentquot; android:layout_height=quot;wrap_contentquot; android:background=quot;@drawable/bg_videoquot;gt; lt;io.vov.vitamio.widget.VideoView android:id=quot;@ id/surface_viewquot; android:layout_width=quot;280dpquot; android:layout_height=quot;210dpquot; android:layout_centerHorizontal=quot;truequot; android:layout_centerVertical=quot;truequot; /gt; lt;/RelativeLayoutgt;
-
透屏及花屏問題
項目中是在百度地圖上層放置一個VideoView播放視頻,而實際使用中發現,啟動后,VideoView不顯示;而將地圖層先隱藏再手動顯示后,會出現花屏現象,且顯示極不清晰。
網上介紹的 兩種方法 在我的項目中并沒能生效:
1. vitamio插件的io.vov.vitamio.widget.VideoView.java 152行 surfaceCreated函數,加入一行代碼搞定 mSurfaceHolder.setFormat(PixelFormat.RGBX_8888); 2. AndroidManifest.xml文件中,播放器的Activity主題背景修改為 android:theme=quot;@android:style/Theme.Translucent.NoTitleBar.Fullscreenquot;
據查,原因應該是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); }
Tags: 安卓開發
文章來源:http://www.jianshu.com/p/01b78fa5d3bb