固然能夠, H5火了這麼久,涵蓋了各個方面的技術。php
對於視頻錄製,可使用強大的webRTC(Web Real-Time Communication)是一個支持網頁瀏覽器進行實時語音對話或視頻對話的技術,缺點是隻在PC的chrome上支持較好,移動端支持不太理想。html
對於視頻播放,可使用HLS(HTTP Live Streaming)協議播放直播流,ios和android都自然支持這種協議,配置簡單,直接使用video標籤便可。html5
webRTC兼容性:android
video標籤播放hls協議視頻:ios
<video controls autoplay> <source src="http://10.66.69.77:8080/hls/mystream.m3u8" type="application/vnd.apple.mpegurl" /> <p class="warning">Your browser does not support HTML5 video.</p> </video>
當簡單講就是把整個流分紅一個個小的基於HTTP的文件來下載,每次只下載一些,前面提到了用於H5播放直播視頻時引入的一個.m3u8的文件,這個文件就是基於HLS協議,存放視頻流元數據的文件。nginx
每個.m3u8文件,分別對應若干個ts文件,這些ts文件纔是真正存放視頻的數據,m3u8文件只是存放了一些ts文件的配置信息和相關路徑,當視頻播放時,.m3u8是動態改變的,video標籤會解析這個文件,並找到對應的ts文件來播放,因此通常爲了加快速度,.m3u8放在web服務器上,ts文件放在cdn上。git
.m3u8文件,其實就是以UTF-8編碼的m3u文件,這個文件自己不能播放,只是存放了播放信息的文本文件:github
#EXTM3U m3u文件頭
#EXT-X-MEDIA-SEQUENCE 第一個TS分片的序列號
#EXT-X-TARGETDURATION 每一個分片TS的最大的時長
#EXT-X-ALLOW-CACHE 是否容許cache
#EXT-X-ENDLIST m3u8文件結束符
#EXTINF 指定每一個媒體段(ts)的持續時間(秒),僅對其後面的URI有效
mystream-12.ts
ts文件:web
HLS的請求流程是:
1 http請求m3u8的url
2 服務端返回一個m3u8的播放列表,這個播放列表是實時跟新的,通常一次給出3段數據的url
3 客戶端解析m3u8的播放列表,再按序請求每一段的url,獲取ts數據流chrome
簡單流程:
當咱們知道hls協議是將直播流分紅一段一段的小段視頻去下載播放的,因此假設列表裏面的包含5個TS文件,每一個TS文件包含5秒的視頻內容,那麼總體的延遲就是25秒。由於當你看到這些視頻時,主播已經將視頻錄製好上傳上去了,因此時這樣產生的延遲。固然能夠縮短列表的長度和單個TS文件的大小來下降延遲,極致來講能夠縮減列表長度爲1,而且TS的時長爲1s,可是這樣會形成請求次數增長,增大服務器壓力,當網速慢時回形成更多的緩衝,因此蘋果官方推薦的ts時長時10s,因此這樣就會大改有30s的延遲。參考資料:https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StreamingMediaGuide/FrequentlyAskedQuestions/FrequentlyAskedQuestions.html
當視頻直播可大體分爲:
1 視頻錄製端:通常是電腦上的音視頻輸入設備或者手機端的攝像頭或者麥克風,目前已移動端的手機視頻爲主。
2 視頻播放端:能夠是電腦上的播放器,手機端的native播放器,還有就是h5的video標籤等,目前仍是已手機端的native播放器爲主。
3 視頻服務器端:通常是一臺nginx服務器,用來接受視頻錄製端提供的視頻源,同時提供給視頻播放端流服務。
簡單流程:
當首先明確幾個概念:
視頻編碼:所謂視頻編碼就是指經過特定的壓縮技術,將某個視頻格式的文件轉換成另外一種視頻格式文件的方式,咱們使用的iphone錄製的視頻,必需要通過編碼,上傳,解碼,才能真正的在用戶端的播放器裏播放。
編解碼標準:視頻流傳輸中最爲重要的編解碼標準有國際電聯的H.26一、H.26三、H.264,其中HLS協議支持H.264格式的編碼。
音頻編碼:同視頻編碼相似,將原始的音頻流按照必定的標準進行編碼,上傳,解碼,同時在播放器裏播放,固然音頻也有許多編碼標準,例如PCM編碼,WMA編碼,AAC編碼等等,這裏咱們HLS協議支持的音頻編碼方式是AAC編碼。
下面將利用ios上的攝像頭,進行音視頻的數據採集,主要分爲如下幾個步驟:
1 音視頻的採集,ios中,利用AVCaptureSession和AVCaptureDevice能夠採集到原始的音視頻數據流。
2 對視頻進行H264編碼,對音頻進行AAC編碼,在ios中分別有已經封裝好的編碼庫來實現對音視頻的編碼。
3 對編碼後的音、視頻數據進行組裝封包;
4 創建RTMP鏈接並上推到服務端。
ps:因爲編碼庫大多使用c語言編寫,須要本身使用時編譯,對於ios,可使用已經編譯好的編碼庫。
x264編碼:https://github.com/kewlbear/x264-ios
faac編碼:https://github.com/fflydev/faac-ios-build
ffmpeg編碼:https://github.com/kewlbear/FFmpeg-iOS-build-script
關於若是想給視頻增長一些特殊效果,例如增長濾鏡等,通常在編碼前給使用濾鏡庫,可是這樣也會形成一些耗時,致使上傳視頻數據有必定延時。
簡單流程:
和以前的x264同樣,ffmpeg其實也是一套編碼庫,相似的還有Xvid,Xvid是基於MPEG4協議的編解碼器,x264是基於H.264協議的編碼器,ffmpeg集合了各類音頻,視頻編解碼協議,經過設置參數能夠完成基於MPEG4,H.264等協議的編解碼,demo這裏使用的是x264編碼庫。
Real Time Messaging Protocol(簡稱 RTMP)是 Macromedia 開發的一套視頻直播協議,如今屬於 Adobe。和HLS同樣均可以應用於視頻直播,區別是RTMP基於flash沒法在ios的瀏覽器裏播放,可是實時性比HLS要好。因此通常使用這種協議來上傳視頻流,也就是視頻流推送到服務器。
這裏列舉一下hls和rtmp對比:
簡所謂推流,就是將咱們已經編碼好的音視頻數據發往視頻流服務器中,通常經常使用的是使用rtmp推流,可使用第三方庫librtmp-iOS進行推流,librtmp封裝了一些核心的api供使用者調用,若是以爲麻煩,可使用現成的ios視頻推流sdk,也是基於rtmp的,https://github.com/runner365/LiveVideoCoreSDK
簡簡單的推流服務器搭建,因爲咱們上傳的視頻流都是基於rtmp協議的,因此服務器也必需要支持rtmp才行,大概須要如下幾個步驟:
1 安裝一臺nginx服務器。
2 安裝nginx的rtmp擴展,目前使用比較多的是https://github.com/arut/nginx-rtmp-module
3 配置nginx的conf文件:
rtmp {
server {
listen 1935; #監聽的端口
chunk_size 4000;
application hls { #rtmp推流請求路徑
live on;
hls on;
hls_path /usr/local/var/www/hls;
hls_fragment 5s;
}
}
}
4 重啓nginx,將rtmp的推流地址寫爲rtmp://ip:1935/hls/mystream,其中hls_path表示生成的.m3u8和ts文件所存放的地址,hls_fragment表示切片時長,mysteam表示一個實例,即未來要生成的文件名能夠先本身隨便設置一個。更多配置能夠參考:https://github.com/arut/nginx-rtmp-module/wiki/
根據以上步驟基本上已經實現了一個支持rtmp的視頻服務器了。
簡單來講,直接使用video標籤便可播放hls協議的直播視頻:
<video autoplay webkit-playsinline> <source src="http://10.66.69.77:8080/hls/mystream.m3u8" type="application/vnd.apple.mpegurl" /> <p class="warning">Your browser does not support HTML5 video.</p> </video>
須要注意的是,給video標籤增長webkit-playsinline屬性,這個屬性是爲了讓video視頻在ios的uiwebview裏面能夠不全屏播放,默認ios會全屏播放視頻,須要給uiwebview設置allowsInlineMediaPlayback=YES。業界比較成熟的videojs,能夠根據不一樣平臺選擇不一樣的策略,例如ios使用video標籤,pc使用flash等。
簡根據以上步驟,筆者寫了一個demo,從實現ios視頻錄製,採集,上傳,nginx服務器下發直播流,h5頁面播放直播視頻者一整套流程,總結出如下幾點比較坑的地方:
1 在使用AVCaptureSession進行採集視頻時,須要實現AVCaptureVideoDataOutputSampleBufferDelegate協議,同時在- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection捕獲到視頻流,要注意的是didOutputSampleBuffer這個方法不是didDropSampleBuffer方法,後者只會觸發一次,當時開始寫的是didDropSampleBuffer方法,差了半天才發現方法調用錯了。
2 在使用rtmp推流時,rmtp地址要以rtmp://開頭,ip地址要寫實際ip地址,不要寫成localhost,同時要加上端口號,由於手機端上傳時是沒法識別localhost的。
這裏後續會補充上一些坑點,有的須要貼代碼,這裏先列這麼多。
目前,騰訊雲,百度雲,阿里雲都已經有了基於視頻直播的解決方案,從視頻錄製到視頻播放,推流,都有一系列的sdk可使用,缺點就是須要收費,若是能夠的話,本身實現一套也並非難事哈。