android視頻播放實現
1. 安卓視頻播放(阿里雲視頻點播播放器SDK+SurfaceView)
本篇文章講述使用阿里雲視頻視頻播放sdk中的高級播放器加上SurfaceView實現,採用id+STS方法進行視頻播放。
流程:用戶App獲取STS憑證 -> 服務端下發STS憑證 -> 用戶上傳視頻並獲取vid -> 服務端獲取STS憑證 -> 將STS憑證下發給客戶端 -> 完成視頻播放。
請看阿里雲文檔=========》》》》》》 阿里雲-高級播放器Android使用說明
接下來我們來看一下安卓給我們提供的手勢控制類
介面
setOnTouchListener(this);
其中定義了四種狀態 NONE = 0, VOLUME = 1, BRIGHTNESS = 2, FF_REW = 3;
接下來我們來看一下我們自定義的SurfaceViewOnGestureListener繼承 GestureDetector.SimpleOnGestureListener主要用到了
onDown(MotionEvent e)
onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)兩個方法
a.在onDown的時候把狀態設置NONE
b.判斷橫向滑動的距離大於縱向滑動的距離,就把模式賦值為快進和後退
c.在onScroll中進行狀態賦值,根據滑動的距離,如果按下的點在屏幕的左半部分就吧狀態設置為調節亮度BRIGHTNESS,如果在右半部分就是調節音量
d.各種情況調用各自的介面方法
快進和後退,我們需要知道的就是我們滑動的距離如何與視頻的長度關聯起來。
那麼咱們就可以把視頻的總長度與屏幕的總長度相比,這樣就能知道你手指滑動的距離占視頻的多少了。
我們可以通過 l = ration / mySurfaceView.getWidth();來獲得這個比例,然後用當前的進度加上指滑動的距離占視頻的長度就是要播放的視頻位置
抬起點的x坐標與按下點的X坐標所得的距離,大於0是快進,小於零是後退。
系統的音量有很多,包括通話音量值,系統鈴聲值,音樂音量值,鬧鈴音量值,等等吧。
做一下筆記以備以後用到
視頻播放我們用的是音樂音量值,同樣的道理,我們需要把音量和高度進行關聯,我們可以控制項的高度閉上最大音量得出比例後就可以知道你滑動的距離占音量的多少了。
這里有個注意點就是activity是當前的這個界面,設置的是當前的界面,離開這個界面後就不管用了。
相同的道理和滑動調節音量一樣也是獲得屏幕的高度比上最大的亮度,然後計算滑動的距離轉換成亮度是多少。(這里不多講了)
為什麼會出現黑屏,就是按Home鍵再點App回來後,只有聲音沒有圖片的問題,因為我們用的是SurfaceView,每次點擊Home鍵時會銷毀這個SurfaceView,再回來時又會重新創建,這樣我們的阿里雲播放器與SurfaceView就沒有綁定了,畫面就沒有了。
這樣我們需要 給surfaceView添加mySurfaceView.getHolder().addCallback(this);
我們在按home鍵的時候會走surfaceDestroyed。這樣,我們就可以在這里做一個標識,讓他暫停,然後再回來的時候就會走surfaceCreated,判斷標識,然後進行處理就可以了。切記一定要重新讓aliyunVodPlayer與SurfaceView進行關聯,這樣才能有畫面也有聲音。
由於我們的視頻在阿里雲的伺服器上存著,訪問阿里雲的伺服器需要臨時憑證,我們通過STS來獲取Token,但是這個Token是有時間限制,正好阿里雲的播放器給我們提供了播放視頻出錯時候的回調介面,我們只需要在這裡面進行重新請求Token就可以了
2. js android端實現視頻自動播放
在安卓手機上,使用video播放視頻有個問題,video控制項層級會永遠在頂層,不利於視頻互動H5開發,而IOS手機上不會有此問題。
<video src="http://xxx.mp4" x5-video-player-type="h5"/>
x5-video-player-type="h5" 只適用於微信瀏覽器
注意:
1.jsmpeg 需要將視頻轉為.ts的文件
先安裝ffmpeg,然後執行以下命令,將mp4格式的文件轉成 .ts(用命令行轉的才能正常播放)
ffmpeg -i video.mp4 -f mpegts -codec:v mpeg1video -codec:a mp2 out.ts(文件的路徑不太好找,建議全局搜索一下)
2.安卓上使用jsmpeg插件渲染canvas,ios上正常使用video並加入隱藏控制條等設置
3. http://hf-app.oss-cn-hangzhou.aliyuncs.com/public/html/jsmpeg.js 請使用此js,原作者的js沒有回調設置
4. https://github.com/phoboslab/jsmpeg 原作者github地址
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JSMpegPlayer</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0">
<style>
html,body{
padding: 0;
margin: 0;
}
.msg-wrap{
position: fixed;
top: 0;
left: 0;
background: #fff;
border: 1px solid #000;
}
.video-wrap{
width: 100%;
display: none;
}
</style>
</head>
<body>
<video class="video-wrap" id="video-ios" x5-playsinline webkit-playsinline playsinline src="1_BG_4s_2.mp4"></video>
<canvas class="video-wrap" id="video-android"></canvas>
<div class="msg-wrap" id="msgTxt">loading...</div>
<script src="http://hf-app.oss-cn-hangzhou.aliyuncs.com/public/html/jsmpeg.js"></script>
<script>
var msgTxt = document.getElementById('msgTxt');
var video = document.getElementById('video-ios');
var canvas = document.getElementById('video-android');
//檢測是否為非安卓瀏覽器並作處理
var check = !! navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
if(check){
msgTxt.innerHTML = "not Android mode"
video.style.display="block"
video.play()
//監聽video載入完成
video.addEventListener("loadedmetadata",function(){
msgTxt.innerHTML = "not Android mode:videoPlaying"
})
//監聽video播放結束
video.addEventListener("ended",function(){
msgTxt.innerHTML = "not Android mode:videoEnd"
})
}else{
// jsmpegPlay(canvas,'1_BG_4s_5.ts',startCallBack,playingCallBack,endCallBack)
jsmpegPlay(canvas,'out.ts',startCallBack,playingCallBack,endCallBack)
}
function jsmpegPlay(Vcanvas,vVideo,startFun,playingFun,endFun) {
var player = new JSMpeg.Player(
vVideo ,{
canvas: Vcanvas,
loop: false,
autoplay: true,
startSign: true,
startCallBack: startFun,
playingCallBack: playingFun,
endCallBack: endFun
});
}
//視頻開始播放(即解碼完成)執行
function startCallBack() {
msgTxt.innerHTML = "Android mode:videoPlaying"
canvas.style.display="block"
}
//視頻播放進度
function playingCallBack(currentTime) {
// console.log(currentTime)
}
//視頻播放完成執行
function endCallBack() {
msgTxt.innerHTML = "Android mode:videoEnd"
}
</script>
</body>
</html>
項目中遇到的坑,把使用方法記錄一下
在線演示DOMO
JSMpegPlayer
https://github.com/xxfxx/android-video-autuplay github地址,歡迎小星星~~~
3. android如何實現視頻的在線播放
vitamio
能播放絕大部分格式的視頻,但是這個有點大,裡面的so文件比較多,官方文檔上說有瘦身的方法,我試過但是沒成功,就一個用了vitamio
的小demo,打完包都10m了。在線視頻的話如果在電腦瀏覽器上能直接播放的話,用這個都可以播的,也有緩沖。我們項目也有在線視頻播放,原本也是准備用vitamio
的,但是太大了,打完包apk增加了10m,然後我就換成了universalvideoview
了,這個也可以在線播放,有緩沖效果,主要是打包後apk不大。如果你播放在線視頻功能要求高,而且不在乎apk大小的話可以使用vitamio
,如果僅想實現在線播放的話建議universalvideoview
就夠了!
4. Android實現視頻播放的幾種方式
Android提供了常見的視頻編碼,解碼機制,使用Android自帶的MediaPlayer,MediaController等類可以很方便的實現視頻播放的功能。支持的視頻格式有MP4和3GP等。這些多媒體數據可以來自於Android應用的資源文件,也可以來自於外部存儲器上的文件,甚至可以是來自於網路上的文件流。
1、MediaController+VideoView實現方式
這種方式是最簡單的實現方式。VideoView繼承了SurfaceView同時實現了MediaPlayerControl介面,MediaController則是安卓封裝的輔助控制器,帶有暫停,播放,停止,進度條等控制項。通過VideoView+MediaController可以很輕松的實現視頻播放、停止、快進、快退等功能。
布局文件如下:
使用此實現方式的步驟:
1.載入指定的視頻文件
2.建立VideoView和MediaController之間的關聯,這樣就不需要自己去控制視頻的播放、暫停等。讓MediaController控制即可。
3.VideoView獲取焦點。
2、MediaPlayer+SurfaceView+自定義控制器
雖然VideoView的實現方式很簡單,但是由於是自帶的封裝好的類,所以無論是播放器的大小、位置以及控制都不受我們控制。
這種實現方式步驟如下:
1.創建MediaPlayer對象,並讓它載入指定的視頻文件。可以是應用的資源文件、本地文件路徑、或者URL。
2.在界面布局文件中定義SurfaceView組件,並為SurfaceView的SurfaceHolder添加Callback監聽器。
3.調用MediaPlayer對象的setDisplay(SurfaceHolder sh)將所播放的視頻圖像輸出到指定的SurfaceView組件。
4.調用MediaPlayer對象的prepareAsync()或prepare()方法裝載流媒體文件
5.調用MediaPlayer對象的start()、stop()和pause()方法來控制視頻的播放。
在實現第二步之前需要先給surfaceHolder設置一個callback,callback的3個回調函數如下:
3、MediaPlayer+SurfaceView+MediaController
第二種實現方式使用的是自定義控制項,MediaPlayer+SurfaceView也可以使用系統自帶的MediaController控制器。
使用這個方式實現,布局文件只需一個SurfaceView即可,其他的控制項都交給MediaController控制器,布局文件如下:
實際過程中推薦大家使用B站的播放器ijkplayer非常好用!
5. Android短視頻滑動播放(一)
本文主要介紹採用RecyclerView配合PagerSnapHelper實現短視頻滑動播放內容。
主頁布局文件定義RecyclerView,為RecyclerView建立對應適配器。
適配器條目中添加視頻播放容器FrameLayout及封面ImageVIew.
PagerSnapHelper 結合 LinearLayoutManager 實現滑動管理,實現監聽任務。
PagerSnapHelper can help achieve a similar behavior to
ViewPager. Set both RecyclerView and the items of the RecyclerView.Adapter to have android.view.ViewGroup.LayoutParams#MATCH_PARENT height and width and then attach PagerSnapHelper to the RecyclerView using #attachToRecyclerView(RecyclerView)}.
RecyclerView管理器為LinearLayoutManager 時,默認為縱向滑動,如果想採用橫向滑動,就設置其滑動方向為RecyclerView.HORIZONTAL。同理,我們也可以這樣採用setOrientation(RecyclerView.HORIZONTAL) 方法去改變滑動方向。
為RecyclerView 設置管理器PagerLayoutManager,設置其Adapter數據內容,進行封面展示,且此時會回調onPageInitComplete()方法,進行首個視頻播放。對RecyclerView進行滑動,當頁面滑動結束後,會先回調管理器中onPageRelease()方法,此時可對進行中播放器進行停止釋放;然後,回調onPageSelected()方法,對選中頁面內容進行展示播放。
當滑動後取消時,要進行判斷當前位置,避免當前頁視頻停止或重復播放。
初始化播放器內容
開始播放視頻內容,進行播放器視圖載入
停止播放,移除視圖
例子中採用了自定義空布局的播放器繼承自GSY開源播放器,單純進行視頻播放,當然也可以採用其它的播放器餃子或者IjkPlayer等。
布局文件
簡單的滑動播放這些就完成了,例子也只是僅僅提供了實現的方法和思路,供大家進行學習參考,實際使用中可以對其進一步地進行封裝及處理,接下來也會補充一些滑動播放適配器的數據載入處理以及多布局內容展示等內容。
6. android手機如何播放mp4
android手機播放MP4視頻文件步驟如下:
工具/材料:以小米6手機為例。
1、首先打開小米6手機,點擊「小米視頻」圖標,如下圖所示;
7. Android 使用MediaCodec實現視頻的無縫切換
網路上面很多視頻播放都是利用MediaPlayer+顯示視圖(SurfaceView、TextureView)進行本地或者網路視頻的播放。那麼利用MediaCodec對視頻流進行硬解碼的小夥伴該如何在不同的控制項之間無縫切換呢?是不是TextureView的生命周期很難控制?
TextureView與SurfaceTexture構成了組合關系,可見SurfaceTexture的確是由TextureView給『包辦』了。在程序世界中,一個對象被『包辦』無非是指:
(1)這個對象什麼時候被創建?
(2)這個對象如何被創建?
(3)這個對象的產生帶來了哪些變化,或者說程序自從有了它有哪些不同?
(4)這個對象什麼時候被銷毀?
之所以對SurfaceTexture這個盯碰態對象要大動筆墨,因為它是整個顯示框架的『連接者』。
是不凱源是遇到過在播放視頻返回後台再回來,發現TextureView顯示視圖是一片黑色?監聽TextureView的生命周期你會發現,返回後台是調用了銷毀方法的。那你就會問銷毀之後豈不是有需要重新創建?重新創建會引來更多的問題,解碼去也需要重新初始化。所以我們只能另尋他法,下面方法就是無縫切換的核心部吵臘分。
在銷毀方法中我們注意,有一個返回參數。官方的解釋如下
現在恍然大悟了吧,我們在銷毀的時候返回false,並保存SurfaceTexture對象,然後從後台返回界面的時候在onSurfaceTextureAvailable()方法中,調用setSurfaceTexture(mSurfaceTexture)方法,這樣就會恢復之前的畫面了。
使用ItemTouchHelper輕松實現RecyclerView拖拽排序和滑動刪除
源碼地址: https://github.com/chezi008/VideoSurveillance