近期遇到項目,其中有在Android平臺播放rtsp流媒體的需求飞崖。整理若干資料如下,備查谨胞。
何謂流媒體
有別于傳統的視頻文件播放固歪,流媒體是專門用于在網絡上傳輸的,采用所謂的流式傳輸方式。
既然在網絡上傳輸牢裳,就免不了有協議用來規(guī)定傳輸過程中的各個場景逢防。流媒體的協議很多,經過前期選型蒲讯,項目中采用了較為常用的RTSP協議忘朝。也曾經考慮過用RTMP協議,但考慮到RTSP的實時性要好于RTMP判帮,更貼合項目需求局嘁,故而選擇了RTSP。
百度百科的詞條里介紹的比較清楚了晦墙,在決定開發(fā)之前悦昵,最好先通讀一遍。
編碼器晌畅、服務器與解碼器
以近期火爆的直播為例但指,編碼器是指流媒體的采集端,如美女主播用的手機APP抗楔、游戲直播用的PC端軟件(如OBS)等枚赡。編碼器將攝像頭、屏幕或具體的視頻文件谓谦,處理成流媒體特定的格式發(fā)往服務器贫橙。而項目中使用的則是專門的硬件編碼器,作用是將HDMI傳輸的視頻流編碼成網絡信號傳給服務器反粥。
服務器起到中轉的作用卢肃,一方面接收編碼器的推送,另一方面負責向單個或多個解碼器分發(fā)視頻流才顿。當然莫湘,很多時候還會有存儲功能。
解碼器就是用來播放視頻流的郑气,如各類視頻播放器幅垮。
常見的解決方案
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插件(可以走走歪門邪道)
開放的直播平臺也不失為一種快速解決方案爹橱,如目睹直播(親測,無需認證或充值即可測試)窄做、樂視云視頻(資質認證一直未能通過)等。一些直播方面的知識也可從這些網站上獲取慰技。
國內的開發(fā)者平臺椭盏,如阿里云的視頻直播、百度云的音視頻直播LSS等吻商,是無需自己搗騰服務器軟件掏颊、而又可自主掌控直播的另一種途徑。并且艾帐,作為開發(fā)者平臺的產物乌叶,要比普通直播平臺提供了更為開放的接口和擴展能力。
此外柒爸,mplayer准浴、ffdshow 提供了開源的解碼器方案,但相對復雜捎稚。vitamio支持Android和iOS乐横,是國產媒體播放領域的翹楚。需要注意的是今野,vitamio對于企業(yè)商用是需要授權的葡公,但官網提到的執(zhí)行周期是14年底,也算是對混亂的國內知識產權領域的一種冷嘲吧条霜。
使用vitamio播放rtsp遇到的問題
vitamio官網 和 官方github 的版本較亂催什,但好在使用并不復雜。
從官網下載vitamio20160930.zip宰睡,加壓后有InitActivity和VitamioListActivity兩個文件夾蒲凶,后面這個目測用不到,在AndroidStudio中將前者引入成Module拆内,并在原項目Module中增加InitActivity的依賴豹爹。
接下來的開發(fā)中遇到了些許問題,記錄如下矛纹。
- 無法固定外框大小
單獨的使用io.vov.vitamio.widget.VideoView插件臂聋,即使在xml中設置了高和寬,或者在代碼中動態(tài)設置,均無法生效孩等。下面是一個無效的例子:
<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" />
- 動態(tài)調整外框大小后無法正確顯示
網上一般的寫法艾君,是在io.vov.vitamio.widget.VideoView外面包裹一層io.vov.vitamio.widget.CenterLayout,這對于意圖在代碼中動態(tài)調整外框的需求是無效的肄方。
同時冰垄,記得在調整大小后,調用
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播放視頻虹茶,而實際使用中發(fā)現,啟動后隅要,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上單擊后變大,再次單擊后返回原始狀態(tài)第步。
而setOnClickListener后唧领,發(fā)現點擊事件不會被觸發(fā)。
原因是VideoView.java中的onTouchEvent將事件“消化”掉了雌续,修改即可斩个。
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (isInPlaybackState() && mMediaController != null)
toggleMediaControlsVisiblity();
//return false;
return super.onTouchEvent(ev);
}