HLS-Demo IOS 视屏直播样例
from: https://github.com/yangchao0033/HLS-Demo/blob/master/README.md
demo簡介:如果覺得文章有用的話,請讀者在github上點個star:grin:,或者在簡書上點個贊。Demo配置原理:1、 需要導入第三方庫:ASIHttpRequest,CocoaHTTPServer,m3u8(其中ASI用于網絡請求,CocoaHTTPServer用于在ios端搭建服務器使用,m3u8是用來對返回的索引文件進行解析的)ASI配置注意事項MRC報錯處理2、導入系統庫:libsqlite3.dylib、libz.dylib、libxml2.dylib、CoreTelephony.framework、SystemConfiguration.framework、MobileCoreServices.framework、Security.framework、CFNetwork.framework、MediaPlayer.framework3、添加頭文件YCHLS-Demo.h4、demo介紹 demo樣式播放:直接播放在線的直播鏈接,是由系統的MPMoviePlayer完成的,它自帶解析HLS直播鏈的功能。下載:遵循HLS的協議,通過索引文件的資源路徑下載相關的視頻切片并保存到手機本地。播放本地視頻:使用下載好的視頻文件片段進行連續播放。清除緩存:刪除下載好的視頻片段原理:通過ASI請求鏈接,通過m3u8庫解析返回的m3u8索引文件。再通過ASI下載解析出的視頻資源地址,仿照HLS中文件存儲路徑存儲。利用CocoaHTTPServer在iOS端搭建本地服務器,并開啟服務,端口號為:12345(高位端口即可)。配置服務器路徑與步驟二存儲路徑一致。設置播放器直播鏈接為本地服務器地址,直接播放,由于播放器遵守HLS協議,所以能夠解析我們之前使用HLS協議搭建的本地服務器地址。點擊在線播放,校驗是否與本地播放效果一致。HLS協議文件存儲結構上面是HLS中服務器存儲視頻文件切片和索引文件的結構圖整個操作流程就是:先點擊下載,通過解析m3u8的第三方庫解析資源。(m3u8的那個庫只能解析一種特定格式的m3u8文件,代碼里會有標注)點擊播放本地視頻播放下載好的資源。點擊播放是用來預覽直播的效果,與整個流程無關。其中進度條用來顯示下載進度。總結: 整個Demo并不只是讓我們搭建一個Hls服務器或者一個支持Hls的播放器。目的在于了解Hls協議的具體實現,以及服務器端的一些物理架構。通過Demo的學習,可以詳細的了解Hls直播具體的實現流程。部分源碼貼出:開啟本地服務器:- (void)openHttpServer{ self.httpServer = [[HTTPServer alloc] init]; [self.httpServer setType:@"_http._tcp."]; // 設置服務類型 [self.httpServer setPort:12345]; // 設置服務器端口 // 獲取本地Library/Cache路徑下downloads路徑 NSString *webPath = [kLibraryCache stringByAppendingPathComponent:kPathDownload]; NSLog(@"-------------\nSetting document root: %@\n", webPath); // 設置服務器路徑 [self.httpServer setDocumentRoot:webPath]; NSError *error; if(![self.httpServer start:&error]) { NSLog(@"-------------\nError starting HTTP Server: %@\n", error); }視頻下載:- (IBAction)downloadStreamingMedia:(id)sender { UIButton *downloadButton = sender; // 獲取本地Library/Cache路徑 NSString *localDownloadsPath = [kLibraryCache stringByAppendingPathComponent:kPathDownload]; // 獲取視頻本地路徑 NSString *filePath = [localDownloadsPath stringByAppendingPathComponent:@"XNjUxMTE4NDAw/movie.m3u8"]; NSFileManager *fileManager = [NSFileManager defaultManager]; // 判斷視頻是否緩存完成,如果完成則播放本地緩存 if ([fileManager fileExistsAtPath:filePath]) { [downloadButton setTitle:@"已完成" forState:UIControlStateNormal]; downloadButton.enabled = NO; }else{ M3U8Handler *handler = [[M3U8Handler alloc] init]; handler.delegate = self; // 解析m3u8視頻地址 [handler praseUrl:TEST_HLS_URL]; // 開啟網絡指示器 [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; }}播放本地視頻:- (IBAction)playVideoFromLocal:(id)sender { NSString * playurl = [NSString stringWithFormat:@"http://127.0.0.1:12345/XNjUxMTE4NDAw/movie.m3u8"]; NSLog(@"本地視頻地址-----%@", playurl); // 獲取本地Library/Cache路徑 NSString *localDownloadsPath = [kLibraryCache stringByAppendingPathComponent:kPathDownload]; // 獲取視頻本地路徑 NSString *filePath = [localDownloadsPath stringByAppendingPathComponent:@"XNjUxMTE4NDAw/movie.m3u8"]; NSFileManager *fileManager = [NSFileManager defaultManager]; // 判斷視頻是否緩存完成,如果完成則播放本地緩存 if ([fileManager fileExistsAtPath:filePath]) { MPMoviePlayerViewController *playerViewController =[[MPMoviePlayerViewController alloc]initWithContentURL:[NSURL URLWithString: playurl]]; [self presentMoviePlayerViewControllerAnimated:playerViewController]; } else{ UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Sorry" message:@"當前視頻未緩存" delegate:self cancelButtonTitle:@"確定" otherButtonTitles:nil, nil]; [alertView show]; }}播放在線視頻- (IBAction)playLiveStreaming { NSURL *url = [[NSURL alloc] initWithString:TEST_HLS_URL]; MPMoviePlayerViewController *player = [[MPMoviePlayerViewController alloc] initWithContentURL:url]; [self presentMoviePlayerViewControllerAnimated:player];}當然,《羋月傳》的直播鏈接到現在也還沒有找到,各位熱心讀者如果有鏈接的話可以留言給我,也讓這篇文章能實至名歸了,能對得文章的標題了:grin:。HTTP Live Streaming (HLS)蘋果官方對于視頻直播服務提出了 HLS 解決方案,該方案主要適用范圍在于:使用 iPhone 、iPod touch、 iPad 以及 Apple TV 進行流媒體直播功能。(MAC 也能用)不使用特殊的服務軟件進行流媒體直播。需要通過加密和鑒定(authentication)的視頻點播服務。首先,需要大家先對 HLS 的概念進行預覽。HLS 的目的在于,讓用戶可以在蘋果設備(包括MAC OS X)上通過普通的網絡服務完成流媒體的播放。 HLS 同時支持流媒體的實時廣播和點播服務。同時也支持不同 bit 速率的多個備用流(平時根據當前網速去自適應視頻的清晰度),這樣客戶端也好根據當前網絡的帶寬去只能調整當前使用的視頻流。安全方面,HLS 提供了通過 HTTPS 加密對媒體文件進行加密 并 對用戶進行驗證,允許視頻發布者去保護自己的網絡。HLS 是蘋果公司QuickTime X和iPhone軟件系統的一部分。它的工作原理是把整個流分成一個個小的基于HTTP的文件來下載,每次只下載一些。當媒體流正在播放時,客戶端可以選擇從許多不同的備用源中以不同的速率下載同樣的資源,允許流媒體會話適應不同的數據速率。在開始一個流媒體會話時,客戶端會下載一個包含元數據的extended M3U (m3u8) playlist文件,用于尋找可用的媒體流。HLS只請求基本的HTTP報文,與實時傳輸協議(RTP)不同,HLS可以穿過任何允許HTTP數據通過的防火墻或者代理服務器。它也很容易使用內容分發網絡來傳輸媒體流。蘋果對于自家的 HLS 推廣也是采取了強硬措施,當你的直播內容持續十分鐘 或者每五分鐘內超過 5 MB 大小時,你的 APP 直播服務必須采用 HLS 架構,否則不允許上架。(詳情)相關服務支持環境 (重要組成)Adobe Flash Media Server:從4.5開始支持HLS、Protected HLS(PHLS)。5.0改名為Adobe Media ServerFlussonic Media Server:2009年1月21日,版本3.0開始支持VOD、HLS、時移等。RealNetworks的 Helix Universal Server :2010年4月,版本15.0開始支持iPhone, iPad和iPod的HTTP直播、點播H.264/AAC內容,最新更新在2012年11月。微軟的IIS Media Services:從4.0開始支持HLS。Nginx RTMP Module:支持直播模式的HLS。Nimber StreamerUnified Streaming PlatformVLC Media Player:從2.0開始支持直播和點播HLS。Wowza Media Server:2009年12月9日發布2.0,開始全面支持HLS。VODOBOX Live Server:始支持HLS。Gstreamill是一個支持hls輸出的,基于gstreamer的實時編碼器。相關客戶端支持環境iOS從3.0開始成為標準功能。Adobe Flash Player從11.0開始支持HLS。Google的Android自Honeycomb(3.0)開始支持HLS。VODOBOX HLS Player (Android,iOS, Adobe Flash Player)JW Player (Adobe Flash player)Windows 10 的 EDGE 瀏覽器開始支持HLS。HLS架構其中輸入視頻源是由攝像機預先錄制好的。之后這些源會被編碼 MPEG-4(H.264 video 和 AAC audio)格式然后用硬件打包到 MPEG-2 的傳輸流中。MPEG-2 傳輸流會被分散為小片段然后保存為一個或多個系列的 .ts 格式的媒體文件。這個過程需要借助編碼工具來完成,比如 Apple stream segmenter。純音頻會被編碼為一些音頻小片段,通常為 ADTS頭的AAC、MP3、或者 AC-3格式。同時上面提到的那個切片器(segmenter)也會創建一個索引文件,通常會包含這些媒體文件的一個列表,也能包含元數據。他一般都是一個.M38U 個hi的列表。列表元素會關聯一個 URL 用于客戶端訪問。然后按序去請求這些 URL。服務器端服務端可以采用硬件編碼和軟件編碼兩種形式,其功能都是按照上文描述的規則對現有的媒體文件進行切片并使用索引文件進行管理。而軟件切片通常會使用 Apple 公司提供的工具或者第三方的集成工具。媒體編碼媒體編碼器獲取到音視頻設備的實時信號,將其編碼后壓縮用于傳輸。而編碼格式必須配置為客戶端所支持的格式,比如 H.264 視頻和HE-AAC 音頻。當前,支持 用于視頻的 MPEG-2 傳輸流和 純音頻 MPEG 基本流。編碼器通過本地網絡將 MPEG-2 傳輸流分發出去,送到流切片器那里。標準傳輸流和壓縮傳輸流無法混合使用。傳輸流可以被打包成很多種不同的壓縮格式,這里有兩個表詳細列舉了支持的壓縮格式類型。Audio TechnologiesVedio Technologies[重點]在編碼中圖,不要修改視頻編碼器的設置,比如視頻大小或者編碼解碼器類型。如果避免不了,那修改動作必須發生在一個片段邊界。并且需要早之后相連的片段上用 EXT-X-DISCONTINUITY 進行標記。流切片器流切片器(通常是一個軟件)會通過本地網絡從上面的媒體編碼器中讀取數據,然后將著這些數據一組相等時間間隔的 小 媒體文件。雖然沒一個片段都是一個單獨的文件,但是他們的來源是一個連續的流,切完照樣可以無縫重構回去。切片器在切片同時會創建一個索引文件,索引文件會包含這些切片文件的引用。每當一個切片文件生成后,索引文件都會進行更新。索引用于追蹤切片文件的有效性和定位切片文件的位置。切片器同時也可以對你的媒體片段進行加密并且創建一個密鑰文件作為整個過程的一部分。文件切片器(相對于上面的流切片器)如果已近有編碼后的文件(而不是編碼流),你可以使用文件切片器,通過它對編碼后的媒體文件進行 MPEG-2 流的封裝并且將它們分割為等長度的小片段。切片器允許你使用已經存在的音視頻庫用于 HLS 服務。它和流切片器的功能相似,但是處理的源從流替換流為了文件。媒體片段文件媒體片段是由切片器生成的,基于編碼后的媒體源,并且是由一系列的 .ts 格式的文件組成,其中包含了你想通過 MPEG-2 傳送流攜帶的 H.264 視頻 和 AAC /MP3/AC-3 音頻。對于純音頻的廣播,切片器可以生產 MPEG 基礎音頻流,其中包含了 ADTS頭的AAC、MP3、或者AC3等音頻。索引文件(PlayLists)通常由切片器附帶生成,保存為 .M3U8 格式,.m3u 一般用于 MP3 音頻的索引文件。 Note如果你的擴展名是.m3u,并且系統支持.mp3文件,那客戶的軟件可能要與典型的 MP3 playList 保持一致來完成 流網絡音頻的播放。下面是一個 .M3U8 的 playlist 文件樣例,其中包含了三個沒有加密的十秒鐘的媒體文件:#EXT-X-VERSION:3#EXTM3U#EXT-X-TARGETDURATION:10#EXT-X-MEDIA-SEQUENCE:1# Old-style integer duration; avoid for newer clients.#EXTINF:10,http://media.example.com/segment0.ts# New-style floating-point duration; use for modern clients.#EXTINF:10.0,http://media.example.com/segment1.ts#EXTINF:9.5,http://media.example.com/segment2.ts#EXT-X-ENDLIST為了更精確,你可以在 version 3 或者之后的協議版本中使用 float 數來標記媒體片段的時長,并且要明確寫明版本號,如果沒有版本號,則必須與 version 1 協議保持一致。你可以使用官方提供的切片器去生產各種各樣的 playlist 索引文件,詳見 媒體文件切片器分布式部分分布式系統是一個網絡服務或者一個網絡緩存系統,用于通過 HTTP 向客戶端發送媒體文件和索引文件。不用自定義模塊發送內容。通常僅僅需要很簡單的網絡配置即可使用。而且這種配置一般就是限制指定 .M38U 文件和 .ts 文件的 MIME 類型。詳見 部署 HTTP Live Streaming客戶端部分客戶端開始時回去抓取 索引文件(.m3u8/.m3u),其中用URL來標記不同的流。索引文件可以指定可用媒體文件的位置,解密的密鑰,以及任何可以切換的流。對于選中的流,客戶端會有序的下載每一個可獲得的文件。每一個文件都包含流中的連環碎片。一旦下載到足夠量的數據,客戶端會開始向用戶展示重新裝配好的媒體資源。客戶端負責抓取任何解密密鑰,認證或者展示一個用于認證的界面,之后再解密需要的文件。這個過程會一直持續知道出現 結束標記 #EXT-X-ENDLIST。如果結束標記不出現,該索引就是用于持續廣播的。客戶端會定期的加載一些新的索引文件。客戶端會從新更新的索引文件中去查找加密密鑰并且將關聯的URL加入到請求隊列中去。HLS 的使用使用 HLS 需要使用一些工具,當然大部分工具都是服務器端使用的,這里簡單了解一下就行,包括 media stream segmenter, a media file segmenter, a stream validator, an id3 tag generator, a variant playlist generator.這些工具用英文注明是為了當你在蘋果開發中心中尋找時方便一些。會話模式通常包含 Live 和 VOD (點播)兩種點播VOD的特點就是可以獲取到一個靜態的索引文件,其中那個包含一套完整的資源文件地址。這種模式允許客戶端訪問全部節目。VOD點播擁有先進的下載技術,包括加密認證技術和動態切換文件傳輸速率的功能(通常用于不同分辨率視頻之間的切換)。Live 會話就是實時事件的錄制展示。它的索引文件一直處于動態變化的,你需要不斷的更新索引文件 playlist 然后移除舊的索引文件。這種類型通過向索引文件添加媒體地址可以很容易的轉化為VOD類型。在轉化時不要移除原來舊的源,而是通過添加一個 #ET-X-ENDLIST 標記來終止實時事件。轉化時如果你的索引文件中包含 EXT-X-PLAYLIST-TYPE 標簽,你需要將值從 EVENT 改為 VOD。ps:自己抓了一個直播的源,從索引中看到的結果是第一次回抓到代表不同帶寬的playList(抓取地址:http://dlhls.cdn.zhanqi.tv/zqlive/34338_PVMT5.m3u8)#EXTM3U#EXT-X-VERSION:3#EXT-X-STREAM-INF:PROGRAM-ID=1,PUBLISHEDTIME=1453914627,CURRENTTIME=1454056509,BANDWIDTH=700000,RESOLUTION=1280x72034338_PVMT5_700/index.m3u8?Dnion_vsnae=34338_PVMT5#EXT-X-STREAM-INF:PROGRAM-ID=1,PUBLISHEDTIME=1453914627,CURRENTTIME=1454056535,BANDWIDTH=40000034338_PVMT5_400/index.m3u8?Dnion_vsnae=34338_PVMT5#EXT-X-STREAM-INF:PROGRAM-ID=1,PUBLISHEDTIME=1453914627,CURRENTTIME=1454056535,BANDWIDTH=102400034338_PVMT5_1024/index.m3u8?Dnion_vsnae=34338_PVMT5這里面的鏈接不是視頻源URL,而是一個用于流切換的主索(下面會有介紹)引我猜想是需要對上一次的抓包地址做一個拼接組合的結果就是:http://dlhls.cdn.zhanqi.tv/zqlive/34338_PVMT5_1024/index.m3u8?Dnion_vsnae=34338_PVMT5(純屬小學智力題:joy:。。。)將它作為抓取地址再一次的結果#EXTM3U#EXT-X-VERSION:3#EXT-X-MEDIA-SEQUENCE:134611#EXT-X-TARGETDURATION:10#EXTINF:9.960,35/1454056634183_128883.ts?Dnion_vsnae=34338_PVMT5#EXTINF:9.960,35/1454056644149_128892.ts?Dnion_vsnae=34338_PVMT5#EXTINF:9.960,35/1454056654075_128901.ts?Dnion_vsnae=34338_PVMT5同理,繼續向下抓:(拼接地址:http://dlhls.cdn.zhanqi.tv/zqlive/34338_PVMT5_1024/index.m3u8?Dnion_vsnae=34338_PVMT5/35/1454056634183_128883.ts?Dnion_vsnae=34338_PVMT5/36/1454059958599_131904.ts?Dnion_vsnae=34338_PVMT5) 抓取結果:#EXTM3U#EXT-X-VERSION:3#EXT-X-MEDIA-SEQUENCE:134984#EXT-X-TARGETDURATION:10#EXTINF:9.280,36/1454059988579_131931.ts?Dnion_vsnae=34338_PVMT5#EXTINF:9.960,36/1454059998012_131940.ts?Dnion_vsnae=34338_PVMT5#EXTINF:9.960,36/1454060007871_131949.ts?Dnion_vsnae=34338_PVMT5相比于第二次又獲取了一個片段的索引,而且只要是第二次之后,資源地址都會包含 .ts,說明里面是有視頻資源URL的,不過具體的截取方法還是需要查看前面提到的IETF的那套標準的HLS的協議,利用里面的協議應該就能拼接出完整的資源路徑進行下載。反正我用蘋果自帶的MPMoviePlayerController直接播放是沒有問題的,的確是直播資源。與之前說過的蘋果自帶的QuickTime類似,都遵循了HLS協議用于流媒體播放。而每次通過拼接獲取下一次的索引,符合協議里提到的不斷的更替索引的動作。內容加密如果內容需要加密,你可以在索引文件中找到密鑰的相關信息。如果索引文件中包含了一個密鑰文件的信息,那接下來的媒體文件就必須使用密鑰解密后才能解密打開了。當前的 HLS 支持使用16-octet 類型密鑰的 AES-128 加密。這個密鑰格式是一個由著在二進制格式中的16個八進制組的數組打包而成的。加密的配置模式通常包含三種: 1. 模式一:允許你在磁盤上制定一個密鑰文件路徑,切片器會在索引文件中插入存在的密鑰文件的 URL。所有的媒體文件都使用該密鑰進行加密。 2. 模式二:切片器會生成一個隨機密鑰文件,將它保存在指定的路徑,并在索引文件中引用它。所有的媒體文件都會使用這個隨機密鑰進行加密。 3. 模式三:每 n 個片段生成一個隨機密鑰文件,并保存到指定的位置,在索引中引用它。這個模式的密鑰處于輪流加密狀態。每一組 n 個片段文件會使用不同的密鑰加密。理論上,不定期的碎片個數生成密鑰會更安全,但是定期的生成密鑰不會對系統的性能產生太大的影響。你可以通過 HTTP 或者 HTTPS 提供密鑰。也可以選擇使用你自己的基于會話的認證安排去保護發送的key。更多詳情可以參考 通過 HTTPS 安全的提供預約密鑰文件需要一個 initialization vector (IV) 去解碼加密的媒體文件。IV 可以隨著密鑰定期的改變。緩存和發送協議HTTPS通常用于發送密鑰,同時,他也可以用于平時的媒體片段和索引文件的傳輸。但是當擴展性更重要時,這樣做是不推薦的。HTTPS 請求通常都是繞開 web 服務緩存,導致所有內容請求都是通過你的服務進行轉發,這有悖于分布式網絡連接系統的目的。處于這個原因,確保你發送的網絡內容都明白非常重要。當處于實況廣播模式時索引文件不會像分片媒體文件一樣長時間的被緩存,他會動態不停地變化。流切換如果你的視頻具備流切換功能,這對于用戶來說是一個非常棒的體驗,處于不同的帶寬、不同的網速播放不同清晰度的視頻流,這樣只能的流切換可以保證用戶感覺到非常流暢的觀影體驗,同時不同的設備也可以作為選擇的條件,比如視網膜屏可以再網速良好的情況下播放清晰度更高的視頻流。這種功能的實現在于,索引文件的特殊結構流切換索引文件結構有別于普通的索引,具備流熱切換的索引通常由主索引和鏈接不同帶寬速率的資源的子索引,由子索引再鏈接對引得.ts視頻切片文件。其中主索引只下載一次,而子索引則會不停定期的下載,通常會先使用主索引中列出的第一個子索引,之后才會根據當時的網絡情況去動態切換合適的流。客戶端會在任何時間去切換不同的流。比如連入或者退出一個 wifi 熱點。所有的切換都會使用相同的音頻文件(換音頻沒多大意思相對于視頻)在不同的流之間平滑的進行切換。 這一套不同速率的視頻都是有工具生成的,使用variantplaylistcreator 工具并且為 mediafilesegmenter 或者 mediastreamsegmenter 指定 -generate-variant-playlist 選項,詳情參考 下載工具概念先寫到這吧,前面的知識夠對HSL的整體結構做一個初步的了解。下面貼一份針對 HLS 測試的一份源碼,下載地址:https://github.com/yangchao0033/HLS-Demo隨后的博客會對代碼進行解釋參考文獻:蘋果官方文檔維基百科http://my.oschina.net/CgShare/blog/302303http://blog.csdn.net/woaifen3344/article/details/40837803
總結
以上是生活随笔為你收集整理的HLS-Demo IOS 视屏直播样例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用google开源框架Exoplaye
- 下一篇: iOS流媒体直播整个框架介绍(HLS、R